comparison hgext/narrow/narrowdirstate.py @ 36079:a2a6e724d61a

narrow: import experimental extension from narrowhg revision cb51d673e9c5 Adjustments: * renamed src to hgext/narrow * marked extension experimental * added correct copyright header where it was missing * updated hgrc extension enable line in library.sh * renamed library.sh to narrow-library.sh * dropped all files from repo root as they're not interesting * dropped test-pyflakes.t, test-check-code.t and test-check-py3-compat.t * renamed remaining tests to all be test-narrow-* when they didn't already * fixed test-narrow-expanddirstate.t to refer to narrow and not narrowhg * fixed tests that wanted `update -C .` instead of `merge --abort` * corrected a two-space indent in narrowspec.py * added a missing _() in narrowcommands.py * fixed imports to pass the import checker * narrow only adds its --include and --exclude to clone if sparse isn't enabled to avoid breaking test-duplicateoptions.py. This is a kludge, and we'll need to come up with a better solution in the future. These were more or less the minimum to import something that would pass tests and not create a bunch of files we'll never use. Changes I intend to make as followups: * rework the test-narrow-*-tree.t tests to use the new testcases functionality in run-tests.py * remove lots of monkeypatches of core things Differential Revision: https://phab.mercurial-scm.org/D1974
author Augie Fackler <augie@google.com>
date Mon, 29 Jan 2018 16:19:33 -0500
parents
children 9fd8c2a3db5a
comparison
equal deleted inserted replaced
36078:7f68235f23ff 36079:a2a6e724d61a
1 # narrowdirstate.py - extensions to mercurial dirstate to support narrow clones
2 #
3 # Copyright 2017 Google, Inc.
4 #
5 # This software may be used and distributed according to the terms of the
6 # GNU General Public License version 2 or any later version.
7
8 from __future__ import absolute_import
9
10 from mercurial.i18n import _
11 from mercurial import (
12 dirstate,
13 error,
14 extensions,
15 match as matchmod,
16 util as hgutil,
17 )
18
19 from . import narrowspec
20
21 def setup(repo):
22 """Add narrow spec dirstate ignore, block changes outside narrow spec."""
23
24 def walk(orig, self, match, subrepos, unknown, ignored, full=True,
25 narrowonly=True):
26 if narrowonly:
27 narrowmatch = repo.narrowmatch()
28 match = matchmod.intersectmatchers(match, narrowmatch)
29 return orig(self, match, subrepos, unknown, ignored, full)
30
31 extensions.wrapfunction(dirstate.dirstate, 'walk', walk)
32
33 # Prevent adding files that are outside the sparse checkout
34 editfuncs = ['normal', 'add', 'normallookup', 'copy', 'remove', 'merge']
35 for func in editfuncs:
36 def _wrapper(orig, self, *args):
37 dirstate = repo.dirstate
38 narrowmatch = repo.narrowmatch()
39 for f in args:
40 if f is not None and not narrowmatch(f) and f not in dirstate:
41 raise error.Abort(_("cannot track '%s' - it is outside " +
42 "the narrow clone") % f)
43 return orig(self, *args)
44 extensions.wrapfunction(dirstate.dirstate, func, _wrapper)
45
46 def filterrebuild(orig, self, parent, allfiles, changedfiles=None):
47 if changedfiles is None:
48 # Rebuilding entire dirstate, let's filter allfiles to match the
49 # narrowspec.
50 allfiles = [f for f in allfiles if repo.narrowmatch()(f)]
51 orig(self, parent, allfiles, changedfiles)
52
53 extensions.wrapfunction(dirstate.dirstate, 'rebuild', filterrebuild)
54
55 def _narrowbackupname(backupname):
56 assert 'dirstate' in backupname
57 return backupname.replace('dirstate', narrowspec.FILENAME)
58
59 def restorebackup(orig, self, tr, backupname):
60 self._opener.rename(_narrowbackupname(backupname), narrowspec.FILENAME,
61 checkambig=True)
62 orig(self, tr, backupname)
63
64 extensions.wrapfunction(dirstate.dirstate, 'restorebackup', restorebackup)
65
66 def savebackup(orig, self, tr, backupname):
67 orig(self, tr, backupname)
68
69 narrowbackupname = _narrowbackupname(backupname)
70 self._opener.tryunlink(narrowbackupname)
71 hgutil.copyfile(self._opener.join(narrowspec.FILENAME),
72 self._opener.join(narrowbackupname), hardlink=True)
73
74 extensions.wrapfunction(dirstate.dirstate, 'savebackup', savebackup)
75
76 def clearbackup(orig, self, tr, backupname):
77 orig(self, tr, backupname)
78 self._opener.unlink(_narrowbackupname(backupname))
79
80 extensions.wrapfunction(dirstate.dirstate, 'clearbackup', clearbackup)