hgext/sparse.py
changeset 33373 fb320398a21c
parent 33372 4481f1fd27b1
child 33374 4dc04cdf2520
equal deleted inserted replaced
33372:4481f1fd27b1 33373:fb320398a21c
    80     commands,
    80     commands,
    81     dirstate,
    81     dirstate,
    82     error,
    82     error,
    83     extensions,
    83     extensions,
    84     hg,
    84     hg,
    85     localrepo,
       
    86     match as matchmod,
    85     match as matchmod,
    87     registrar,
    86     registrar,
    88     sparse,
    87     sparse,
    89     util,
    88     util,
    90 )
    89 )
   103 
   102 
   104     _setupclone(ui)
   103     _setupclone(ui)
   105     _setuplog(ui)
   104     _setuplog(ui)
   106     _setupadd(ui)
   105     _setupadd(ui)
   107     _setupdirstate(ui)
   106     _setupdirstate(ui)
   108 
       
   109 def reposetup(ui, repo):
       
   110     if not util.safehasattr(repo, 'dirstate'):
       
   111         return
       
   112 
       
   113     if 'dirstate' in repo._filecache:
       
   114         repo.dirstate.repo = repo
       
   115 
   107 
   116 def replacefilecache(cls, propname, replacement):
   108 def replacefilecache(cls, propname, replacement):
   117     """Replace a filecache property with a new class. This allows changing the
   109     """Replace a filecache property with a new class. This allows changing the
   118     cache invalidation condition."""
   110     cache invalidation condition."""
   119     origcls = cls
   111     origcls = cls
   198 def _setupdirstate(ui):
   190 def _setupdirstate(ui):
   199     """Modify the dirstate to prevent stat'ing excluded files,
   191     """Modify the dirstate to prevent stat'ing excluded files,
   200     and to prevent modifications to files outside the checkout.
   192     and to prevent modifications to files outside the checkout.
   201     """
   193     """
   202 
   194 
   203     def _dirstate(orig, repo):
       
   204         dirstate = orig(repo)
       
   205         dirstate.repo = repo
       
   206         return dirstate
       
   207     extensions.wrapfunction(
       
   208         localrepo.localrepository.dirstate, 'func', _dirstate)
       
   209 
       
   210     # The atrocity below is needed to wrap dirstate._ignore. It is a cached
   195     # The atrocity below is needed to wrap dirstate._ignore. It is a cached
   211     # property, which means normal function wrapping doesn't work.
   196     # property, which means normal function wrapping doesn't work.
   212     class ignorewrapper(object):
   197     class ignorewrapper(object):
   213         def __init__(self, orig):
   198         def __init__(self, orig):
   214             self.orig = orig
   199             self.orig = orig
   215             self.origignore = None
   200             self.origignore = None
   216             self.func = None
   201             self.func = None
   217             self.sparsematch = None
   202             self.sparsematch = None
   218 
   203 
   219         def __get__(self, obj, type=None):
   204         def __get__(self, obj, type=None):
   220             repo = obj.repo
       
   221             origignore = self.orig.__get__(obj)
   205             origignore = self.orig.__get__(obj)
   222 
   206 
   223             sparsematch = sparse.matcher(repo)
   207             sparsematch = obj._sparsematcher
   224             if sparsematch.always():
   208             if sparsematch.always():
   225                 return origignore
   209                 return origignore
   226 
   210 
   227             if self.sparsematch != sparsematch or self.origignore != origignore:
   211             if self.sparsematch != sparsematch or self.origignore != origignore:
   228                 self.func = matchmod.unionmatcher([
   212                 self.func = matchmod.unionmatcher([
   239 
   223 
   240     replacefilecache(dirstate.dirstate, '_ignore', ignorewrapper)
   224     replacefilecache(dirstate.dirstate, '_ignore', ignorewrapper)
   241 
   225 
   242     # dirstate.rebuild should not add non-matching files
   226     # dirstate.rebuild should not add non-matching files
   243     def _rebuild(orig, self, parent, allfiles, changedfiles=None):
   227     def _rebuild(orig, self, parent, allfiles, changedfiles=None):
   244         matcher = sparse.matcher(self.repo)
   228         matcher = self._sparsematcher
   245         if not matcher.always():
   229         if not matcher.always():
   246             allfiles = allfiles.matches(matcher)
   230             allfiles = allfiles.matches(matcher)
   247             if changedfiles:
   231             if changedfiles:
   248                 changedfiles = [f for f in changedfiles if matcher(f)]
   232                 changedfiles = [f for f in changedfiles if matcher(f)]
   249 
   233 
   260     editfuncs = ['normal', 'add', 'normallookup', 'copy', 'remove', 'merge']
   244     editfuncs = ['normal', 'add', 'normallookup', 'copy', 'remove', 'merge']
   261     hint = _('include file with `hg debugsparse --include <pattern>` or use ' +
   245     hint = _('include file with `hg debugsparse --include <pattern>` or use ' +
   262              '`hg add -s <file>` to include file directory while adding')
   246              '`hg add -s <file>` to include file directory while adding')
   263     for func in editfuncs:
   247     for func in editfuncs:
   264         def _wrapper(orig, self, *args):
   248         def _wrapper(orig, self, *args):
   265             repo = self.repo
   249             sparsematch = self._sparsematcher
   266             sparsematch = sparse.matcher(repo)
       
   267             if not sparsematch.always():
   250             if not sparsematch.always():
   268                 for f in args:
   251                 for f in args:
   269                     if (f is not None and not sparsematch(f) and
   252                     if (f is not None and not sparsematch(f) and
   270                         f not in self):
   253                         f not in self):
   271                         raise error.Abort(_("cannot add '%s' - it is outside "
   254                         raise error.Abort(_("cannot add '%s' - it is outside "