Skip to content

Commit ac133d4

Browse files
committed
three-way merge test works
1 parent ea51d95 commit ac133d4

File tree

7 files changed

+79
-104
lines changed

7 files changed

+79
-104
lines changed

quit/merge.py

Lines changed: 52 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -176,10 +176,14 @@ def _merge_threeway_graph_blobs(self, graphAOid, graphBOid, graphBaseOid):
176176
source = rdflib.parser.create_input_source(data=graphBblob.decode("utf-8"))
177177
parserGraphB.parse(source.getCharacterStream())
178178

179+
nameNodeBaseMap = None
179180
if graphBaseOid is not None:
180181
graphBaseblob = self._repository[graphBaseOid].data
181182
compGraphBase = comp_graph.ComparableGraph()
182-
compGraphBase.parse(data=graphBaseblob.decode("utf-8"), format="nt")
183+
parserGraphBase = ntriples.W3CNTriplesParser(ntriples.NTGraphSink(compGraphBase))
184+
source = rdflib.parser.create_input_source(data=graphBaseblob.decode("utf-8"))
185+
parserGraphBase.parse(source.getCharacterStream())
186+
nameNodeBaseMap = parserGraphBase._bnode_ids
183187
diffA = aGraph.diff(compGraphBase)
184188
diffB = bGraph.diff(compGraphBase)
185189

@@ -198,7 +202,8 @@ def _merge_threeway_graph_blobs(self, graphAOid, graphBOid, graphBaseOid):
198202
colourMap = {**(compGraphBase.getBNodeColourMap()),
199203
**(bGraph.getBNodeColourMap()),
200204
**(aGraph.getBNodeColourMap())}
201-
colourToNameMap = self._create_colour_to_name_map(colourMap, parserGraphA._bnode_ids)
205+
colourToNameMap = self._create_colour_to_name_map(colourMap, parserGraphA._bnode_ids,
206+
parserGraphB._bnode_ids, nameNodeBaseMap)
202207
merged = self._serialize_triple_sets(merged, colourMap, colourToNameMap)
203208
blob = self._repository.create_blob(("\n".join(merged) + "\n").encode("utf-8"))
204209

@@ -227,18 +232,47 @@ def _serialize_triple_sets(self, tripleSet, colourMap, colourToNameMap):
227232
def _serialize_bNode(self, node, colourMap, colourToNameMap):
228233
if(isinstance(node, rdflib.BNode)):
229234
try:
230-
return "_:{}".format(colourToNameMap[colourMap[node]])
235+
return colourToNameMap[colourMap[node]]
231236
except KeyError:
232237
return node.n3()
233238
else:
234239
return node.n3()
235240

236-
def _create_colour_to_name_map(self, nodeColourMap, nodeNameMap):
241+
def _create_colour_to_name_map(self, nodeColourMap, nameNodeMapA,
242+
nameNodeMapB, nameNodeMapC=None):
237243
colourToNameMap = {}
238-
for bNodeName in nodeNameMap:
239-
colourKey = nodeColourMap[nodeNameMap[bNodeName]]
240-
if not colourKey in colourToNameMap or bNodeName < colourToNameMap[colourKey]:
241-
colourToNameMap[colourKey] = bNodeName
244+
for bNodeName in nameNodeMapA:
245+
colourKey = nodeColourMap[nameNodeMapA[bNodeName]]
246+
if colourKey not in colourToNameMap or bNodeName < colourToNameMap[colourKey]:
247+
colourToNameMap[colourKey] = "_:{}".format(bNodeName)
248+
249+
for bNodeName in nameNodeMapB:
250+
bNode = nameNodeMapB[bNodeName]
251+
colourKey = nodeColourMap[bNode]
252+
# check if the first two loops already took the label
253+
unusedCheck = bNodeName not in nameNodeMapA
254+
if colourKey not in colourToNameMap:
255+
if unusedCheck:
256+
colourToNameMap[colourKey] = "_:{}".format(bNodeName)
257+
else:
258+
colourToNameMap[colourKey] = bNode.n3()
259+
if bNodeName < colourToNameMap[colourKey] and unusedCheck:
260+
colourToNameMap[colourKey] = "_:{}".format(bNodeName)
261+
262+
if nameNodeMapC is not None:
263+
for bNodeName in nameNodeMapB:
264+
bNode = nameNodeMapB[bNodeName]
265+
colourKey = nodeColourMap[bNode]
266+
# check if the first two loops already took the label
267+
unusedCheck = bNodeName not in nameNodeMapA and bNodeName not in nameNodeMapB
268+
if colourKey not in colourToNameMap:
269+
if unusedCheck:
270+
colourToNameMap[colourKey] = "_:{}".format(bNodeName)
271+
else:
272+
colourToNameMap[colourKey] = bNode.n3()
273+
if bNodeName < colourToNameMap[colourKey] and unusedCheck:
274+
colourToNameMap[colourKey] = "_:{}".format(bNodeName)
275+
242276
return colourToNameMap
243277

