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
# narrowrepo.py - repository which supports narrow revlogs, lazy loading
#
# Copyright 2017 Google, Inc.
#
# This software may be used and distributed according to the terms of the
# GNU General Public License version 2 or any later version.
from __future__ import absolute_import
from mercurial import (
bundlerepo,
localrepo,
match as matchmod,
scmutil,
)
from .. import (
share,
)
from . import (
narrowrevlog,
narrowspec,
)
requirement = 'narrowhg'
def wrappostshare(orig, sourcerepo, destrepo, **kwargs):
orig(sourcerepo, destrepo, **kwargs)
if requirement in sourcerepo.requirements:
with destrepo.wlock():
with destrepo.vfs('shared', 'a') as fp:
fp.write(narrowspec.FILENAME + '\n')
def unsharenarrowspec(orig, ui, repo, repopath):
if (requirement in repo.requirements
and repo.path == repopath and repo.shared()):
srcrepo = share._getsrcrepo(repo)
with srcrepo.vfs(narrowspec.FILENAME) as f:
spec = f.read()
with repo.vfs(narrowspec.FILENAME, 'w') as f:
f.write(spec)
return orig(ui, repo, repopath)
def wraprepo(repo, opts_narrow):
"""Enables narrow clone functionality on a single local repository."""
cacheprop = localrepo.storecache
if isinstance(repo, bundlerepo.bundlerepository):
# We have to use a different caching property decorator for
# bundlerepo because storecache blows up in strange ways on a
# bundlerepo. Fortunately, there's no risk of data changing in
# a bundlerepo.
cacheprop = lambda name: localrepo.unfilteredpropertycache
class narrowrepository(repo.__class__):
def _constructmanifest(self):
manifest = super(narrowrepository, self)._constructmanifest()
narrowrevlog.makenarrowmanifestrevlog(manifest, repo)
return manifest
@cacheprop('00manifest.i')
def manifestlog(self):
mfl = super(narrowrepository, self).manifestlog
narrowrevlog.makenarrowmanifestlog(mfl, self)
return mfl
def file(self, f):
fl = super(narrowrepository, self).file(f)
narrowrevlog.makenarrowfilelog(fl, self.narrowmatch())
return fl
@localrepo.repofilecache(narrowspec.FILENAME)
def narrowpats(self):
return narrowspec.load(self)
@localrepo.repofilecache(narrowspec.FILENAME)
def _narrowmatch(self):
include, exclude = self.narrowpats
if not opts_narrow and not include and not exclude:
return matchmod.always(self.root, '')
return narrowspec.match(self.root, include=include, exclude=exclude)
# TODO(martinvonz): make this property-like instead?
def narrowmatch(self):
return self._narrowmatch
def setnarrowpats(self, newincludes, newexcludes):
narrowspec.save(self, newincludes, newexcludes)
self.invalidate(clearfilecache=True)
# I'm not sure this is the right place to do this filter.
# context._manifestmatches() would probably be better, or perhaps
# move it to a later place, in case some of the callers do want to know
# which directories changed. This seems to work for now, though.
def status(self, *args, **kwargs):
s = super(narrowrepository, self).status(*args, **kwargs)
narrowmatch = self.narrowmatch()
modified = filter(narrowmatch, s.modified)
added = filter(narrowmatch, s.added)
removed = filter(narrowmatch, s.removed)
deleted = filter(narrowmatch, s.deleted)
unknown = filter(narrowmatch, s.unknown)
ignored = filter(narrowmatch, s.ignored)
clean = filter(narrowmatch, s.clean)
return scmutil.status(modified, added, removed, deleted, unknown,
ignored, clean)
repo.__class__ = narrowrepository