narrow: only wrap dirstate functions once, instead of per-reposetup
ClosedPublic

Authored by spectral on May 14 2018, 6:53 PM.

Details

Summary

chg will call reposetup multiple times, and we would end up double-wrapping (or
worse) the dirstate functions; this can cause issues like OSError 'No such file
or directory' during rebase operations, when we go to double-delete our
narrowspec backup file.

Diff Detail

Repository
rHG Mercurial
Lint
Automatic diff as part of commit; lint not applicable.
Unit
Automatic diff as part of commit; unit tests not applicable.
spectral created this revision.May 14 2018, 6:53 PM
yuja added a subscriber: yuja.May 16 2018, 8:07 AM

-def setup(repo):
+# Mapping of root:str to repo for repos that have the narrow requirement
+# specified.
+_rootrepomap = {}
+
+def _getrepo(ds):
+ """Check if narrow is enabled for repo associated with ds; return repo."""
+ return _rootrepomap.get(ds._root, None)

This might cause problem on long-running processes such as hgweb and
commandserver.

Instead, maybe we can extract a factory function of repo.dirstate() so that
the narrowrepo can easily override it.

class localrepository(object):
    @repofilecache('dirstate')
    def dirstate(self):
        return self._makedirstate()

...
    class narrowrepository(repo.__class__):
        def _makedirstate(self):
            d = super(...)
            return wrapdirstate(d)
spectral updated this revision to Diff 8744.May 18 2018, 5:53 PM
spectral edited the summary of this revision. (Show Details)
yuja added a comment.May 22 2018, 8:34 AM

Queued, thanks.

  • a/mercurial/localrepo.py +++ b/mercurial/localrepo.py @@ -778,6 +778,9 @@

    @repofilecache('dirstate') def dirstate(self): + return self._makedirstate() + + def _makedirstate(self):

Can you add a docstring so we wouldn't remove this function by mistake?

  • # Prevent adding files that are outside the sparse checkout
  • editfuncs = ['normal', 'add', 'normallookup', 'copy', 'remove', 'merge']

+ @_editfunc
+ def remove(self, *args):
+ return super(narrowdirstate, self).remove(*args)
+
+ @_editfunc
+ def remove(self, *args):
+ return super(narrowdirstate, self).remove(*args)

s/remove/merge/ the last function in flight.

This revision was automatically updated to reflect the committed changes.