comparison hgext/largefiles/lfcommands.py @ 22197:f72d73937853

largefiles: update lfdirstate for unchanged largefiles during linear merging Before this patch, linear merging of modified largefiles causes an unexpected result, if (1) largefile collides with same-name normal one in the target revision and (2) "local" largefile is chosen, even though branch merging between such revisions works correctly. Expected result of such linear merging is marking the largefile as (re-)"added", but the actual result is marking it as "modified". The standin of modified "local largefile" is not changed by linear merging, and updating/merging update lfdirstate entries only for largefiles of which standins are changed. This patch adds the code path to update lfdirstate only for largefiles of which standins are not changed. In this case, "synclfdirstate" should be invoked with True as "normallookup" argument always to force using "normallookup" on dirstate for "n" files, because "normal" may mark target files as "clean" unexpectedly. To reduce cost of "lfile not in filelist", this patch converts "filelist" to a "set" object: "filelist" is used only in (1) the newly added code path and (2) the next line of "filelist = set(filelist)". This is a temporary way to fix with less changes. For fundamental resolution of this kind of problems in the future, "lfdirstate" should be updated with "dirstate" simultaneously during "merge.update" execution: maybe by hooking "recordupdates" (+ total refactoring around lfdirstate handling)
author FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
date Fri, 15 Aug 2014 20:28:51 +0900
parents cb62d77c7a01
children 650b5b6e75ed
comparison
equal deleted inserted replaced
22196:23fe278bde43 22197:f72d73937853
441 try: 441 try:
442 lfdirstate = lfutil.openlfdirstate(ui, repo) 442 lfdirstate = lfutil.openlfdirstate(ui, repo)
443 lfiles = set(lfutil.listlfiles(repo)) | set(lfdirstate) 443 lfiles = set(lfutil.listlfiles(repo)) | set(lfdirstate)
444 444
445 if filelist is not None: 445 if filelist is not None:
446 filelist = set(filelist)
446 lfiles = [f for f in lfiles if f in filelist] 447 lfiles = [f for f in lfiles if f in filelist]
447 448
448 update = {} 449 update = {}
449 updated, removed = 0, 0 450 updated, removed = 0, 0
450 for lfile in lfiles: 451 for lfile in lfiles:
510 511
511 updated += update1 512 updated += update1
512 513
513 lfutil.synclfdirstate(repo, lfdirstate, lfile, normallookup) 514 lfutil.synclfdirstate(repo, lfdirstate, lfile, normallookup)
514 515
516 if filelist is not None:
517 # If "local largefile" is chosen at file merging, it is
518 # not listed in "filelist" (= dirstate syncing is
519 # omitted), because the standin file is not changed before and
520 # after merging.
521 # But the status of such files may have to be changed by
522 # merging. For example, locally modified ("M") largefile
523 # has to become re-added("A"), if it is "normal" file in
524 # the target revision of linear-merging.
525 for lfile in lfdirstate:
526 if lfile not in filelist:
527 lfutil.synclfdirstate(repo, lfdirstate, lfile, True)
528
515 lfdirstate.write() 529 lfdirstate.write()
516 if printmessage and lfiles: 530 if printmessage and lfiles:
517 ui.status(_('%d largefiles updated, %d removed\n') % (updated, 531 ui.status(_('%d largefiles updated, %d removed\n') % (updated,
518 removed)) 532 removed))
519 finally: 533 finally: