|
1 | 1 | import os |
2 | 2 | import pygit2 |
3 | 3 | import rdflib |
| 4 | +from atomicgraphs import comp_graph |
4 | 5 | import logging |
5 | 6 | from quit.exceptions import QuitMergeConflict, QuitBlobMergeConflict |
6 | 7 | from rdflib.plugins.serializers.nt import _nt_row as _nt |
| 8 | +import rdflib.plugins.parsers as parsers |
7 | 9 |
|
8 | 10 | logger = logging.getLogger('quit.merge') |
9 | 11 |
|
@@ -80,11 +82,12 @@ def merge_quit_commits(self, target, branch, favour): |
80 | 82 |
|
81 | 83 | mergedTreeBuilder = self._repository.TreeBuilder(targetCommit.tree) |
82 | 84 | logger.debug(diff) |
83 | | - |
| 85 | + print("Diff: {}".format(diff)) |
84 | 86 | logger.debug(diff.stats) |
85 | 87 | logger.debug("Diff has following patches") |
86 | 88 | conflicts = {} |
87 | 89 | for p in diff: |
| 90 | + print("Patch: {}".format(p)) |
88 | 91 | logger.debug("A Patch") |
89 | 92 | logger.debug(p) |
90 | 93 | logger.debug(p.line_stats) |
@@ -160,79 +163,118 @@ def _merge_graph_blobs(self, graphAOid, graphBOid, graphBaseOid, favour): |
160 | 163 |
|
161 | 164 | def _merge_threeway_graph_blobs(self, graphAOid, graphBOid, graphBaseOid): |
162 | 165 | if str(graphAOid) == pygit2.GIT_OID_HEX_ZERO: |
163 | | - a = set() |
| 166 | + aGraph = rdflib.Graph() |
164 | 167 | else: |
165 | 168 | graphAblob = self._repository[graphAOid].data |
166 | | - a = set(graphAblob.decode("utf-8").strip().split("\n")) |
| 169 | + aGraph = rdflib.Graph().parse(data=graphAblob.decode("utf-8"), format="nt") |
167 | 170 |
|
168 | 171 | if str(graphBOid) == pygit2.GIT_OID_HEX_ZERO: |
169 | | - b = set() |
| 172 | + bGraph = rdflib.Graph() |
170 | 173 | else: |
171 | 174 | graphBblob = self._repository[graphBOid].data |
172 | | - b = set(graphBblob.decode("utf-8").strip().split("\n")) |
| 175 | + bGraph = rdflib.Graph().parse(data=graphBblob.decode("utf-8"), format="nt") |
173 | 176 |
|
174 | 177 | if graphBaseOid is not None: |
175 | 178 | graphBaseblob = self._repository[graphBaseOid].data |
176 | | - base = set(graphBaseblob.decode("utf-8").strip().split("\n")) |
177 | | - addA = a - base |
178 | | - addB = b - base |
179 | | - intersect = a.intersection(b) |
180 | | - merged = sorted(intersect.union(addA).union(addB)) |
| 179 | + compGraphBase = comp_graph.ComparableGraph() |
| 180 | + compGraphBase.parse(data=graphBaseblob.decode("utf-8"), format="nt") |
| 181 | + compGraphA = comp_graph.ComparableGraph(aGraph.store, aGraph.identifier) |
| 182 | + compGraphB = comp_graph.ComparableGraph(bGraph.store, bGraph.identifier) |
| 183 | + diffA = compGraphA.diff(compGraphBase) |
| 184 | + diffB = compGraphB.diff(compGraphBase) |
| 185 | + |
| 186 | + diffANewTriples = self._accumulate_triples(diffA[1]) |
| 187 | + diffBNewTriples = self._accumulate_triples(diffB[1]) |
| 188 | + diffARemovedTriples = self._accumulate_triples(diffA[0]) |
| 189 | + diffBRemovedTriples = self._accumulate_triples(diffB[0]) |
| 190 | + baseTriples = self._get_triples(compGraphBase) |
| 191 | + merged = (baseTriples - diffARemovedTriples - diffBRemovedTriples + |
| 192 | + diffANewTriples + diffBNewTriples) |
| 193 | + serializer = parsers.ntriples.NTriplesParser(parsers.nt.NTSink(aGraph)) |
| 194 | + merged = self._serialize_triple_sets(merged, serializer._bnode_ids) |
181 | 195 | else: |
182 | | - merged = a.union(b) |
| 196 | + compGraphA = comp_graph.ComparableGraph(aGraph.store, bGraph.identifier) |
| 197 | + compGraphB = comp_graph.ComparableGraph(bGraph.store, bGraph.identifier) |
| 198 | + diff = compGraphA.diff(compGraphB) |
| 199 | + merged = self._get_triples(compGraphA) |
| 200 | + merged = merged.union(self._accumulate_triples(diff[0])) |
| 201 | + serializer = parsers.ntriples.NTriplesParser(parsers.nt.NTSink(aGraph)) |
| 202 | + merged = self._serialize_triple_sets(merged, serializer._bnode_ids) |
183 | 203 | print("\n".join(merged)) |
184 | 204 |
|
185 | 205 | blob = self._repository.create_blob(("\n".join(merged) + "\n").encode("utf-8")) |
186 | 206 | return blob |
187 | 207 |
|
| 208 | + def _accumulate_triples(self, setOfGraphs): |
| 209 | + result = set() |
| 210 | + for aGraph in setOfGraphs: |
| 211 | + result = result.union(self._get_triples(aGraph)) |
| 212 | + return result |
| 213 | + |
| 214 | + def _get_triples(self, graph): |
| 215 | + return set(graph.triples((None, None, None))) |
| 216 | + |
| 217 | + def _serialize_triple_sets(self, set, bIdMap): |
| 218 | + result = set() |
| 219 | + for triple in set: |
| 220 | + result.add("{} {} {} .".format(self._serialize_bNode(triple[0], bIdMap), |
| 221 | + triple[1].n3(), |
| 222 | + self._serialize_bNode(triple[2], bIdMap))) |
| 223 | + return sorted(result) |
| 224 | + |
| 225 | + def _serialize_bNode(self, node, bIdMap): |
| 226 | + if(isinstance(node, rdflib.BNode)): |
| 227 | + return "_:{}".format(bIdMap[node]) |
| 228 | + else: |
| 229 | + return node.n3() |
| 230 | + |
188 | 231 | def _merge_context_graph_blobs(self, graphAOid, graphBOid, graphBaseOid): |
189 | 232 | if str(graphAOid) == pygit2.GIT_OID_HEX_ZERO: |
190 | | - a = set() |
| 233 | + graphA = comp_graph.ComparableGraph() |
191 | 234 | else: |
192 | 235 | graphAblob = self._repository[graphAOid].data |
193 | | - a = set(graphAblob.decode("utf-8").split("\n")) |
| 236 | + graphA = comp_graph.ComparableGraph() |
| 237 | + graphA.parse(data=graphAblob.decode("utf-8"), format="nt") |
194 | 238 |
|
195 | 239 | if str(graphBOid) == pygit2.GIT_OID_HEX_ZERO: |
196 | | - b = set() |
| 240 | + graphB = comp_graph.ComparableGraph() |
197 | 241 | else: |
198 | 242 | graphBblob = self._repository[graphBOid].data |
199 | | - b = set(graphBblob.decode("utf-8").split("\n")) |
| 243 | + graphB = comp_graph.ComparableGraph() |
| 244 | + graphB.parse(data=graphBblob.decode("utf-8"), format="nt") |
200 | 245 |
|
201 | 246 | if graphBaseOid is not None: |
202 | 247 | graphBaseblob = self._repository[graphBaseOid].data |
203 | | - base = set(graphBaseblob.decode("utf-8").split("\n")) |
| 248 | + graphBase = comp_graph.ComparableGraph() |
| 249 | + graphBase.parse(data=graphBaseblob.decode("utf-8"), format="nt") |
204 | 250 | else: |
205 | | - base = set() |
206 | | - |
207 | | - logger.debug("base") |
208 | | - logger.debug(base) |
209 | | - logger.debug("a") |
210 | | - logger.debug(a) |
211 | | - logger.debug("b") |
212 | | - logger.debug(b) |
213 | | - |
214 | | - addA = a - base |
215 | | - delA = base - a |
216 | | - addB = b - base |
217 | | - delB = base - b |
218 | | - |
219 | | - ok, conflicts = self._merge_context_conflict_detection(addA - addB, delA - delB, |
220 | | - addB - addA, delB - delA) |
221 | | - |
222 | | - logger.debug("intersect and ok, then merged") |
223 | | - logger.debug(a.intersection(b)) |
224 | | - logger.debug(ok) |
225 | | - merged = sorted(a.intersection(b).union(ok)) |
226 | | - logger.debug(merged) |
227 | | - print(merged) |
228 | | - |
229 | | - if conflicts is not None: |
230 | | - print("raised") |
231 | | - raise QuitBlobMergeConflict('Conflicts, ahhhhh!!', merged, conflicts) |
| 251 | + graphBase = comp_graph.ComparableGraph() |
| 252 | + |
| 253 | + diffA = graphA.diff(graphBase) |
| 254 | + diffB = graphB.diff(graphBase) |
| 255 | + |
| 256 | + diffANewTriples = self._accumulate_triples(diffA[1]) |
| 257 | + diffBNewTriples = self._accumulate_triples(diffB[1]) |
| 258 | + diffARemovedTriples = self._accumulate_triples(diffA[0]) |
| 259 | + diffBRemovedTriples = self._accumulate_triples(diffB[0]) |
| 260 | + baseTriples = self._get_triples(graphBase) |
| 261 | + merged = (baseTriples - diffARemovedTriples - diffBRemovedTriples + |
| 262 | + diffANewTriples + diffBNewTriples) |
| 263 | + serializer = parsers.ntriples.NTriplesParser(parsers.nt.NTSink(graphA)) |
| 264 | + merged = self._serialize_triple_sets(merged, serializer._bnode_ids) |
232 | 265 |
|
233 | 266 | blob = self._repository.create_blob("\n".join(merged).encode("utf-8")) |
234 | 267 | return blob |
235 | 268 |
|
| 269 | + def _compare_atomic_graphs(self, graphDataA, graphDataB): |
| 270 | + aGraph = comp_graph.ComparableGraph() |
| 271 | + aGraph.parse(data=graphDataA, format="n3") |
| 272 | + bGraph = comp_graph.ComparableGraph() |
| 273 | + bGraph.parse(data=graphDataB, format="n3") |
| 274 | + aData = aGraph.serialize(destination=None, format='nt') |
| 275 | + diffData = aGraph.diff(bGraph)[1].serialize(destination=None, format='nt') |
| 276 | + return aData + diffData |
| 277 | + |
236 | 278 | def _merge_context_conflict_detection(self, addA, delA, addB, delB): |
237 | 279 |
|
238 | 280 | def conflictSet(graph, conflictingNodes): |
|
0 commit comments