4
4
except ImportError :
5
5
from urllib import quote as quote_from_bytes
6
6
from urllib import unquote as unquote_to_bytes
7
+ from cinnabar .dag import gitdag
7
8
from cinnabar .githg import (
8
9
Changeset ,
9
10
FileFindParents ,
@@ -160,8 +161,7 @@ def create_hg_manifest(self, commit, parents):
160
161
if not parents :
161
162
for line in Git .ls_tree (commit , recursive = True ):
162
163
mode , typ , sha1 , path = line
163
- node = self .create_file (sha1 , git_manifest_parents = (),
164
- path = path )
164
+ node = self .create_file (sha1 )
165
165
manifest .add (path , node , self .ATTR [mode ], modified = True )
166
166
changeset_files .append (path )
167
167
@@ -181,7 +181,22 @@ def create_hg_manifest(self, commit, parents):
181
181
self .manifest_ref (parent2_node ))
182
182
183
183
# TODO: this would benefit from less git queries
184
- files = [(path , mode , sha1 ) for mode , _ , sha1 , path in
184
+ file_dags = {}
185
+ for m , tree , mparents in GitHgHelper .rev_list (
186
+ b'--parents' , b'--topo-order' ,
187
+ b'--full-history' , b'--reverse' ,
188
+ b'%s...%s' % git_manifests ):
189
+ for p in mparents :
190
+ for path , sha1_after , sha1_before in manifest_diff (p , m ):
191
+ path = GitHgStore .manifest_path (path )
192
+ if path not in file_dags :
193
+ file_dags [path ] = gitdag ()
194
+ dag = file_dags [path ]
195
+ if sha1_before == NULL_NODE_ID :
196
+ dag .add (sha1_after , ())
197
+ else :
198
+ dag .add (sha1_after , (sha1_before ,))
199
+ files = [(p , mode , sha1 ) for mode , _ , sha1 , p in
185
200
Git .ls_tree (commit , recursive = True )]
186
201
manifests = sorted_merge (parent_manifest , parent2_manifest ,
187
202
key = lambda i : i .path , non_key = lambda i : i )
@@ -210,15 +225,25 @@ def create_hg_manifest(self, commit, parents):
210
225
if self ._merge_warn == 1 :
211
226
logging .warning ('This may take a while...' )
212
227
self ._merge_warn = 2
213
- file_parents = (manifest_line_p1 .sha1 ,
214
- manifest_line_p2 .sha1 )
228
+ file_parents = ()
229
+ dag = file_dags .pop (path )
230
+ if dag :
231
+ dag .tag_nodes_and_parents (
232
+ (manifest_line_p1 .sha1 ,), 'a' )
233
+ if dag ._tags .get (manifest_line_p2 .sha1 ) == 'a' :
234
+ file_parents = (manifest_line_p1 .sha1 ,)
235
+ else :
236
+ dag ._tags .clear ()
237
+ dag .tag_nodes_and_parents (
238
+ (manifest_line_p2 .sha1 ,), 'b' )
239
+ if dag ._tags .get (manifest_line_p1 .sha1 ) == 'b' :
240
+ file_parents = (manifest_line_p2 .sha1 ,)
241
+ if not file_parents :
242
+ file_parents = (manifest_line_p1 .sha1 ,
243
+ manifest_line_p2 .sha1 )
215
244
216
245
assert file_parents is not None
217
- f = self ._create_file_internal (
218
- sha1 , * file_parents ,
219
- git_manifest_parents = git_manifests ,
220
- path = path
221
- )
246
+ f = self ._create_file_internal (sha1 , * file_parents )
222
247
file_parents = tuple (p for p in (f .parent1 , f .parent2 )
223
248
if p != NULL_NODE_ID )
224
249
merged = len (file_parents ) == 2
@@ -277,31 +302,17 @@ def process_diff(diff):
277
302
if sha1_before == sha1_after :
278
303
node = manifest_line .sha1
279
304
else :
280
- node = self .create_file (
281
- sha1_after , manifest_line .sha1 ,
282
- git_manifest_parents = (
283
- self .manifest_ref (parent_node ),),
284
- path = path )
305
+ node = self .create_file (sha1_after , manifest_line .sha1 )
285
306
elif status in b'RC' :
286
307
if sha1_after != EMPTY_BLOB :
287
308
node = self .create_copy (
288
309
(path2 , parent_lines [path2 ].sha1 ), sha1_after ,
289
- git_manifest_parents = (
290
- self .manifest_ref (parent_node ),),
291
310
path = path )
292
311
else :
293
- node = self .create_file (
294
- sha1_after ,
295
- git_manifest_parents = (
296
- self .manifest_ref (parent_node ),),
297
- path = path )
312
+ node = self .create_file (sha1_after )
298
313
else :
299
314
assert status == b'A'
300
- node = self .create_file (
301
- sha1_after ,
302
- git_manifest_parents = (
303
- self .manifest_ref (parent_node ),),
304
- path = path )
315
+ node = self .create_file (sha1_after )
305
316
manifest .add (path , node , attr , modified = True )
306
317
changeset_files .append (path )
307
318
manifest .parents = (parent_node ,)
@@ -364,14 +375,10 @@ def create_hg_metadata(self, commit, parents):
364
375
raise Exception ('Changeset mismatch' )
365
376
366
377
def _create_file_internal (self , sha1 , parent1 = NULL_NODE_ID ,
367
- parent2 = NULL_NODE_ID ,
368
- git_manifest_parents = None , path = None ):
378
+ parent2 = NULL_NODE_ID ):
369
379
hg_file = File ()
370
380
hg_file .content = GitHgHelper .cat_file (b'blob' , sha1 )
371
- FileFindParents .set_parents (
372
- hg_file , parent1 , parent2 ,
373
- git_manifest_parents = git_manifest_parents ,
374
- path = path )
381
+ FileFindParents .set_parents (hg_file , parent1 , parent2 )
375
382
node = hg_file .node = hg_file .sha1
376
383
GitHgHelper .set (b'file' , node , sha1 )
377
384
return hg_file
@@ -381,14 +388,11 @@ def _store_file_internal(self, hg_file):
381
388
self ._pushed .add (node )
382
389
return node
383
390
384
- def create_file (self , sha1 , parent1 = NULL_NODE_ID , parent2 = NULL_NODE_ID ,
385
- git_manifest_parents = None , path = None ):
386
- hg_file = self ._create_file_internal (sha1 , parent1 , parent2 ,
387
- git_manifest_parents , path )
391
+ def create_file (self , sha1 , parent1 = NULL_NODE_ID , parent2 = NULL_NODE_ID ):
392
+ hg_file = self ._create_file_internal (sha1 , parent1 , parent2 )
388
393
return self ._store_file_internal (hg_file )
389
394
390
- def create_copy (self , hg_source , sha1 , git_manifest_parents = None ,
391
- path = None ):
395
+ def create_copy (self , hg_source , sha1 , path = None ):
392
396
path , rev = hg_source
393
397
hg_file = File ()
394
398
hg_file .metadata = {
@@ -476,7 +480,7 @@ def bundle_data(store, commits):
476
480
for path , hg_file , hg_fileparents in changes :
477
481
if hg_file != NULL_NODE_ID :
478
482
files [store .manifest_path (path )].append (
479
- (hg_file , hg_fileparents , changeset , parents ))
483
+ (hg_file , hg_fileparents , changeset ))
480
484
481
485
yield None
482
486
@@ -485,12 +489,12 @@ def iter_files(files):
485
489
for count_names , path in enumerate (sorted (files ), 1 ):
486
490
yield (count_chunks , count_names ), path
487
491
nodes = set ()
488
- for node , parents , changeset , mn_parents in files [path ]:
492
+ for node , parents , changeset in files [path ]:
489
493
if node in nodes :
490
494
continue
491
495
count_chunks += 1
492
496
nodes .add (node )
493
- file = store .file (node , parents , mn_parents , path )
497
+ file = store .file (node , parents )
494
498
file .changeset = changeset
495
499
assert file .node == file .sha1
496
500
yield (count_chunks , count_names ), file
0 commit comments