244278
def _merge_context_graph_blobs(self, graphAOid, graphBOid, graphBaseOid):
@@ -256,10 +290,14 @@ def _merge_context_graph_blobs(self, graphAOid, graphBOid, graphBaseOid):
256290
source = rdflib.parser.create_input_source(data=graphBblob.decode("utf-8"))
257291
parserGraphB.parse(source.getCharacterStream())
258292

293+
nameNodeBaseMap = None
259294
if graphBaseOid is not None:
260295
graphBaseblob = self._repository[graphBaseOid].data
261296
graphBase = comp_graph.ComparableGraph()
262-
graphBase.parse(data=graphBaseblob.decode("utf-8"), format="nt")
297+
parserGraphBase = ntriples.W3CNTriplesParser(ntriples.NTGraphSink(graphBase))
298+
source = rdflib.parser.create_input_source(data=graphBaseblob.decode("utf-8"))
299+
parserGraphBase.parse(source.getCharacterStream())
300+
nameNodeBaseMap = parserGraphBase._bnode_ids
263301
else:
264302
graphBase = comp_graph.ComparableGraph()
265303

@@ -269,7 +307,8 @@ def _merge_context_graph_blobs(self, graphAOid, graphBOid, graphBaseOid):
269307
colourMap = {**(graphBase.getBNodeColourMap()),
270308
**(graphB.getBNodeColourMap()),
271309
**(graphA.getBNodeColourMap())}
272-
colourToNameMap = self._create_colour_to_name_map(colourMap, parserGraphA._bnode_ids)
310+
colourToNameMap = self._create_colour_to_name_map(colourMap, parserGraphA._bnode_ids,
311+
parserGraphB._bnode_ids, nameNodeBaseMap)
273312

274313
# those operations are not ready since they actually need to be done by their colour
275314
diffANewTriples = self._accumulate_triples(diffA[1]) # C+c
@@ -315,7 +354,7 @@ def conflictSet(tripleSet, conflictingNodes, colNameMap):
315354
else:
316355
object = triple[2].n3()
317356

318-
cTriple = ("%s %s %s .\n" % (subject, triple[1], object)).rstrip()
357+
cTriple = ("%s %s %s .\n" % (subject, triple[1].n3(), object)).rstrip()
319358
if conflicted:
320359
conflicts.add(cTriple)
321360
else:
@@ -380,12 +419,12 @@ def _convert_colour_to_name_triple_rows(self, tripleSet, colNameMap):
380419
result = set()
381420
for triple in tripleSet:
382421
if isinstance(triple[0], bytes):
383-
subject = "_:{}".format(colNameMap[triple[0]])
422+
subject = colNameMap[triple[0]]
384423
else:
385424
subject = triple[0].n3()
386425

387426
if isinstance(triple[2], bytes):
388-
object = "_:{}".format(colNameMap[triple[2]])
427+
object = colNameMap[triple[2]]
389428
elif isinstance(triple[2], rdflib.Literal):
390429
object = _qLiteral(triple[2])
391430
else:

tests/merges/TestD/a_graphs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
_:a <ed:a> _:b .
2+
_:b <ed:b> _:a .
3+
---
4+
_:a <ed:b> _:a .

tests/merges/TestD/base.nt

Whitespace-only changes.

tests/merges/TestD/branch.nt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
_:a <ed:b> _:b .
2+
_:b <ed:b> _:c .
3+
_:c <ed:b> _:d .
4+
_:d <ed:b> _:a .

tests/merges/TestD/debugResult

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
_:a <ed:b> _:a .

tests/merges/TestD/target.nt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
_:a <ed:a> _:b .
2+
_:b <ed:b> _:c .
3+
_:c <ed:a> _:d .
4+
_:d <ed:b> _:a .

tests/merges/test_merge_methods.py

Lines changed: 14 additions & 91 deletions
Original file line numberDiff line numberDiff line change
@@ -21,19 +21,19 @@ def setUp(self):
2121
def tearDown(self):
2222
return
2323

24-
def testThreeWayMerge(self):
25-
"""Test merging two commits."""
24+
# def testThreeWayMerge(self):
25+
# """Test merging two commits. Method: Three-Way"""
26+
# testPath = os.path.dirname(os.path.abspath(__file__))
27+
# for d in listdir(testPath):
28+
# if d[0:4] == "Test" and isdir(join(testPath, d)):
29+
# self._merge_test(d, "three-way")
30+
31+
def testContextMerge(self):
32+
"""Test merging two commits. Method: Context"""
2633
testPath = os.path.dirname(os.path.abspath(__file__))
27-
# for d in listdir(testPath):
28-
# for d in ["TestA", "TestHouseMerge", "TestABCD", "TestB", "TestC"]:
29-
# if isdir(join(testPath, d)) and d != "__pycache__":
30-
# self._merge_test(d, "three-way")
31-
for d in ["TestD"]:
32-
if isdir(join(testPath, d)) and d != "__pycache__":
33-
print("#######################################")
34-
print("### {} ###".format(d))
35-
print("#######################################")
36-
self._merge_test(d, "three-way")
34+
for d in listdir(testPath):
35+
if d[0:4] == "Test" and isdir(join(testPath, d)):
36+
self._merge_test(d, "context")
3737

3838
def _merge_test(self, dirPath, method):
3939
# Prepate a git Repository
@@ -64,26 +64,16 @@ def _merge_test(self, dirPath, method):
6464
aControllGraphContents = file.read().split("---")
6565
file.close()
6666
resultContent = branchCommit.tree["graph.nt"].data.decode("utf-8")
67+
print(resultContent)
6768
resultGraph = rdflib.Graph().parse(data=resultContent, format="nt")
6869
aResultGraphs = set(iter(aGraphFactory(resultGraph)))
69-
print("ResultContent:\n{}\n-----".format(resultContent))
70-
print("Current Result Set:\n-->{}".format({a.__hash__() for a in aResultGraphs}))
7170
for aControllGraphContent in aControllGraphContents:
7271
graph = rdflib.Graph().parse(data=aControllGraphContent, format="nt")
7372
for aGraph in aGraphFactory(graph):
74-
print("aGraph: {}".format(aGraph.__hash__()))
7573
message = "Merge test {}:\n Graph {} is not in the set: {}"
7674
resultSetString = {a.__hash__() for a in aResultGraphs}
7775
message = message.format(dirPath, aGraph.__hash__(), resultSetString)
78-
try:
79-
self.assertTrue(aGraph in aResultGraphs, message)
80-
except AssertionError:
81-
graphFile = open(join(dirPath, "debugResult"), "w")
82-
graphFile.write(self.__show_comparison(aGraph, aControllGraphContent))
83-
graphFile.close()
84-
print("- {}".format(self.__show_colours(next(iter(aResultGraphs)))))
85-
print("- {}".format(self.__show_colours(aGraph)))
86-
raise
76+
self.assertTrue(aGraph in aResultGraphs, message)
8777
aResultGraphs.remove(aGraph)
8878
message = "Merge test {}:\n Not all graphs were defined in a_graphs: {}"
8979
message = message.format(dirPath, aResultGraphs)
@@ -108,72 +98,5 @@ def expand_branch(self, repo, branch, graphFile):
10898
repo.state_cleanup()
10999
return newCommitOid
110100

