comparison hgext/largefiles/lfutil.py @ 23185:9870173e0b48

largefiles: factor out procedures to update standins for pre-committing This patch factors out procedures to update standins for pre-committing. This is one of preparations to avoid execution of such procedures according to invocation context. For example, resuming automated committing (e.g. "hg rebase --continue") should update standins at the 1st commit, because largefiles in the working directory may be modified manually. But on the other hand, it should avoid updating standins at subsequent committings for efficiency reason. For simplicity, this patch just moves procedures mechanically only with replacing below. - "self" => "repo" - "lfutil." => (none) - "orig" invocation => returning "match" Using "fstandin" instead "standin" as the name of local variable for the loop below is the only special care, because the latter shadows the same name function in "lfutil.py". [before] for standin in standins: lfile = lfutil.splitstandin(standin) if lfdirstate[lfile] != 'r': lfutil.updatestandin(self, standin) [after] for fstandin in standins: lfile = splitstandin(fstandin) if lfdirstate[lfile] != 'r': updatestandin(repo, fstandin)
author FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
date Wed, 05 Nov 2014 23:24:47 +0900
parents 3100d1cbce32
children f726b05ecfe6
comparison
equal deleted inserted replaced
23184:3100d1cbce32 23185:9870173e0b48
10 10
11 import os 11 import os
12 import platform 12 import platform
13 import shutil 13 import shutil
14 import stat 14 import stat
15 import copy
15 16
16 from mercurial import dirstate, httpconnection, match as match_, util, scmutil 17 from mercurial import dirstate, httpconnection, match as match_, util, scmutil
17 from mercurial.i18n import _ 18 from mercurial.i18n import _
18 from mercurial import node 19 from mercurial import node
19 20
425 if mc[f] != mp1.get(f, None) or mc[f] != mp2.get(f, None): 426 if mc[f] != mp1.get(f, None) or mc[f] != mp2.get(f, None):
426 files.add(f) 427 files.add(f)
427 for fn in files: 428 for fn in files:
428 if isstandin(fn) and fn in ctx: 429 if isstandin(fn) and fn in ctx:
429 addfunc(fn, ctx[fn].data().strip()) 430 addfunc(fn, ctx[fn].data().strip())
431
432 def updatestandinsbymatch(repo, match):
433 '''Update standins in the working directory according to specified match
434
435 This returns (possibly modified) ``match`` object to be used for
436 subsequent commit process.
437 '''
438
439 ui = repo.ui
440
441 # Case 0: Automated committing
442 #
443 # While automated committing (like rebase, transplant
444 # and so on), this code path is used to avoid:
445 # (1) updating standins, because standins should
446 # be already updated at this point
447 # (2) aborting when standins are matched by "match",
448 # because automated committing may specify them directly
449 #
450 if getattr(repo, "_isrebasing", False) or \
451 getattr(repo, "_istransplanting", False):
452 return match
453
454 # Case 1: user calls commit with no specific files or
455 # include/exclude patterns: refresh and commit all files that
456 # are "dirty".
457 if match is None or match.always():
458 # Spend a bit of time here to get a list of files we know
459 # are modified so we can compare only against those.
460 # It can cost a lot of time (several seconds)
461 # otherwise to update all standins if the largefiles are
462 # large.
463 lfdirstate = openlfdirstate(ui, repo)
464 dirtymatch = match_.always(repo.root, repo.getcwd())
465 unsure, s = lfdirstate.status(dirtymatch, [], False, False,
466 False)
467 modifiedfiles = unsure + s.modified + s.added + s.removed
468 lfiles = listlfiles(repo)
469 # this only loops through largefiles that exist (not
470 # removed/renamed)
471 for lfile in lfiles:
472 if lfile in modifiedfiles:
473 if os.path.exists(
474 repo.wjoin(standin(lfile))):
475 # this handles the case where a rebase is being
476 # performed and the working copy is not updated
477 # yet.
478 if os.path.exists(repo.wjoin(lfile)):
479 updatestandin(repo,
480 standin(lfile))
481
482 return match
483
484 lfiles = listlfiles(repo)
485 match._files = repo._subdirlfs(match.files(), lfiles)
486
487 # Case 2: user calls commit with specified patterns: refresh
488 # any matching big files.
489 smatcher = composestandinmatcher(repo, match)
490 standins = repo.dirstate.walk(smatcher, [], False, False)
491
492 # No matching big files: get out of the way and pass control to
493 # the usual commit() method.
494 if not standins:
495 return match
496
497 # Refresh all matching big files. It's possible that the
498 # commit will end up failing, in which case the big files will
499 # stay refreshed. No harm done: the user modified them and
500 # asked to commit them, so sooner or later we're going to
501 # refresh the standins. Might as well leave them refreshed.
502 lfdirstate = openlfdirstate(ui, repo)
503 for fstandin in standins:
504 lfile = splitstandin(fstandin)
505 if lfdirstate[lfile] != 'r':
506 updatestandin(repo, fstandin)
507
508 # Cook up a new matcher that only matches regular files or
509 # standins corresponding to the big files requested by the
510 # user. Have to modify _files to prevent commit() from
511 # complaining "not tracked" for big files.
512 match = copy.copy(match)
513 origmatchfn = match.matchfn
514
515 # Check both the list of largefiles and the list of
516 # standins because if a largefile was removed, it
517 # won't be in the list of largefiles at this point
518 match._files += sorted(standins)
519
520 actualfiles = []
521 for f in match._files:
522 fstandin = standin(f)
523
524 # ignore known largefiles and standins
525 if f in lfiles or fstandin in standins:
526 continue
527
528 actualfiles.append(f)
529 match._files = actualfiles
530
531 def matchfn(f):
532 if origmatchfn(f):
533 return f not in lfiles
534 else:
535 return f in standins
536
537 match.matchfn = matchfn
538
539 return match