Skip to content

Commit 8b560ab

Browse files
Copilotmballance
andcommitted
Implement conversion from MemUCIS to SqliteUCIS for merge operations
Co-authored-by: mballance <1340805+mballance@users.noreply.github.com>
1 parent cc13f19 commit 8b560ab

3 files changed

Lines changed: 298 additions & 87 deletions

File tree

src/ucis/sqlite/sqlite_ucis.py

Lines changed: 136 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,126 @@
4141
from ucis.sqlite import schema_manager
4242

4343

44+
def _convert_to_sqlite(source_ucis: UCIS) -> 'SqliteUCIS':
45+
"""
46+
Convert a non-SQLite UCIS database to SqliteUCIS.
47+
48+
This creates a temporary in-memory SQLite database and copies all
49+
scopes, coverage items, and history nodes from the source.
50+
51+
Args:
52+
source_ucis: The source UCIS database to convert
53+
54+
Returns:
55+
A SqliteUCIS instance with the copied data
56+
"""
57+
# Create in-memory SQLite database
58+
sqlite_db = SqliteUCIS()
59+
60+
# Copy metadata
61+
sqlite_db.setWrittenBy(source_ucis.getWrittenBy())
62+
sqlite_db.setWrittenTime(source_ucis.getWrittenTime())
63+
64+
# Copy file handles
65+
file_handle_map = {}
66+
if hasattr(source_ucis, 'file_handle_m'):
67+
for filename, src_fh in source_ucis.file_handle_m.items():
68+
file_handle_map[filename] = sqlite_db.createFileHandle(filename, None)
69+
70+
# Copy history nodes
71+
for src_hist in source_ucis.historyNodes(-1):
72+
_copy_history_node(src_hist, sqlite_db, None)
73+
74+
# Copy scopes recursively from root
75+
_copy_scope_recursive(source_ucis, sqlite_db, file_handle_map)
76+
77+
return sqlite_db
78+
79+
80+
def _copy_history_node(src_node, dst_db: 'SqliteUCIS', parent):
81+
"""Copy a history node from source to destination database"""
82+
dst_node = dst_db.createHistoryNode(
83+
parent,
84+
src_node.getLogicalName(),
85+
src_node.getPhysicalName(),
86+
src_node.getKind()
87+
)
88+
89+
# Copy metadata
90+
if hasattr(src_node, 'getTestStatus'):
91+
dst_node.setTestStatus(src_node.getTestStatus())
92+
if hasattr(src_node, 'getSeed'):
93+
dst_node.setSeed(src_node.getSeed())
94+
if hasattr(src_node, 'getCmd'):
95+
dst_node.setCmd(src_node.getCmd())
96+
if hasattr(src_node, 'getCpuTime'):
97+
dst_node.setCpuTime(src_node.getCpuTime())
98+
if hasattr(src_node, 'getDate'):
99+
dst_node.setDate(src_node.getDate())
100+
if hasattr(src_node, 'getUserName'):
101+
dst_node.setUserName(src_node.getUserName())
102+
103+
return dst_node
104+
105+
106+
def _copy_scope_recursive(src_scope, dst_scope, file_handle_map):
107+
"""Recursively copy scopes and coverage items from source to destination"""
108+
109+
# Copy coverage items for this scope
110+
for src_cover in src_scope.coverItems(-1):
111+
# Map source file handle to destination file handle
112+
src_info = src_cover.getSourceInfo()
113+
dst_info = src_info
114+
if src_info and src_info.file and hasattr(src_info.file, 'filename'):
115+
filename = src_info.file.filename
116+
if filename in file_handle_map:
117+
from ucis.source_info import SourceInfo
118+
dst_info = SourceInfo(
119+
file_handle_map[filename],
120+
src_info.line,
121+
src_info.token
122+
)
123+
124+
dst_scope.createNextCover(
125+
src_cover.getName(),
126+
src_cover.getCoverData(),
127+
dst_info
128+
)
129+
130+
# Recursively copy child scopes
131+
for src_child in src_scope.scopes(-1):
132+
# Map source file handle to destination file handle
133+
src_info = src_child.getSourceInfo()
134+
dst_info = src_info
135+
if src_info and src_info.file and hasattr(src_info.file, 'filename'):
136+
filename = src_info.file.filename
137+
if filename in file_handle_map:
138+
from ucis.source_info import SourceInfo
139+
dst_info = SourceInfo(
140+
file_handle_map[filename],
141+
src_info.line,
142+
src_info.token
143+
)
144+
145+
# Get flags - MemScope stores it in m_flags but doesn't implement getFlags()
146+
try:
147+
flags = src_child.getFlags()
148+
except (NotImplementedError, AttributeError):
149+
flags = getattr(src_child, 'm_flags', 0)
150+
151+
dst_child = dst_scope.createScope(
152+
src_child.getScopeName(),
153+
dst_info,
154+
src_child.getWeight(),
155+
0, # source
156+
src_child.getScopeType(),
157+
flags
158+
)
159+
160+
# Recursively copy children
161+
_copy_scope_recursive(src_child, dst_child, file_handle_map)
162+
163+
44164
class SqliteUCIS(SqliteScope, UCIS):
45165
"""SQLite-backed UCIS database"""
46166

@@ -307,13 +427,26 @@ def merge(self, source_ucis, create_history: bool = True):
307427
Merge coverage from another UCIS database
308428
309429
Args:
310-
source_ucis: Source SqliteUCIS database to merge from
430+
source_ucis: Source UCIS database to merge from (can be any UCIS type)
311431
create_history: Whether to create merge history node
312432
313433
Returns:
314434
MergeStats object with statistics
315435
"""
316436
from ucis.sqlite.sqlite_merge import SqliteMerger
317437

318-
merger = SqliteMerger(self)
319-
return merger.merge(source_ucis, create_history)
438+
# If source is not a SqliteUCIS, convert it first
439+
if not isinstance(source_ucis, SqliteUCIS):
440+
source_ucis = _convert_to_sqlite(source_ucis)
441+
temp_source = source_ucis # Keep reference to close later
442+
else:
443+
temp_source = None
444+
445+
try:
446+
merger = SqliteMerger(self)
447+
result = merger.merge(source_ucis, create_history)
448+
return result
449+
finally:
450+
# Clean up temporary SQLite database if we created one
451+
if temp_source is not None:
452+
temp_source.close()

test_issue_reproduce.py

Lines changed: 0 additions & 84 deletions
This file was deleted.

0 commit comments

Comments
 (0)