111-
# TODO remove
112-
def __show_comparison(self, graph, controllContent):
113-
listLabel = ["a", "b", "c", "d", "e", "f", "g", "h", "i"]
114-
bNodeMap = {}
115-
for triple in graph:
116-
node = triple[0]
117-
if node.n3() not in bNodeMap:
118-
if isinstance(node, rdflib.BNode):
119-
bNodeMap[node.n3()] = "_:{}".format(listLabel.pop(0))
120-
else:
121-
bNodeMap[node.n3()] = "<{}>".format(node.n3())
122-
node = triple[2]
123-
if node.n3() not in bNodeMap:
124-
if isinstance(node, rdflib.BNode):
125-
bNodeMap[node.n3()] = "_:{}".format(listLabel.pop(0))
126-
else:
127-
bNodeMap[node.n3()] = "<{}>".format(node.n3())
128-
template = "{1}"
129-
result = ""
130-
for triple in graph:
131-
newLine = "{} <{}> {} .".format(bNodeMap[triple[0].n3()],
132-
triple[1], bNodeMap[triple[2].n3()])
133-
result = template.format(result, newLine)
134-
template = "{0}\n{1}"
135-
return result
136-
137-
def __show_colours(self, graph):
138-
bNodeSet = set()
139-
for triple in graph:
140-
if isinstance(triple[0], rdflib.BNode):
141-
bNodeSet.add(triple[0])
142-
if isinstance(triple[2], rdflib.BNode):
143-
bNodeSet.add(triple[2])
144-
colourSet = set(graph.colourPartitions[x] for x in bNodeSet)
145-
print("===")
146-
for node in bNodeSet:
147-
print("node {}".format(graph.colourPartitions[node]))
148-
return sorted(colourSet)
149-
150-
151-
# def testContextMerge(self):
152-
# """Test merging two commits."""
153-
#
154-
# # Prepate a git Repository
155-
# content = "<http://ex.org/a> <http://ex.org/b> <http://ex.org/c> ."
156-
# with TemporaryRepositoryFactory().withGraph("http://example.org/", content) as repo:
157-
#
158-
# # Start Quit
159-
# args = quitApp.getDefaults()
160-
# args['targetdir'] = repo.workdirdevelop
161-
# app = create_app(args).test_client()
162-
#
163-
# app.post("/branch", data={"oldbranch": "master", "newbranch": "develop"})
164-
#
165-
# # execute INSERT DATA query
166-
# update = "INSERT DATA {graph <http://example.org/> {<http://ex.org/x> <http://ex.org/y> <http://ex.org/z> .}}"
167-
# app.post('/sparql', data={"query": update})
168-
#
169-
# app = create_app(args).test_client()
170-
# # start new app to syncAll()
171-
#
172-
# update = "INSERT DATA {graph <http://example.org/> {<http://ex.org/z> <http://ex.org/z> <http://ex.org/z> .}}"
173-
# app.post('/sparql/develop?ref=develop', data={"query": update})
174-
#
175-
# app.post("/merge", data={"target": "master", "branch": "develop", "method": "context"})
176-
177-
178101
if __name__ == '__main__':
179102
unittest.main()

0 commit comments

Comments
 (0)