Mercurial > public > mercurial-scm > hg
comparison mercurial/sparse.py @ 33556:22371eabb3b1
sparse: add a requirement when a repository uses sparse (BC)
The presence of a sparse checkout can confuse legacy clients or
clients without sparse enabled for reasons that should be obvious.
This commit introduces a new repository requirement that tracks
whether sparse is enabled. The requirement is added when a sparse
config is activated and removed when the sparse config is reset.
The localrepository constructor has been taught to not open repos
with this requirement unless the sparse feature is enabled. It yields
a more actionable error message than what you would get if the
lockout were handled strictly at the requirements verification phase.
Old clients that aren't sparse aware will see the generic
"repository requires features unknown to this Mercurial" error,
however.
The new requirement has "exp" in its name to reflect the
experimental nature of sparse. There's a chance that the eventual
non-experimental feature won't change significantly and we could
have squatted on the "sparse" requirement without ill effect. If
that happens, we can teach new clients to still recognize the old
name. But I suspect we'll sneak in some BC and we'll want a new
requirement to convey new meaning.
Differential Revision: https://phab.mercurial-scm.org/D110
author | Gregory Szorc <gregory.szorc@gmail.com> |
---|---|
date | Mon, 17 Jul 2017 11:45:38 -0700 |
parents | 6755b719048c |
children | 7dcb517122f9 |
comparison
equal
deleted
inserted
replaced
33555:6755b719048c | 33556:22371eabb3b1 |
---|---|
16 from . import ( | 16 from . import ( |
17 error, | 17 error, |
18 match as matchmod, | 18 match as matchmod, |
19 merge as mergemod, | 19 merge as mergemod, |
20 pycompat, | 20 pycompat, |
21 scmutil, | |
21 util, | 22 util, |
22 ) | 23 ) |
23 | 24 |
24 # Whether sparse features are enabled. This variable is intended to be | 25 # Whether sparse features are enabled. This variable is intended to be |
25 # temporary to facilitate porting sparse to core. It should eventually be | 26 # temporary to facilitate porting sparse to core. It should eventually be |
520 refreshwdir(repo, origstatus, origsparsematch, force=True) | 521 refreshwdir(repo, origstatus, origsparsematch, force=True) |
521 | 522 |
522 prunetemporaryincludes(repo) | 523 prunetemporaryincludes(repo) |
523 | 524 |
524 def _updateconfigandrefreshwdir(repo, includes, excludes, profiles, | 525 def _updateconfigandrefreshwdir(repo, includes, excludes, profiles, |
525 force=False): | 526 force=False, removing=False): |
526 """Update the sparse config and working directory state.""" | 527 """Update the sparse config and working directory state.""" |
527 raw = repo.vfs.tryread('sparse') | 528 raw = repo.vfs.tryread('sparse') |
528 oldincludes, oldexcludes, oldprofiles = parseconfig(repo.ui, raw) | 529 oldincludes, oldexcludes, oldprofiles = parseconfig(repo.ui, raw) |
529 | 530 |
530 oldstatus = repo.status() | 531 oldstatus = repo.status() |
531 oldmatch = matcher(repo) | 532 oldmatch = matcher(repo) |
533 oldrequires = set(repo.requirements) | |
532 | 534 |
533 # TODO remove this try..except once the matcher integrates better | 535 # TODO remove this try..except once the matcher integrates better |
534 # with dirstate. We currently have to write the updated config | 536 # with dirstate. We currently have to write the updated config |
535 # because that will invalidate the matcher cache and force a | 537 # because that will invalidate the matcher cache and force a |
536 # re-read. We ideally want to update the cached matcher on the | 538 # re-read. We ideally want to update the cached matcher on the |
537 # repo instance then flush the new config to disk once wdir is | 539 # repo instance then flush the new config to disk once wdir is |
538 # updated. But this requires massive rework to matcher() and its | 540 # updated. But this requires massive rework to matcher() and its |
539 # consumers. | 541 # consumers. |
540 | 542 |
541 writeconfig(repo, includes, excludes, profiles) | 543 if 'exp-sparse' in oldrequires and removing: |
544 repo.requirements.discard('exp-sparse') | |
545 scmutil.writerequires(repo.vfs, repo.requirements) | |
546 elif 'exp-sparse' not in oldrequires: | |
547 repo.requirements.add('exp-sparse') | |
548 scmutil.writerequires(repo.vfs, repo.requirements) | |
542 | 549 |
543 try: | 550 try: |
551 writeconfig(repo, includes, excludes, profiles) | |
544 return refreshwdir(repo, oldstatus, oldmatch, force=force) | 552 return refreshwdir(repo, oldstatus, oldmatch, force=force) |
545 except Exception: | 553 except Exception: |
554 if repo.requirements != oldrequires: | |
555 repo.requirements.clear() | |
556 repo.requirements |= oldrequires | |
557 scmutil.writerequires(repo.vfs, repo.requirements) | |
546 writeconfig(repo, oldincludes, oldexcludes, oldprofiles) | 558 writeconfig(repo, oldincludes, oldexcludes, oldprofiles) |
547 raise | 559 raise |
548 | 560 |
549 def clearrules(repo, force=False): | 561 def clearrules(repo, force=False): |
550 """Clears include/exclude rules from the sparse config. | 562 """Clears include/exclude rules from the sparse config. |
645 len(oldinclude - newinclude)) | 657 len(oldinclude - newinclude)) |
646 excludecount = (len(newexclude - oldexclude) - | 658 excludecount = (len(newexclude - oldexclude) - |
647 len(oldexclude - newexclude)) | 659 len(oldexclude - newexclude)) |
648 | 660 |
649 fcounts = map(len, _updateconfigandrefreshwdir( | 661 fcounts = map(len, _updateconfigandrefreshwdir( |
650 repo, newinclude, newexclude, newprofiles, force=force)) | 662 repo, newinclude, newexclude, newprofiles, force=force, |
663 removing=reset)) | |
651 | 664 |
652 printchanges(repo.ui, opts, profilecount, includecount, | 665 printchanges(repo.ui, opts, profilecount, includecount, |
653 excludecount, *fcounts) | 666 excludecount, *fcounts) |
654 | 667 |
655 def printchanges(ui, opts, profilecount=0, includecount=0, excludecount=0, | 668 def printchanges(ui, opts, profilecount=0, includecount=0, excludecount=0, |