[PATCH] tests: stabilize change for handling not quoting non-empty-directory
# HG changeset patch # User Matt Harbison # Date 1536808259 14400 # Wed Sep 12 23:10:59 2018 -0400 # Node ID c8514f858788ffebee5f5e01a24d20e00e9d68a8 # Parent 5e78c100a21586dfdc622a86537c0a0231652e1d tests: stabilize change for handling not quoting non-empty-directory The change originated in cb1329738d64. I suspect the problem is with the combination of (re) and the '\' to '/' retry on Windows. I've no idea if py3 on Windows needs the quoting, since it can't even run `hg` with no arguments. (It's dying somewhere on the ctype declarations when win32.py is imported.) diff --git a/tests/test-merge1.t b/tests/test-merge1.t --- a/tests/test-merge1.t +++ b/tests/test-merge1.t @@ -30,7 +30,7 @@ of the files in a commit we're updating $ mkdir b && touch b/nonempty $ hg up - abort: Unlinking directory not permitted: '?\$TESTTMP/t/b'? (re) (windows !) + abort: Unlinking directory not permitted: *$TESTTMP/t/b* (glob) (windows !) abort: Directory not empty: '?\$TESTTMP/t/b'? (re) (no-windows !) [255] $ hg ci diff --git a/tests/test-update-names.t b/tests/test-update-names.t --- a/tests/test-update-names.t +++ b/tests/test-update-names.t @@ -50,7 +50,7 @@ make sure that this does not erase untra $ hg st ? name/file $ hg up 1 - abort: Unlinking directory not permitted: '?$TESTTMP/r1/r2/name'? (re) (windows !) + abort: Unlinking directory not permitted: *$TESTTMP/r1/r2/name* (glob) (windows !) abort: Directory not empty: '?\$TESTTMP/r1/r2/name'? (re) (no-windows !) [255] $ cat name/file ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
D4557: hg: don't reuse repo instance after unshare()
indygreg created this revision. Herald added a subscriber: mercurial-devel. Herald added a reviewer: hg-reviewers. REVISION SUMMARY Unsharing a repository is a pretty invasive procedure and fundamentally changes the behavior of the repository. Currently, hg.unshare() calls into localrepository.__init__ to re-initialize the repository instance. This is a bit hacky. And future commits that refactor how localrepository instances are constructed will make this difficult to support. This commit changes unshare() so it constructs a new repo instance once the unshare I/O has completed. It then poisons the old repo instance so any further use will result in error. Surprisingly, nothing in core appears to access a repo instance after it has been unshared! .. api:: ``hg.unshare()`` now poisons the repo instance so it can't be used. It also returns a new repo instance suitable for interacting with the unshared repository. REPOSITORY rHG Mercurial REVISION DETAIL https://phab.mercurial-scm.org/D4557 AFFECTED FILES mercurial/hg.py mercurial/localrepo.py CHANGE DETAILS diff --git a/mercurial/localrepo.py b/mercurial/localrepo.py --- a/mercurial/localrepo.py +++ b/mercurial/localrepo.py @@ -2503,3 +2503,28 @@ b'layout') scmutil.writerequires(hgvfs, requirements) + +def poisonrepository(repo): +"""Poison a repository instance so it can no longer be used.""" +# Perform any cleanup on the instance. +repo.close() + +# Our strategy is to replace the type of the object with one that +# has all attribute lookups result in error. +# +# But we have to allow the close() method because some constructors +# of repos call close() on repo references. +class poisonedrepository(object): +def __getattribute__(self, item): +if item == r'close': +return object.__getattribute__(self, item) + +raise error.ProgrammingError('repo instances should not be used ' + 'after unshare') + +def close(self): +pass + +# We may have a repoview, which intercepts __setattr__. So be sure +# we operate at the lowest level possible. +object.__setattr__(repo, r'__class__', poisonedrepository) diff --git a/mercurial/hg.py b/mercurial/hg.py --- a/mercurial/hg.py +++ b/mercurial/hg.py @@ -307,6 +307,11 @@ """convert a shared repository to a normal one Copy the store data to the repo and remove the sharedpath data. + +Returns a new repository object representing the unshared repository. + +The passed repository object is not usable after this function is +called. """ destlock = lock = None @@ -329,16 +334,22 @@ destlock and destlock.release() lock and lock.release() -# update store, spath, svfs and sjoin of repo -repo.unfiltered().__init__(repo.baseui, repo.root) +# Removing share changes some fundamental properties of the repo instance. +# So we instantiate a new repo object and operate on it rather than +# try to keep the existing repo usable. +newrepo = repository(repo.baseui, repo.root, create=False) # TODO: figure out how to access subrepos that exist, but were previously # removed from .hgsub -c = repo['.'] +c = newrepo['.'] subs = c.substate for s in sorted(subs): c.sub(s).unshare() +localrepo.poisonrepository(repo) + +return newrepo + def postshare(sourcerepo, destrepo, bookmarks=True, defaultpath=None): """Called after a new shared repo is created. To: indygreg, #hg-reviewers Cc: mercurial-devel ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
D4555: bundlerepo: dynamically create repository type from base repository
indygreg created this revision. Herald added a subscriber: mercurial-devel. Herald added a reviewer: hg-reviewers. REVISION SUMMARY Previously, bundlerepository inherited from localrepo.localrepository. You simply instantiated a bundlerepository and its __init__ called localrepo.localrepository.__init__. Things were simple. Unfortunately, this strategy is limiting because it assumes that the base repository is a localrepository instance. And it assumes various properties of localrepository, such as the arguments its __init__ takes. And it prevents us from changing behavior of localrepository.__init__ without also having to change derived classes. Previous and ongoing work to abstract storage revealed these limitations. This commit changes the initialization strategy of bundle repositories to dynamically create a type to represent the repository. Instead of a static type, we instantiate a new local repo instance via localrepo.instance(). We then combine its __class__ with bundlerepository to produce a new type. This ensures that no matter how localrepo.instance() decides to create a repository object, we can derive a bundle repo object from it. i.e. localrepo.instance() could return a type that isn't a localrepository and it would "just work." Well, it would "just work" if bundlerepository's custom implementations only accessed attributes in the documented repository interface. I'm pretty sure it violates the interface contract in a handful of places. But we can worry about that another day. This change gets us closer to doing more clever things around instantiating repository instances without having to worry about teaching bundlerepository about them. .. api:: ``bundlerepo.bundlerepository`` is no longer usable on its own. The class is combined with the class of the base repository it is associated with at run-time. New bundlerepository instances can be obtained by calling ``bundlerepo.instance()`` or ``bundlerepo.makebundlerepository()``. REPOSITORY rHG Mercurial REVISION DETAIL https://phab.mercurial-scm.org/D4555 AFFECTED FILES mercurial/bundlerepo.py CHANGE DETAILS diff --git a/mercurial/bundlerepo.py b/mercurial/bundlerepo.py --- a/mercurial/bundlerepo.py +++ b/mercurial/bundlerepo.py @@ -255,33 +255,27 @@ pass return filespos -class bundlerepository(localrepo.localrepository): +class bundlerepository(object): """A repository instance that is a union of a local repo and a bundle. Instances represent a read-only repository composed of a local repository with the contents of a bundle file applied. The repository instance is conceptually similar to the state of a repository after an ``hg unbundle`` operation. However, the contents of the bundle are never applied to the actual base repository. + +Instances constructed directly are not usable as repository objects. +Use instance() or makebundlerepository() to create instances. """ -def __init__(self, ui, repopath, bundlepath): -self._tempparent = None -try: -localrepo.localrepository.__init__(self, ui, repopath) -except error.RepoError: -self._tempparent = pycompat.mkdtemp() -localrepo.instance(ui, self._tempparent, create=True) -localrepo.localrepository.__init__(self, ui, self._tempparent) +def __init__(self, bundlepath, url, tempparent): +self._tempparent = tempparent +self._url = url + self.ui.setconfig('phases', 'publish', False, 'bundlerepo') -if repopath: -self._url = 'bundle:' + util.expandpath(repopath) + '+' + bundlepath -else: -self._url = 'bundle:' + bundlepath - self.tempfile = None f = util.posixfile(bundlepath, "rb") -bundle = exchange.readbundle(ui, f, bundlepath) +bundle = exchange.readbundle(self.ui, f, bundlepath) if isinstance(bundle, bundle2.unbundle20): self._bundlefile = bundle @@ -311,7 +305,7 @@ if bundle.compressed(): f = self._writetempbundle(bundle.read, '.hg10un', header='HG10UN') -bundle = exchange.readbundle(ui, f, bundlepath, self.vfs) +bundle = exchange.readbundle(self.ui, f, bundlepath, self.vfs) self._bundlefile = bundle self._cgunpacker = bundle @@ -484,7 +478,41 @@ def makebundlerepository(ui, repopath, bundlepath): """Make a bundle repository object based on repo and bundle paths.""" -return bundlerepository(ui, repopath, bundlepath) +if repopath: +url = 'bundle:%s+%s' % (util.expandpath(repopath), bundlepath) +else: +url = 'bundle:%s' % bundlepath + +# Because we can't make any guarantees about the type of the base +# repository, we can't have a static class
D4556: unionrepo: dynamically create repository type from base repository
indygreg created this revision. Herald added a subscriber: mercurial-devel. Herald added a reviewer: hg-reviewers. REVISION SUMMARY This is basically the same thing we just did for bundlerepo except for union repositories. .. api:: ``unionrepo.unionrepository()`` is no longer usable on its own. To instantiate an instance, call ``unionrepo.instance()`` or ``unionrepo.makeunionrepository()``. REPOSITORY rHG Mercurial REVISION DETAIL https://phab.mercurial-scm.org/D4556 AFFECTED FILES mercurial/unionrepo.py CHANGE DETAILS diff --git a/mercurial/unionrepo.py b/mercurial/unionrepo.py --- a/mercurial/unionrepo.py +++ b/mercurial/unionrepo.py @@ -192,15 +192,18 @@ def canpush(self): return False -class unionrepository(localrepo.localrepository): -def __init__(self, ui, path, path2): -localrepo.localrepository.__init__(self, ui, path) +class unionrepository(object): +"""Represents the union of data in 2 repositories. + +Instances are not usable if constructed directly. Use ``instance()`` +or ``makeunionrepository()`` to create a usable instance. +""" +def __init__(self, repo2, url): +self.repo2 = repo2 +self._url = url + self.ui.setconfig('phases', 'publish', False, 'unionrepo') -self._url = 'union:%s+%s' % (util.expandpath(path), - util.expandpath(path2)) -self.repo2 = localrepo.localrepository(ui, path2) - @localrepo.unfilteredpropertycache def changelog(self): return unionchangelog(self.svfs, self.repo2.svfs) @@ -260,4 +263,22 @@ repopath, repopath2 = s else: repopath, repopath2 = parentpath, path -return unionrepository(ui, repopath, repopath2) + +return makeunionrepository(ui, repopath, repopath2) + +def makeunionrepository(ui, repopath1, repopath2): +"""Make a union repository object from 2 local repo paths.""" +repo1 = localrepo.instance(ui, repopath1, create=False) +repo2 = localrepo.instance(ui, repopath2, create=False) + +url = 'union:%s+%s' % (util.expandpath(repopath1), + util.expandpath(repopath2)) + +class derivedunionrepository(unionrepository, repo1.__class__): +pass + +repo = repo1 +repo.__class__ = derivedunionrepository +unionrepository.__init__(repo1, repo2, url) + +return repo To: indygreg, #hg-reviewers Cc: mercurial-devel ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
D4554: bundlerepo: factor out code for instantiating a bundle repository
indygreg created this revision. Herald added a subscriber: mercurial-devel. Herald added a reviewer: hg-reviewers. REVISION SUMMARY This code will soon become a bit more complicated. So extract to its own function. And change both instantiators of bundlerepository to use it. REPOSITORY rHG Mercurial REVISION DETAIL https://phab.mercurial-scm.org/D4554 AFFECTED FILES mercurial/bundlerepo.py CHANGE DETAILS diff --git a/mercurial/bundlerepo.py b/mercurial/bundlerepo.py --- a/mercurial/bundlerepo.py +++ b/mercurial/bundlerepo.py @@ -479,7 +479,12 @@ repopath, bundlename = s else: repopath, bundlename = parentpath, path -return bundlerepository(ui, repopath, bundlename) + +return makebundlerepository(ui, repopath, bundlename) + +def makebundlerepository(ui, repopath, bundlepath): +"""Make a bundle repository object based on repo and bundle paths.""" +return bundlerepository(ui, repopath, bundlepath) class bundletransactionmanager(object): def transaction(self): @@ -588,8 +593,10 @@ bundle = None if not localrepo: # use the created uncompressed bundlerepo -localrepo = bundlerepo = bundlerepository(repo.baseui, repo.root, - fname) +localrepo = bundlerepo = makebundlerepository(repo. baseui, + repo.root, + fname) + # this repo contains local and peer now, so filter out local again common = repo.heads() if localrepo: To: indygreg, #hg-reviewers Cc: mercurial-devel ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
D4553: bundlerepo: pass create=True
indygreg created this revision. Herald added a subscriber: mercurial-devel. Herald added a reviewer: hg-reviewers. REVISION SUMMARY I don't want to know how this came to be. Maybe a holdover from the days before Python had a bool type? REPOSITORY rHG Mercurial REVISION DETAIL https://phab.mercurial-scm.org/D4553 AFFECTED FILES mercurial/bundlerepo.py CHANGE DETAILS diff --git a/mercurial/bundlerepo.py b/mercurial/bundlerepo.py --- a/mercurial/bundlerepo.py +++ b/mercurial/bundlerepo.py @@ -270,7 +270,7 @@ localrepo.localrepository.__init__(self, ui, repopath) except error.RepoError: self._tempparent = pycompat.mkdtemp() -localrepo.instance(ui, self._tempparent, 1) +localrepo.instance(ui, self._tempparent, create=True) localrepo.localrepository.__init__(self, ui, self._tempparent) self.ui.setconfig('phases', 'publish', False, 'bundlerepo') To: indygreg, #hg-reviewers Cc: mercurial-devel ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
D4552: shelve: use bundlerepo.instance() to construct a repo object
indygreg created this revision. Herald added a subscriber: mercurial-devel. Herald added a reviewer: hg-reviewers. REVISION SUMMARY The instance() functions are preferred over cls.__init__ for creating repo instances. It doesn't really matter now. But future commits will refactor the bundlerepository class in ways that will cause the old way to break. REPOSITORY rHG Mercurial REVISION DETAIL https://phab.mercurial-scm.org/D4552 AFFECTED FILES hgext/shelve.py CHANGE DETAILS diff --git a/hgext/shelve.py b/hgext/shelve.py --- a/hgext/shelve.py +++ b/hgext/shelve.py @@ -152,8 +152,10 @@ fp.close() def bundlerepo(self): -return bundlerepo.bundlerepository(self.repo.baseui, self.repo.root, - self.vfs.join(self.fname)) +path = self.vfs.join(self.fname) +return bundlerepo.instance(self.repo.baseui, + 'bundle://%s+%s' % (self.repo.root, path)) + def writebundle(self, bases, node): cgversion = changegroup.safeversion(self.repo) if cgversion == '01': To: indygreg, #hg-reviewers Cc: mercurial-devel ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
D4346: hg: wrap the highest layer in the `hg` script possible in trace event
This revision was automatically updated to reflect the committed changes. Closed by commit rHG5e78c100a215: hg: wrap the highest layer in the `hg` script possible in trace event (authored by durin42, committed by ). REPOSITORY rHG Mercurial CHANGES SINCE LAST UPDATE https://phab.mercurial-scm.org/D4346?vs=10620=10983 REVISION DETAIL https://phab.mercurial-scm.org/D4346 AFFECTED FILES hg CHANGE DETAILS diff --git a/hg b/hg --- a/hg +++ b/hg @@ -27,15 +27,17 @@ libdir = os.path.abspath(libdir) sys.path.insert(0, libdir) -# enable importing on demand to reduce startup time -try: -if sys.version_info[0] < 3 or sys.version_info >= (3, 6): -import hgdemandimport; hgdemandimport.enable() -except ImportError: -sys.stderr.write("abort: couldn't find mercurial libraries in [%s]\n" % - ' '.join(sys.path)) -sys.stderr.write("(check your install and PYTHONPATH)\n") -sys.exit(-1) +from hgdemandimport import tracing +with tracing.log('hg script'): +# enable importing on demand to reduce startup time +try: +if sys.version_info[0] < 3 or sys.version_info >= (3, 6): +import hgdemandimport; hgdemandimport.enable() +except ImportError: +sys.stderr.write("abort: couldn't find mercurial libraries in [%s]\n" % + ' '.join(sys.path)) +sys.stderr.write("(check your install and PYTHONPATH)\n") +sys.exit(-1) -from mercurial import dispatch -dispatch.run() +from mercurial import dispatch +dispatch.run() To: durin42, #hg-reviewers, indygreg Cc: indygreg, mercurial-devel ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
D4549: localrepo: move check for existing repo into createrepository()
This revision was automatically updated to reflect the committed changes. Closed by commit rHGe471cb2852ea: localrepo: move check for existing repo into createrepository() (authored by martinvonz, committed by ). REPOSITORY rHG Mercurial CHANGES SINCE LAST UPDATE https://phab.mercurial-scm.org/D4549?vs=10977=10981 REVISION DETAIL https://phab.mercurial-scm.org/D4549 AFFECTED FILES mercurial/localrepo.py CHANGE DETAILS diff --git a/mercurial/localrepo.py b/mercurial/localrepo.py --- a/mercurial/localrepo.py +++ b/mercurial/localrepo.py @@ -2378,12 +2378,7 @@ def instance(ui, path, create, intents=None, createopts=None): if create: -vfs = vfsmod.vfs(path, expandpath=True, realpath=True) - -if vfs.exists('.hg'): -raise error.RepoError(_('repository %s already exists') % path) - -createrepository(ui, vfs, createopts=createopts) +createrepository(ui, path, createopts=createopts) return localrepository(ui, util.urllocalpath(path), intents=intents) @@ -2459,10 +2454,10 @@ return {k: v for k, v in createopts.items() if k not in known} -def createrepository(ui, wdirvfs, createopts=None): +def createrepository(ui, path, createopts=None): """Create a new repository in a vfs. -``wdirvfs`` is a vfs instance pointing at the working directory. +``path`` path to the new repo's working directory. ``createopts`` options for the new repository. """ createopts = createopts or {} @@ -2481,10 +2476,14 @@ requirements = newreporequirements(ui, createopts=createopts) +wdirvfs = vfsmod.vfs(path, expandpath=True, realpath=True) if not wdirvfs.exists(): wdirvfs.makedirs() hgvfs = vfsmod.vfs(wdirvfs.join(b'.hg')) +if hgvfs.exists(): +raise error.RepoError(_('repository %s already exists') % path) + hgvfs.makedir(notindexed=True) if b'store' in requirements: To: martinvonz, #hg-reviewers Cc: pulkit, mercurial-devel ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
D4550: localrepo: use urllocalpath() for path to create repo too
This revision was automatically updated to reflect the committed changes. Closed by commit rHG76b58f240821: localrepo: use urllocalpath() for path to create repo too (authored by martinvonz, committed by ). REPOSITORY rHG Mercurial CHANGES SINCE LAST UPDATE https://phab.mercurial-scm.org/D4550?vs=10978=10982 REVISION DETAIL https://phab.mercurial-scm.org/D4550 AFFECTED FILES mercurial/localrepo.py CHANGE DETAILS diff --git a/mercurial/localrepo.py b/mercurial/localrepo.py --- a/mercurial/localrepo.py +++ b/mercurial/localrepo.py @@ -2377,10 +2377,11 @@ return os.path.join(base, name.replace('journal', 'undo', 1)) def instance(ui, path, create, intents=None, createopts=None): +localpath = util.urllocalpath(path) if create: -createrepository(ui, path, createopts=createopts) +createrepository(ui, localpath, createopts=createopts) -return localrepository(ui, util.urllocalpath(path), intents=intents) +return localrepository(ui, localpath, intents=intents) def islocal(path): return True To: martinvonz, #hg-reviewers Cc: mercurial-devel ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
D2883: revlogstore: create and implement an interface for repo files storage
indygreg abandoned this revision. indygreg added a comment. I'm not actively working on this. REPOSITORY rHG Mercurial REVISION DETAIL https://phab.mercurial-scm.org/D2883 To: indygreg, #hg-reviewers Cc: mharbison72, mercurial-devel ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
Re: [PATCH] py3: add b'' to some run-tests.py strings for Windows
On Wed, Sep 12, 2018 at 6:36 PM Matt Harbison wrote: > # HG changeset patch > # User Matt Harbison > # Date 1536802328 14400 > # Wed Sep 12 21:32:08 2018 -0400 > # Node ID dfb052baace5510876f56e67f49b082273ebb858 > # Parent 2105ed5ef206052a5ff093fba8cbd44bef470f20 > py3: add b'' to some run-tests.py strings for Windows > Queued, thanks. > > Things go seriously off the rails after this, so there may be more that are > missing. > > # skip-blame since these are just converting to bytes literals > > diff --git a/tests/run-tests.py b/tests/run-tests.py > --- a/tests/run-tests.py > +++ b/tests/run-tests.py > @@ -3118,8 +3118,8 @@ class TestRunner(object): > def _checktools(self): > """Ensure tools required to run tests are present.""" > for p in self.REQUIREDTOOLS: > -if os.name == 'nt' and not p.endswith('.exe'): > -p += '.exe' > +if os.name == 'nt' and not p.endswith(b'.exe'): > +p += b'.exe' > found = self._findprogram(p) > if found: > vlog("# Found prerequisite", p, "at", found) > ___ > Mercurial-devel mailing list > Mercurial-devel@mercurial-scm.org > https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel > ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
[PATCH] py3: add b'' to some run-tests.py strings for Windows
# HG changeset patch # User Matt Harbison # Date 1536802328 14400 # Wed Sep 12 21:32:08 2018 -0400 # Node ID dfb052baace5510876f56e67f49b082273ebb858 # Parent 2105ed5ef206052a5ff093fba8cbd44bef470f20 py3: add b'' to some run-tests.py strings for Windows Things go seriously off the rails after this, so there may be more that are missing. # skip-blame since these are just converting to bytes literals diff --git a/tests/run-tests.py b/tests/run-tests.py --- a/tests/run-tests.py +++ b/tests/run-tests.py @@ -3118,8 +3118,8 @@ class TestRunner(object): def _checktools(self): """Ensure tools required to run tests are present.""" for p in self.REQUIREDTOOLS: -if os.name == 'nt' and not p.endswith('.exe'): -p += '.exe' +if os.name == 'nt' and not p.endswith(b'.exe'): +p += b'.exe' found = self._findprogram(p) if found: vlog("# Found prerequisite", p, "at", found) ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
D4551: wireprotov1peer: forward __name__ of wrapped method in batchable decorator
This revision was automatically updated to reflect the committed changes. Closed by commit rHGf15a587d2dfc: wireprotov1peer: forward __name__ of wrapped method in batchable decorator (authored by durin42, committed by ). REPOSITORY rHG Mercurial CHANGES SINCE LAST UPDATE https://phab.mercurial-scm.org/D4551?vs=10979=10980 REVISION DETAIL https://phab.mercurial-scm.org/D4551 AFFECTED FILES mercurial/wireprotov1peer.py CHANGE DETAILS diff --git a/mercurial/wireprotov1peer.py b/mercurial/wireprotov1peer.py --- a/mercurial/wireprotov1peer.py +++ b/mercurial/wireprotov1peer.py @@ -64,6 +64,7 @@ encresref.set(self._submitone(cmd, encargsorres)) return next(batchable) setattr(plain, 'batchable', f) +setattr(plain, '__name__', f.__name__) return plain class future(object): To: durin42, #hg-reviewers Cc: mercurial-devel ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
D4546: tests: handle Python 3 not quoting non-empty-directory error
mharbison72 added a comment. This motivated me to install py3, and give it a try. But the test runner keeps crashing on str/bytes issues. I fixed a couple, but it looks like treating everything as bytes can be a problem, since environment stuff internally wants to uppercase, which wants a str (apparently). $ /c/Program\ Files/Python37/python run-tests.py --local test-update-names.t Traceback (most recent call last): File "run-tests.py", line 3194, in sys.exit(runner.run(sys.argv[1:])) File "run-tests.py", line 2475, in run self._checktools() File "run-tests.py", line 3123, in _checktools found = self._findprogram(p) File "run-tests.py", line 3112, in _findprogram for p in osenvironb.get(b'PATH', dpb).split(sepb): File "c:\Program Files\Python37\lib\_collections_abc.py", line 660, in get return self[key] File "c:\Program Files\Python37\lib\os.py", line 675, in __getitem__ value = self._data[self.encodekey(key)] File "c:\Program Files\Python37\lib\os.py", line 744, in encodekey return encode(key).upper() File "c:\Program Files\Python37\lib\os.py", line 739, in check_str raise TypeError("str expected, not %s" % type(value).__name__) TypeError: str expected, not bytes I "fixed" that with the following... @@ -3107,10 +3107,12 @@ class TestRunner(object): def _findprogram(self, program): """Search PATH for a executable program""" -dpb = _bytespath(os.defpath) -sepb = _bytespath(os.pathsep) -for p in osenvironb.get(b'PATH', dpb).split(sepb): -name = os.path.join(p, program) +#dpb = _bytespath(os.defpath) +#sepb = _bytespath(os.pathsep) +dpb = os.defpath +sepb = os.pathsep +for p in osenvironb.get('PATH', dpb).split(sepb): +name = os.path.join(_bytespath(p), program) if os.name == 'nt' or os.access(name, os.X_OK): return name return None ... and then got a crash with a warning that the Windows bytes API is deprecated. $ /c/Program\ Files/Python37/python run-tests.py --local test-update-names.t run-tests.py:2491: DeprecationWarning: The Windows bytes API has been deprecated, use Unicode filenames instead os, 'getcwdb', os.getcwd)() Traceback (most recent call last): File "run-tests.py", line 3196, in sys.exit(runner.run(sys.argv[1:])) File "run-tests.py", line 2480, in run result = self._run(testdescs) File "run-tests.py", line 2491, in _run os, 'getcwdb', os.getcwd)() File "c:\Program Files\Python37\lib\os.py", line 682, in __setitem__ key = self.encodekey(key) File "c:\Program Files\Python37\lib\os.py", line 744, in encodekey return encode(key).upper() File "c:\Program Files\Python37\lib\os.py", line 739, in check_str raise TypeError("str expected, not %s" % type(value).__name__) TypeError: str expected, not bytes REPOSITORY rHG Mercurial REVISION DETAIL https://phab.mercurial-scm.org/D4546 To: durin42, #hg-reviewers, pulkit Cc: mharbison72, mercurial-devel ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
D4551: wireprotov1peer: forward __name__ of wrapped method in batchable decorator
durin42 created this revision. Herald added a subscriber: mercurial-devel. Herald added a reviewer: hg-reviewers. REVISION SUMMARY Not required, but clarifies debugging when the going gets really tough. REPOSITORY rHG Mercurial REVISION DETAIL https://phab.mercurial-scm.org/D4551 AFFECTED FILES mercurial/wireprotov1peer.py CHANGE DETAILS diff --git a/mercurial/wireprotov1peer.py b/mercurial/wireprotov1peer.py --- a/mercurial/wireprotov1peer.py +++ b/mercurial/wireprotov1peer.py @@ -64,6 +64,7 @@ encresref.set(self._submitone(cmd, encargsorres)) return next(batchable) setattr(plain, 'batchable', f) +setattr(plain, '__name__', f.__name__) return plain class future(object): To: durin42, #hg-reviewers Cc: mercurial-devel ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
D4550: localrepo: use urllocalpath() for path to create repo too
martinvonz updated this revision to Diff 10978. REPOSITORY rHG Mercurial CHANGES SINCE LAST UPDATE https://phab.mercurial-scm.org/D4550?vs=10974=10978 REVISION DETAIL https://phab.mercurial-scm.org/D4550 AFFECTED FILES mercurial/localrepo.py CHANGE DETAILS diff --git a/mercurial/localrepo.py b/mercurial/localrepo.py --- a/mercurial/localrepo.py +++ b/mercurial/localrepo.py @@ -2377,10 +2377,11 @@ return os.path.join(base, name.replace('journal', 'undo', 1)) def instance(ui, path, create, intents=None, createopts=None): +localpath = util.urllocalpath(path) if create: -createrepository(ui, path, createopts=createopts) +createrepository(ui, localpath, createopts=createopts) -return localrepository(ui, util.urllocalpath(path), intents=intents) +return localrepository(ui, localpath, intents=intents) def islocal(path): return True To: martinvonz, #hg-reviewers Cc: mercurial-devel ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
D4549: localrepo: move check for existing repo into createrepository()
martinvonz updated this revision to Diff 10977. REPOSITORY rHG Mercurial CHANGES SINCE LAST UPDATE https://phab.mercurial-scm.org/D4549?vs=10973=10977 REVISION DETAIL https://phab.mercurial-scm.org/D4549 AFFECTED FILES mercurial/localrepo.py CHANGE DETAILS diff --git a/mercurial/localrepo.py b/mercurial/localrepo.py --- a/mercurial/localrepo.py +++ b/mercurial/localrepo.py @@ -2378,12 +2378,7 @@ def instance(ui, path, create, intents=None, createopts=None): if create: -vfs = vfsmod.vfs(path, expandpath=True, realpath=True) - -if vfs.exists('.hg'): -raise error.RepoError(_('repository %s already exists') % path) - -createrepository(ui, vfs, createopts=createopts) +createrepository(ui, path, createopts=createopts) return localrepository(ui, util.urllocalpath(path), intents=intents) @@ -2459,10 +2454,10 @@ return {k: v for k, v in createopts.items() if k not in known} -def createrepository(ui, wdirvfs, createopts=None): +def createrepository(ui, path, createopts=None): """Create a new repository in a vfs. -``wdirvfs`` is a vfs instance pointing at the working directory. +``path`` path to the new repo's working directory. ``createopts`` options for the new repository. """ createopts = createopts or {} @@ -2481,10 +2476,14 @@ requirements = newreporequirements(ui, createopts=createopts) +wdirvfs = vfsmod.vfs(path, expandpath=True, realpath=True) if not wdirvfs.exists(): wdirvfs.makedirs() hgvfs = vfsmod.vfs(wdirvfs.join(b'.hg')) +if hgvfs.exists(): +raise error.RepoError(_('repository %s already exists') % path) + hgvfs.makedir(notindexed=True) if b'store' in requirements: To: martinvonz, #hg-reviewers Cc: pulkit, mercurial-devel ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
D4548: localrepo: fix a mixmatched arg name in createrepository() docstring
martinvonz updated this revision to Diff 10976. REPOSITORY rHG Mercurial CHANGES SINCE LAST UPDATE https://phab.mercurial-scm.org/D4548?vs=10975=10976 REVISION DETAIL https://phab.mercurial-scm.org/D4548 AFFECTED FILES mercurial/localrepo.py CHANGE DETAILS diff --git a/mercurial/localrepo.py b/mercurial/localrepo.py --- a/mercurial/localrepo.py +++ b/mercurial/localrepo.py @@ -2463,7 +2463,7 @@ """Create a new repository in a vfs. ``wdirvfs`` is a vfs instance pointing at the working directory. -``requirements`` is a set of requirements for the new repository. +``createopts`` options for the new repository. """ createopts = createopts or {} To: martinvonz, #hg-reviewers Cc: mercurial-devel ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
D4436: httppeer: expose capabilities for each command
durin42 added a comment. Hmm. I'm still uneasy about this. Maybe we could make it a dev-mode thing and not be something we depend on long term? REPOSITORY rHG Mercurial REVISION DETAIL https://phab.mercurial-scm.org/D4436 To: indygreg, #hg-reviewers Cc: durin42, mercurial-devel ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
Re: [PATCH] ancestor: remove extra generator from lazyancestors.__iter__()
> On Sep 10, 2018, at 09:15, Yuya Nishihara wrote: > > # HG changeset patch > # User Yuya Nishihara mailto:y...@tcha.org>> > # Date 1536580638 -32400 > # Mon Sep 10 20:57:18 2018 +0900 > # Node ID 4eee6e03686df30cacc8d78f9bd37d4628e478d6 > # Parent 43d92d68ac889eed34e6223bdc0298bc4f056592 > ancestor: remove extra generator from lazyancestors.__iter__() queued, thanks___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
Re: [PATCH] tests: stabilize test-no-symlink
already pushed as 0612e4c6fda0 > On Sep 10, 2018, at 21:16, Matt Harbison wrote: > > # HG changeset patch > # User Matt Harbison > # Date 1536628554 14400 > # Mon Sep 10 21:15:54 2018 -0400 > # Node ID 9f87aa9f809f353d699a2de0d8440386cd007303 > # Parent 98995b689e03fd3d39ace0799d7357d4edba9ef5 > tests: stabilize test-no-symlink > > This goes with 89630d0b3e23. > > diff --git a/tests/test-no-symlinks.t b/tests/test-no-symlinks.t > --- a/tests/test-no-symlinks.t > +++ b/tests/test-no-symlinks.t > @@ -48,7 +48,7 @@ Bundle and extract again > adding manifests > adding file changes > added 2 changesets with 6 changes to 6 files > - new changesets d326ae2d01ee:71d85cf3ba90 > + new changesets d326ae2d01ee:71d85cf3ba90 (2 drafts) > (run 'hg update' to get a working copy) > $ hg update > 5 files updated, 0 files merged, 0 files removed, 0 files unresolved > ___ > Mercurial-devel mailing list > Mercurial-devel@mercurial-scm.org > https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
D4549: localrepo: move check for existing repo into createrepository()
martinvonz added a comment. In https://phab.mercurial-scm.org/D4549#69559, @pulkit wrote: > test-init.t and test-mq.t says hi! Sorry! :( Looks like I forgot to drop the `.hg` argument when I switched from wdirvfs to hgvfs. I'll fix right away. REPOSITORY rHG Mercurial REVISION DETAIL https://phab.mercurial-scm.org/D4549 To: martinvonz, #hg-reviewers Cc: pulkit, mercurial-devel ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
D4548: localrepo: fix a mixmatched arg name in createrepository() docstring
This revision was automatically updated to reflect the committed changes. Closed by commit rHGa64a965b3610: localrepo: fix a mixmatched arg name in createrepository() docstring (authored by martinvonz, committed by ). REPOSITORY rHG Mercurial CHANGES SINCE LAST UPDATE https://phab.mercurial-scm.org/D4548?vs=10972=10975 REVISION DETAIL https://phab.mercurial-scm.org/D4548 AFFECTED FILES mercurial/localrepo.py CHANGE DETAILS diff --git a/mercurial/localrepo.py b/mercurial/localrepo.py --- a/mercurial/localrepo.py +++ b/mercurial/localrepo.py @@ -2463,7 +2463,7 @@ """Create a new repository in a vfs. ``wdirvfs`` is a vfs instance pointing at the working directory. -``requirements`` is a set of requirements for the new repository. +``createopts`` options for the new repository. """ createopts = createopts or {} To: martinvonz, #hg-reviewers Cc: mercurial-devel ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
D4549: localrepo: move check for existing repo into createrepository()
pulkit added a comment. test-init.t and test-mq.t says hi! --- /storage/pulkit/repo/hgpush/tests/test-init.t +++ /storage/pulkit/repo/hgpush/tests/test-init.t.err @@ -99,7 +99,7 @@ test failure $ hg init local - abort: repository local already exists! + abort: File exists: '$TESTTMP/local/.hg' [255] init+push to remote2 @@ -144,14 +144,14 @@ init to existing repo $ hg init -e "\"$PYTHON\" \"$TESTDIR/dummyssh\"" ssh://user@dummy/remote1 - abort: repository remote1 already exists! + abort: File exists: '$TESTTMP/remote1/.hg' abort: could not create remote repo! [255] clone to existing repo $ hg clone -e "\"$PYTHON\" \"$TESTDIR/dummyssh\"" local ssh://user@dummy/remote1 - abort: repository remote1 already exists! + abort: File exists: '$TESTTMP/remote1/.hg' abort: could not create remote repo! [255] ERROR: test-init.t output changed ! --- /storage/pulkit/repo/hgpush/tests/test-mq.t +++ /storage/pulkit/repo/hgpush/tests/test-mq.t.err @@ -154,7 +154,7 @@ guards $ cat .hg/patches/series $ hg qinit -c - abort: repository $TESTTMP/d/.hg/patches already exists! + abort: File exists: '$TESTTMP/d/.hg/patches/.hg' [255] $ cd .. ERROR: test-mq.t output changed REPOSITORY rHG Mercurial REVISION DETAIL https://phab.mercurial-scm.org/D4549 To: martinvonz, #hg-reviewers Cc: pulkit, mercurial-devel ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
D4550: localrepo: use urllocalpath() for path to create repo too
martinvonz created this revision. Herald added a subscriber: mercurial-devel. Herald added a reviewer: hg-reviewers. REVISION SUMMARY It looks like this was lost in https://phab.mercurial-scm.org/rHG7ce9dea3a14a9142dadb2083f34a22834f5e9b70 (localrepo: move repo creation logic out of localrepository.__init__ (API), 2018-09-11). I don't know when it makes a difference (maybe on Windows, since urllocalpath() mentions something about drive letters). REPOSITORY rHG Mercurial REVISION DETAIL https://phab.mercurial-scm.org/D4550 AFFECTED FILES mercurial/localrepo.py CHANGE DETAILS diff --git a/mercurial/localrepo.py b/mercurial/localrepo.py --- a/mercurial/localrepo.py +++ b/mercurial/localrepo.py @@ -2377,10 +2377,11 @@ return os.path.join(base, name.replace('journal', 'undo', 1)) def instance(ui, path, create, intents=None, createopts=None): +localpath = util.urllocalpath(path) if create: -createrepository(ui, path, createopts=createopts) +createrepository(ui, localpath, createopts=createopts) -return localrepository(ui, util.urllocalpath(path), intents=intents) +return localrepository(ui, localpath, intents=intents) def islocal(path): return True To: martinvonz, #hg-reviewers Cc: mercurial-devel ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
D4549: localrepo: move check for existing repo into createrepository()
martinvonz created this revision. Herald added a subscriber: mercurial-devel. Herald added a reviewer: hg-reviewers. REVISION SUMMARY For symmetry with the check for existence of a repo in localrepository.__init__, we should check for the non-existence in createrepository(). We could alternatively move both checks into instance(). REPOSITORY rHG Mercurial REVISION DETAIL https://phab.mercurial-scm.org/D4549 AFFECTED FILES mercurial/localrepo.py CHANGE DETAILS diff --git a/mercurial/localrepo.py b/mercurial/localrepo.py --- a/mercurial/localrepo.py +++ b/mercurial/localrepo.py @@ -2378,12 +2378,7 @@ def instance(ui, path, create, intents=None, createopts=None): if create: -vfs = vfsmod.vfs(path, expandpath=True, realpath=True) - -if vfs.exists('.hg'): -raise error.RepoError(_('repository %s already exists') % path) - -createrepository(ui, vfs, createopts=createopts) +createrepository(ui, path, createopts=createopts) return localrepository(ui, util.urllocalpath(path), intents=intents) @@ -2459,10 +2454,10 @@ return {k: v for k, v in createopts.items() if k not in known} -def createrepository(ui, wdirvfs, createopts=None): +def createrepository(ui, path, createopts=None): """Create a new repository in a vfs. -``wdirvfs`` is a vfs instance pointing at the working directory. +``path`` path to the new repo's working directory. ``createopts`` options for the new repository. """ createopts = createopts or {} @@ -2481,10 +2476,14 @@ requirements = newreporequirements(ui, createopts=createopts) +wdirvfs = vfsmod.vfs(path, expandpath=True, realpath=True) if not wdirvfs.exists(): wdirvfs.makedirs() hgvfs = vfsmod.vfs(wdirvfs.join(b'.hg')) +if hgvfs.exists('.hg'): +raise error.RepoError(_('repository %s already exists') % path) + hgvfs.makedir(notindexed=True) if b'store' in requirements: To: martinvonz, #hg-reviewers Cc: mercurial-devel ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
D4548: localrepo: fix a mixmatches arg name in createrepository() docstring
martinvonz created this revision. Herald added a subscriber: mercurial-devel. Herald added a reviewer: hg-reviewers. REPOSITORY rHG Mercurial REVISION DETAIL https://phab.mercurial-scm.org/D4548 AFFECTED FILES mercurial/localrepo.py CHANGE DETAILS diff --git a/mercurial/localrepo.py b/mercurial/localrepo.py --- a/mercurial/localrepo.py +++ b/mercurial/localrepo.py @@ -2463,7 +2463,7 @@ """Create a new repository in a vfs. ``wdirvfs`` is a vfs instance pointing at the working directory. -``requirements`` is a set of requirements for the new repository. +``createopts`` options for the new repository. """ createopts = createopts or {} To: martinvonz, #hg-reviewers Cc: mercurial-devel ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
mercurial@39557: 10 new changesets
10 new changesets in mercurial: https://www.mercurial-scm.org/repo/hg/rev/7ce9dea3a14a changeset: 39548:7ce9dea3a14a parent: 39546:41aa5dced975 user:Gregory Szorc date:Tue Sep 11 13:46:59 2018 -0700 summary: localrepo: move repo creation logic out of localrepository.__init__ (API) https://www.mercurial-scm.org/repo/hg/rev/089fc0db0954 changeset: 39549:089fc0db0954 user:Gregory Szorc date:Tue Sep 11 17:11:32 2018 -0700 summary: hg: allow extra arguments to be passed to repo creation (API) https://www.mercurial-scm.org/repo/hg/rev/65b5900f30be changeset: 39550:65b5900f30be user:Gregory Szorc date:Tue Sep 11 17:15:35 2018 -0700 summary: hg: recognize include and exclude patterns when cloning https://www.mercurial-scm.org/repo/hg/rev/261f1e8dc300 changeset: 39551:261f1e8dc300 user:Gregory Szorc date:Tue Sep 11 14:16:05 2018 -0700 summary: localrepo: add requirement when narrow files creation option present https://www.mercurial-scm.org/repo/hg/rev/4c807ec07888 changeset: 39552:4c807ec07888 user:Gregory Szorc date:Tue Sep 11 17:20:14 2018 -0700 summary: commands: pass include and exclude options to hg.clone() https://www.mercurial-scm.org/repo/hg/rev/130e5df346d5 changeset: 39553:130e5df346d5 user:Gregory Szorc date:Tue Sep 11 17:21:18 2018 -0700 summary: exchange: support defining narrow file patterns for pull https://www.mercurial-scm.org/repo/hg/rev/841c82d1a973 changeset: 39554:841c82d1a973 user:Gregory Szorc date:Tue Sep 11 16:59:17 2018 -0700 summary: narrow: don't wrap exchange.pull() during clone https://www.mercurial-scm.org/repo/hg/rev/cb675e95a2c2 changeset: 39555:cb675e95a2c2 user:Gregory Szorc date:Tue Sep 11 17:22:15 2018 -0700 summary: hg: write narrow patterns after repo creation https://www.mercurial-scm.org/repo/hg/rev/c8ea5c7ec99d changeset: 39556:c8ea5c7ec99d user:Yuya Nishihara date:Wed Sep 12 22:15:43 2018 +0900 summary: narrowspec: remove parseserverpatterns() which isn't used anymore https://www.mercurial-scm.org/repo/hg/rev/623081f2abc2 changeset: 39557:623081f2abc2 bookmark:@ tag: tip user:Yuya Nishihara date:Wed Sep 12 22:19:29 2018 +0900 summary: narrow: remove hack to write narrowspec to shared .hg directory -- Repository URL: https://www.mercurial-scm.org/repo/hg ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
D4492: wireprotov2: let clients drive delta behavior
indygreg updated this revision to Diff 10971. REPOSITORY rHG Mercurial CHANGES SINCE LAST UPDATE https://phab.mercurial-scm.org/D4492?vs=10805=10971 REVISION DETAIL https://phab.mercurial-scm.org/D4492 AFFECTED FILES mercurial/exchangev2.py mercurial/help/internals/wireprotocolv2.txt mercurial/wireprotov2server.py tests/test-http-protocol.t tests/test-wireproto-command-capabilities.t tests/test-wireproto-command-filedata.t tests/test-wireproto-command-manifestdata.t tests/test-wireproto-exchangev2.t CHANGE DETAILS diff --git a/tests/test-wireproto-exchangev2.t b/tests/test-wireproto-exchangev2.t --- a/tests/test-wireproto-exchangev2.t +++ b/tests/test-wireproto-exchangev2.t @@ -82,6 +82,7 @@ 'parents', 'revision' ]), +'haveparents': True, 'nodes': [ '\x99/Gy\x02\x9a=\xf8\xd0fm\x00\xbb\x92OicN', '\xa9\x88\xfbCX>\x87\x1d\x1e\xd5u\x0e\xe0t\xc6\xd8@\xbb\xbf\xc8', @@ -100,6 +101,7 @@ 'parents', 'revision' ]), +'haveparents': True, 'nodes': [ '+N\xb0s\x19\xbf\xa0w\xa4\n/\x04\x916Y\xae\xf0\xdaB\xda', '\x9a8\x12)\x97\xb3\xac\x97\xbe*\x9a\xa2\xe5V\x83\x83A\xfd\xf2\xcc', @@ -112,6 +114,7 @@ 'parents', 'revision' ]), +'haveparents': True, 'nodes': [ '\x81\x9e%\x8d1\xa5\xe1`f)\xf3e\xbb\x90*\x1b!\xeeB\x16', '\xb1zk\xd3g=\x9a\xb8\xce\xd5\x81\xa2\t\xf6/=\xa5\xccEx', @@ -211,6 +214,7 @@ 'parents', 'revision' ]), +'haveparents': True, 'nodes': [ '\x99/Gy\x02\x9a=\xf8\xd0fm\x00\xbb\x92OicN', '\xa9\x88\xfbCX>\x87\x1d\x1e\xd5u\x0e\xe0t\xc6\xd8@\xbb\xbf\xc8' @@ -226,6 +230,7 @@ 'parents', 'revision' ]), +'haveparents': True, 'nodes': [ '+N\xb0s\x19\xbf\xa0w\xa4\n/\x04\x916Y\xae\xf0\xdaB\xda', '\x9a8\x12)\x97\xb3\xac\x97\xbe*\x9a\xa2\xe5V\x83\x83A\xfd\xf2\xcc' @@ -237,6 +242,7 @@ 'parents', 'revision' ]), +'haveparents': True, 'nodes': [ '\x81\x9e%\x8d1\xa5\xe1`f)\xf3e\xbb\x90*\x1b!\xeeB\x16' ], @@ -317,6 +323,7 @@ 'parents', 'revision' ]), +'haveparents': True, 'nodes': [ '\xec\x80NH\x8c \x88\xc25\t\x9a\x10 u\x13\xbe\xcd\xc3\xdd\xa5', '\x04\\\x7f9\'\xda\x13\xe7Z\xf8\xf0\xe4\xf0HI\xe4a\xa9x\x0f', @@ -333,6 +340,7 @@ 'parents', 'revision' ]), +'haveparents': True, 'nodes': [ '+N\xb0s\x19\xbf\xa0w\xa4\n/\x04\x916Y\xae\xf0\xdaB\xda', '\xc2\xa2\x05\xc8\xb2\xad\xe2J\xf2`b\xe5<\xd5\xbc8\x01\xd6`\xda' @@ -344,6 +352,7 @@ 'parents', 'revision' ]), +'haveparents': True, 'nodes': [ '\x81\x9e%\x8d1\xa5\xe1`f)\xf3e\xbb\x90*\x1b!\xeeB\x16', '\xb1zk\xd3g=\x9a\xb8\xce\xd5\x81\xa2\t\xf6/=\xa5\xccEx', @@ -498,6 +507,7 @@ 'parents', 'revision' ]), +'haveparents': True, 'nodes': [ '\x99/Gy\x02\x9a=\xf8\xd0fm\x00\xbb\x92OicN', '\xa9\x88\xfbCX>\x87\x1d\x1e\xd5u\x0e\xe0t\xc6\xd8@\xbb\xbf\xc8', @@ -516,6 +526,7 @@ 'parents', 'revision' ]), +'haveparents': True, 'nodes': [ '+N\xb0s\x19\xbf\xa0w\xa4\n/\x04\x916Y\xae\xf0\xdaB\xda', '\x9a8\x12)\x97\xb3\xac\x97\xbe*\x9a\xa2\xe5V\x83\x83A\xfd\xf2\xcc', @@ -528,6 +539,7 @@ 'parents', 'revision' ]), +'haveparents': True, 'nodes': [ '\x81\x9e%\x8d1\xa5\xe1`f)\xf3e\xbb\x90*\x1b!\xeeB\x16', '\xb1zk\xd3g=\x9a\xb8\xce\xd5\x81\xa2\t\xf6/=\xa5\xccEx', diff --git a/tests/test-wireproto-command-manifestdata.t b/tests/test-wireproto-command-manifestdata.t --- a/tests/test-wireproto-command-manifestdata.t +++ b/tests/test-wireproto-command-manifestdata.t @@ -248,6 +248,7 @@ ] Requesting revision data works +(haveparents defaults to false, so fulltext is emitted) $ sendhttpv2peer << EOF > command manifestdata @@ -278,6 +279,124 @@ s> \xa1FstatusBok s> \r\n received frame(size=11; request=1; stream=2; streamflags=stream-begin; type=command-response; flags=continuation) + s> 167\r\n + s> _\x01\x00\x01\x00\x02\x001 + s> \xa1Jtotalitems\x01\xa2DnodeTF\xa6r\x1b^\xda\xf0\xea\x04\xb7\x9a\\\xb3!\x88T\xa4\xd2\xab\xa0Lrevisionsize\x19\x01$Y\x01$a\x000879345e39377229634b420c639454156726c6b6\n + s> b\x00819e258d31a5e1606629f365bb902a1b21ee4216\n + s> dir0/c\x00914445346a0ca0629bd47ceb5dfe07e4d4cf2501\n + s> dir0/child0/e\x00bbba6c06b30f443d34ff841bc985c4d0827c6be4\n + s> dir0/child1/f\x0012fc7dcd773b5a0a929ce195228083c6ddc9cec4\n + s> dir0/d\x00538206dc971e521540d6843abfe6d16032f6d426\n + s> \r\n + received frame(size=351; request=1; stream=2; streamflags=; type=command-response; flags=continuation) + s> 8\r\n + s> \x00\x00\x00\x01\x00\x02\x002 + s> \r\n + s> 0\r\n + s> \r\n + received frame(size=0; request=1; stream=2; streamflags=; type=command-response; flags=eos) + response: gen[ +{ +
D4490: wireprotov2: define and implement "filedata" command
indygreg updated this revision to Diff 10969. REPOSITORY rHG Mercurial CHANGES SINCE LAST UPDATE https://phab.mercurial-scm.org/D4490?vs=10803=10969 REVISION DETAIL https://phab.mercurial-scm.org/D4490 AFFECTED FILES mercurial/help/internals/wireprotocolv2.txt mercurial/wireprotov2server.py tests/test-http-protocol.t tests/test-wireproto-command-capabilities.t tests/test-wireproto-command-filedata.t CHANGE DETAILS diff --git a/tests/test-wireproto-command-filedata.t b/tests/test-wireproto-command-filedata.t new file mode 100644 --- /dev/null +++ b/tests/test-wireproto-command-filedata.t @@ -0,0 +1,497 @@ + $ . $TESTDIR/wireprotohelpers.sh + + $ hg init server + $ enablehttpv2 server + $ cd server + $ echo a0 > a + $ echo b0 > b + $ mkdir -p dir0/child0 dir0/child1 dir1 + $ echo c0 > dir0/c + $ echo d0 > dir0/d + $ echo e0 > dir0/child0/e + $ echo f0 > dir0/child1/f + $ hg -q commit -A -m 'commit 0' + + $ echo a1 > a + $ echo d1 > dir0/d + $ hg commit -m 'commit 1' + $ echo f0 > dir0/child1/f + $ hg commit -m 'commit 2' + nothing changed + [1] + + $ hg -q up -r 0 + $ echo a2 > a + $ hg commit -m 'commit 3' + created new head + + $ hg log -G -T '{rev}:{node} {desc}\n' + @ 2:c8757a2ffe552850d1e0dfe60d295ebf64c196d9 commit 3 + | + | o 1:650165e803375748a94df471e5b58d85763e0b29 commit 1 + |/ + o 0:6d85ca1270b377d320098556ba5bfad34a9ee12d commit 0 + + + $ hg --debug debugindex a + rev linkrev nodeid p1 p2 + 0 0 2b4eb07319bfa077a40a2f04913659aef0da42da + 1 1 9a38122997b3ac97be2a9aa2e556838341fdf2cc 2b4eb07319bfa077a40a2f04913659aef0da42da + 2 2 0879345e39377229634b420c639454156726c6b6 2b4eb07319bfa077a40a2f04913659aef0da42da + + $ hg --debug debugindex dir0/child0/e + rev linkrev nodeid p1 p2 + 0 0 bbba6c06b30f443d34ff841bc985c4d0827c6be4 + + $ hg serve -p $HGPORT -d --pid-file hg.pid -E error.log + $ cat hg.pid > $DAEMON_PIDS + +Missing arguments is an error + + $ sendhttpv2peer << EOF + > command filedata + > EOF + creating http peer for wire protocol version 2 + sending filedata command + s> POST /api/exp-http-v2-0001/ro/filedata HTTP/1.1\r\n + s> Accept-Encoding: identity\r\n + s> accept: application/mercurial-exp-framing-0005\r\n + s> content-type: application/mercurial-exp-framing-0005\r\n + s> content-length: 23\r\n + s> host: $LOCALIP:$HGPORT\r\n (glob) + s> user-agent: Mercurial debugwireproto\r\n + s> \r\n + s> \x0f\x00\x00\x01\x00\x01\x01\x11\xa1DnameHfiledata + s> makefile('rb', None) + s> HTTP/1.1 200 OK\r\n + s> Server: testing stub value\r\n + s> Date: $HTTP_DATE$\r\n + s> Content-Type: application/mercurial-exp-framing-0005\r\n + s> Transfer-Encoding: chunked\r\n + s> \r\n + s> 45\r\n + s> =\x00\x00\x01\x00\x02\x012 + s> \xa2Eerror\xa1GmessageX\x1enodes argument must be definedFstatusEerror + s> \r\n + received frame(size=61; request=1; stream=2; streamflags=stream-begin; type=command-response; flags=eos) + s> 0\r\n + s> \r\n + abort: nodes argument must be defined! + [255] + + $ sendhttpv2peer << EOF + > command filedata + > nodes eval:[] + > EOF + creating http peer for wire protocol version 2 + sending filedata command + s> POST /api/exp-http-v2-0001/ro/filedata HTTP/1.1\r\n + s> Accept-Encoding: identity\r\n + s> accept: application/mercurial-exp-framing-0005\r\n + s> content-type: application/mercurial-exp-framing-0005\r\n + s> content-length: 36\r\n + s> host: $LOCALIP:$HGPORT\r\n (glob) + s> user-agent: Mercurial debugwireproto\r\n + s> \r\n + s> \x1c\x00\x00\x01\x00\x01\x01\x11\xa2Dargs\xa1Enodes\x80DnameHfiledata + s> makefile('rb', None) + s> HTTP/1.1 200 OK\r\n + s> Server: testing stub value\r\n + s> Date: $HTTP_DATE$\r\n + s> Content-Type: application/mercurial-exp-framing-0005\r\n + s> Transfer-Encoding: chunked\r\n + s> \r\n + s> 44\r\n + s> <\x00\x00\x01\x00\x02\x012 + s> \xa2Eerror\xa1GmessageX\x1dpath argument must be definedFstatusEerror + s> \r\n + received frame(size=60; request=1; stream=2; streamflags=stream-begin; type=command-response; flags=eos) + s> 0\r\n + s> \r\n + abort: path argument must be defined! + [255] + +Unknown node is an error + + $ sendhttpv2peer << EOF + > command filedata + > nodes eval:[b'\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa'] + > path eval:b'a' + > EOF +
D4488: wireprotov2: define and implement "manifestdata" command
indygreg updated this revision to Diff 10967. REPOSITORY rHG Mercurial CHANGES SINCE LAST UPDATE https://phab.mercurial-scm.org/D4488?vs=10801=10967 REVISION DETAIL https://phab.mercurial-scm.org/D4488 AFFECTED FILES mercurial/help/internals/wireprotocolv2.txt mercurial/wireprotov2server.py tests/test-http-protocol.t tests/test-wireproto-command-capabilities.t tests/test-wireproto-command-manifestdata.t CHANGE DETAILS diff --git a/tests/test-wireproto-command-manifestdata.t b/tests/test-wireproto-command-manifestdata.t new file mode 100644 --- /dev/null +++ b/tests/test-wireproto-command-manifestdata.t @@ -0,0 +1,507 @@ + $ . $TESTDIR/wireprotohelpers.sh + + $ hg init server + $ enablehttpv2 server + $ cd server + $ echo a0 > a + $ echo b0 > b + $ mkdir -p dir0/child0 dir0/child1 dir1 + $ echo c0 > dir0/c + $ echo d0 > dir0/d + $ echo e0 > dir0/child0/e + $ echo f0 > dir0/child1/f + $ hg -q commit -A -m 'commit 0' + + $ echo a1 > a + $ echo d1 > dir0/d + $ hg commit -m 'commit 1' + $ echo f0 > dir0/child1/f + $ hg commit -m 'commit 2' + nothing changed + [1] + + $ hg -q up -r 0 + $ echo a2 > a + $ hg commit -m 'commit 3' + created new head + + $ hg log -G -T '{rev}:{node} {desc}\n' + @ 2:c8757a2ffe552850d1e0dfe60d295ebf64c196d9 commit 3 + | + | o 1:650165e803375748a94df471e5b58d85763e0b29 commit 1 + |/ + o 0:6d85ca1270b377d320098556ba5bfad34a9ee12d commit 0 + + + $ hg --debug debugindex -m + rev linkrev nodeid p1 p2 + 0 0 1b175b595f022cfab5b809cc0ed551bd0b3ff5e4 + 1 1 91e0bdbfb0dde0023fa063edc1445f207a22eac7 1b175b595f022cfab5b809cc0ed551bd0b3ff5e4 + 2 2 46a6721b5edaf0ea04b79a5cb3218854a4d2aba0 1b175b595f022cfab5b809cc0ed551bd0b3ff5e4 + + $ hg serve -p $HGPORT -d --pid-file hg.pid -E error.log + $ cat hg.pid > $DAEMON_PIDS + +Missing arguments is an error + + $ sendhttpv2peer << EOF + > command manifestdata + > EOF + creating http peer for wire protocol version 2 + sending manifestdata command + s> POST /api/exp-http-v2-0001/ro/manifestdata HTTP/1.1\r\n + s> Accept-Encoding: identity\r\n + s> accept: application/mercurial-exp-framing-0005\r\n + s> content-type: application/mercurial-exp-framing-0005\r\n + s> content-length: 27\r\n + s> host: $LOCALIP:$HGPORT\r\n (glob) + s> user-agent: Mercurial debugwireproto\r\n + s> \r\n + s> \x13\x00\x00\x01\x00\x01\x01\x11\xa1DnameLmanifestdata + s> makefile('rb', None) + s> HTTP/1.1 200 OK\r\n + s> Server: testing stub value\r\n + s> Date: $HTTP_DATE$\r\n + s> Content-Type: application/mercurial-exp-framing-0005\r\n + s> Transfer-Encoding: chunked\r\n + s> \r\n + s> 45\r\n + s> =\x00\x00\x01\x00\x02\x012 + s> \xa2Eerror\xa1GmessageX\x1enodes argument must be definedFstatusEerror + s> \r\n + received frame(size=61; request=1; stream=2; streamflags=stream-begin; type=command-response; flags=eos) + s> 0\r\n + s> \r\n + abort: nodes argument must be defined! + [255] + + $ sendhttpv2peer << EOF + > command manifestdata + > nodes eval:[] + > EOF + creating http peer for wire protocol version 2 + sending manifestdata command + s> POST /api/exp-http-v2-0001/ro/manifestdata HTTP/1.1\r\n + s> Accept-Encoding: identity\r\n + s> accept: application/mercurial-exp-framing-0005\r\n + s> content-type: application/mercurial-exp-framing-0005\r\n + s> content-length: 40\r\n + s> host: $LOCALIP:$HGPORT\r\n (glob) + s> user-agent: Mercurial debugwireproto\r\n + s> \r\n + s> \x00\x00\x01\x00\x01\x01\x11\xa2Dargs\xa1Enodes\x80DnameLmanifestdata + s> makefile('rb', None) + s> HTTP/1.1 200 OK\r\n + s> Server: testing stub value\r\n + s> Date: $HTTP_DATE$\r\n + s> Content-Type: application/mercurial-exp-framing-0005\r\n + s> Transfer-Encoding: chunked\r\n + s> \r\n + s> 44\r\n + s> <\x00\x00\x01\x00\x02\x012 + s> \xa2Eerror\xa1GmessageX\x1dtree argument must be definedFstatusEerror + s> \r\n + received frame(size=60; request=1; stream=2; streamflags=stream-begin; type=command-response; flags=eos) + s> 0\r\n + s> \r\n + abort: tree argument must be defined! + [255] + +Unknown node is an error + + $ sendhttpv2peer << EOF + > command manifestdata + > nodes eval:[b'\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa'] + > tree eval:b'' + > EOF + creating http peer for wire protocol version 2 + sending manifestdata command + s> POST /api/exp-http-v2-0001/ro/manifestdata HTTP/1.1\r\n + s> Accept-Encoding: identity\r\n + s> accept:
D4481: wireprotov2: define and implement "changesetdata" command
indygreg updated this revision to Diff 10962. REPOSITORY rHG Mercurial CHANGES SINCE LAST UPDATE https://phab.mercurial-scm.org/D4481?vs=10794=10962 REVISION DETAIL https://phab.mercurial-scm.org/D4481 AFFECTED FILES mercurial/exchange.py mercurial/help/internals/wireprotocolv2.txt mercurial/httppeer.py mercurial/wireprotov2server.py tests/test-http-protocol.t tests/test-wireproto-command-capabilities.t tests/test-wireproto-command-changesetdata.t CHANGE DETAILS diff --git a/tests/test-wireproto-command-changesetdata.t b/tests/test-wireproto-command-changesetdata.t new file mode 100644 --- /dev/null +++ b/tests/test-wireproto-command-changesetdata.t @@ -0,0 +1,486 @@ + $ . $TESTDIR/wireprotohelpers.sh + + $ hg init server + $ enablehttpv2 server + $ cd server + $ echo a0 > a + $ echo b0 > b + + $ hg -q commit -A -m 'commit 0' + + $ echo a1 > a + $ echo b1 > b + $ hg commit -m 'commit 1' + $ echo b2 > b + $ hg commit -m 'commit 2' + + $ hg -q up -r 0 + $ echo a2 > a + $ hg commit -m 'commit 3' + created new head + + $ hg log -G -T '{rev}:{node} {desc}\n' + @ 3:eae5f82c2e622368d27daecb76b7e393d0f24211 commit 3 + | + | o 2:0bb8ad894a15b15380b2a2a5b183e20f2a4b28dd commit 2 + | | + | o 1:7592917e1c3e82677cb0a4bc715ca25dd12d28c1 commit 1 + |/ + o 0:3390ef850073fbc2f0dfff2244342c8e9229013a commit 0 + + + $ hg serve -p $HGPORT -d --pid-file hg.pid -E error.log + $ cat hg.pid > $DAEMON_PIDS + +No arguments is an invalid request + + $ sendhttpv2peer << EOF + > command changesetdata + > EOF + creating http peer for wire protocol version 2 + sending changesetdata command + s> POST /api/exp-http-v2-0001/ro/changesetdata HTTP/1.1\r\n + s> Accept-Encoding: identity\r\n + s> accept: application/mercurial-exp-framing-0005\r\n + s> content-type: application/mercurial-exp-framing-0005\r\n + s> content-length: 28\r\n + s> host: $LOCALIP:$HGPORT\r\n (glob) + s> user-agent: Mercurial debugwireproto\r\n + s> \r\n + s> \x14\x00\x00\x01\x00\x01\x01\x11\xa1DnameMchangesetdata + s> makefile('rb', None) + s> HTTP/1.1 200 OK\r\n + s> Server: testing stub value\r\n + s> Date: $HTTP_DATE$\r\n + s> Content-Type: application/mercurial-exp-framing-0005\r\n + s> Transfer-Encoding: chunked\r\n + s> \r\n + s> 49\r\n + s> A\x00\x00\x01\x00\x02\x012 + s> \xa2Eerror\xa1GmessageX"noderange or nodes must be definedFstatusEerror + s> \r\n + received frame(size=65; request=1; stream=2; streamflags=stream-begin; type=command-response; flags=eos) + s> 0\r\n + s> \r\n + abort: noderange or nodes must be defined! + [255] + +Empty noderange heads results in an error + + $ sendhttpv2peer << EOF + > command changesetdata + > noderange eval:[[],[]] + > EOF + creating http peer for wire protocol version 2 + sending changesetdata command + s> POST /api/exp-http-v2-0001/ro/changesetdata HTTP/1.1\r\n + s> Accept-Encoding: identity\r\n + s> accept: application/mercurial-exp-framing-0005\r\n + s> content-type: application/mercurial-exp-framing-0005\r\n + s> content-length: 47\r\n + s> host: $LOCALIP:$HGPORT\r\n (glob) + s> user-agent: Mercurial debugwireproto\r\n + s> \r\n + s> \'\x00\x00\x01\x00\x01\x01\x11\xa2Dargs\xa1Inoderange\x82\x80\x80DnameMchangesetdata + s> makefile('rb', None) + s> HTTP/1.1 200 OK\r\n + s> Server: testing stub value\r\n + s> Date: $HTTP_DATE$\r\n + s> Content-Type: application/mercurial-exp-framing-0005\r\n + s> Transfer-Encoding: chunked\r\n + s> \r\n + s> 51\r\n + s> I\x00\x00\x01\x00\x02\x012 + s> \xa2Eerror\xa1GmessageX*heads in noderange request cannot be emptyFstatusEerror + s> \r\n + received frame(size=73; request=1; stream=2; streamflags=stream-begin; type=command-response; flags=eos) + s> 0\r\n + s> \r\n + abort: heads in noderange request cannot be empty! + [255] + +Sending just noderange heads sends all revisions + + $ sendhttpv2peer << EOF + > command changesetdata + > noderange eval:[[], [b'\x0b\xb8\xad\x89\x4a\x15\xb1\x53\x80\xb2\xa2\xa5\xb1\x83\xe2\x0f\x2a\x4b\x28\xdd', b'\xea\xe5\xf8\x2c\x2e\x62\x23\x68\xd2\x7d\xae\xcb\x76\xb7\xe3\x93\xd0\xf2\x42\x11']] + > EOF + creating http peer for wire protocol version 2 + sending changesetdata command + s> POST /api/exp-http-v2-0001/ro/changesetdata HTTP/1.1\r\n + s> Accept-Encoding: identity\r\n + s> accept: application/mercurial-exp-framing-0005\r\n + s> content-type: application/mercurial-exp-framing-0005\r\n + s> content-length: 89\r\n + s> host: $LOCALIP:$HGPORT\r\n (glob) + s> user-agent: Mercurial debugwireproto\r\n + s> \r\n + s>
D4491: exchangev2: fetch file revisions
indygreg updated this revision to Diff 10970. REPOSITORY rHG Mercurial CHANGES SINCE LAST UPDATE https://phab.mercurial-scm.org/D4491?vs=10804=10970 REVISION DETAIL https://phab.mercurial-scm.org/D4491 AFFECTED FILES mercurial/exchangev2.py tests/test-wireproto-exchangev2.t CHANGE DETAILS diff --git a/tests/test-wireproto-exchangev2.t b/tests/test-wireproto-exchangev2.t --- a/tests/test-wireproto-exchangev2.t +++ b/tests/test-wireproto-exchangev2.t @@ -94,6 +94,37 @@ received frame(size=11; request=1; stream=2; streamflags=stream-begin; type=command-response; flags=continuation) received frame(size=922; request=1; stream=2; streamflags=; type=command-response; flags=continuation) received frame(size=0; request=1; stream=2; streamflags=; type=command-response; flags=eos) + sending 2 commands + sending command filedata: { +'fields': set([ + 'parents', + 'revision' +]), +'nodes': [ + '+N\xb0s\x19\xbf\xa0w\xa4\n/\x04\x916Y\xae\xf0\xdaB\xda', + '\x9a8\x12)\x97\xb3\xac\x97\xbe*\x9a\xa2\xe5V\x83\x83A\xfd\xf2\xcc', + '\xc2\xa2\x05\xc8\xb2\xad\xe2J\xf2`b\xe5<\xd5\xbc8\x01\xd6`\xda' +], +'path': 'a' + } + sending command filedata: { +'fields': set([ + 'parents', + 'revision' +]), +'nodes': [ + '\x81\x9e%\x8d1\xa5\xe1`f)\xf3e\xbb\x90*\x1b!\xeeB\x16', + '\xb1zk\xd3g=\x9a\xb8\xce\xd5\x81\xa2\t\xf6/=\xa5\xccEx', + '\xc5\xb1\xf9\xd3n\x1c\xc18\xbf\xb6\xef\xb3\xde\xb7]\x8c\xcad\x94\xc3' +], +'path': 'b' + } + received frame(size=11; request=1; stream=2; streamflags=stream-begin; type=command-response; flags=continuation) + received frame(size=389; request=1; stream=2; streamflags=; type=command-response; flags=continuation) + received frame(size=0; request=1; stream=2; streamflags=; type=command-response; flags=eos) + received frame(size=11; request=3; stream=2; streamflags=; type=command-response; flags=continuation) + received frame(size=389; request=3; stream=2; streamflags=; type=command-response; flags=continuation) + received frame(size=0; request=3; stream=2; streamflags=; type=command-response; flags=eos) updating the branch cache new changesets 3390ef850073:caa2a465451d (3 drafts) @@ -189,6 +220,34 @@ received frame(size=11; request=1; stream=2; streamflags=stream-begin; type=command-response; flags=continuation) received frame(size=376; request=1; stream=2; streamflags=; type=command-response; flags=continuation) received frame(size=0; request=1; stream=2; streamflags=; type=command-response; flags=eos) + sending 2 commands + sending command filedata: { +'fields': set([ + 'parents', + 'revision' +]), +'nodes': [ + '+N\xb0s\x19\xbf\xa0w\xa4\n/\x04\x916Y\xae\xf0\xdaB\xda', + '\x9a8\x12)\x97\xb3\xac\x97\xbe*\x9a\xa2\xe5V\x83\x83A\xfd\xf2\xcc' +], +'path': 'a' + } + sending command filedata: { +'fields': set([ + 'parents', + 'revision' +]), +'nodes': [ + '\x81\x9e%\x8d1\xa5\xe1`f)\xf3e\xbb\x90*\x1b!\xeeB\x16' +], +'path': 'b' + } + received frame(size=11; request=1; stream=2; streamflags=stream-begin; type=command-response; flags=continuation) + received frame(size=249; request=1; stream=2; streamflags=; type=command-response; flags=continuation) + received frame(size=0; request=1; stream=2; streamflags=; type=command-response; flags=eos) + received frame(size=11; request=3; stream=2; streamflags=; type=command-response; flags=continuation) + received frame(size=109; request=3; stream=2; streamflags=; type=command-response; flags=continuation) + received frame(size=0; request=3; stream=2; streamflags=; type=command-response; flags=eos) updating the branch cache new changesets 3390ef850073:4432d83626e8 @@ -268,6 +327,36 @@ received frame(size=11; request=1; stream=2; streamflags=stream-begin; type=command-response; flags=continuation) received frame(size=559; request=1; stream=2; streamflags=; type=command-response; flags=continuation) received frame(size=0; request=1; stream=2; streamflags=; type=command-response; flags=eos) + sending 2 commands + sending command filedata: { +'fields': set([ + 'parents', + 'revision' +]), +'nodes': [ + '+N\xb0s\x19\xbf\xa0w\xa4\n/\x04\x916Y\xae\xf0\xdaB\xda', + '\xc2\xa2\x05\xc8\xb2\xad\xe2J\xf2`b\xe5<\xd5\xbc8\x01\xd6`\xda' +], +'path': 'a' + } + sending command filedata: { +'fields': set([ + 'parents', + 'revision' +]), +'nodes': [ + '\x81\x9e%\x8d1\xa5\xe1`f)\xf3e\xbb\x90*\x1b!\xeeB\x16', + '\xb1zk\xd3g=\x9a\xb8\xce\xd5\x81\xa2\t\xf6/=\xa5\xccEx', + '\xc5\xb1\xf9\xd3n\x1c\xc18\xbf\xb6\xef\xb3\xde\xb7]\x8c\xcad\x94\xc3' +], +'path': 'b' + } + received frame(size=11; request=1; stream=2; streamflags=stream-begin; type=command-response; flags=continuation) + received frame(size=249; request=1; stream=2; streamflags=;
D4489: exchangev2: fetch manifest revisions
indygreg updated this revision to Diff 10968. REPOSITORY rHG Mercurial CHANGES SINCE LAST UPDATE https://phab.mercurial-scm.org/D4489?vs=10802=10968 REVISION DETAIL https://phab.mercurial-scm.org/D4489 AFFECTED FILES mercurial/exchangev2.py tests/test-wireproto-exchangev2.t CHANGE DETAILS diff --git a/tests/test-wireproto-exchangev2.t b/tests/test-wireproto-exchangev2.t --- a/tests/test-wireproto-exchangev2.t +++ b/tests/test-wireproto-exchangev2.t @@ -76,6 +76,24 @@ add changeset e96ae20f4188 add changeset caa2a465451d checking for updated bookmarks + sending 1 commands + sending command manifestdata: { +'fields': set([ + 'parents', + 'revision' +]), +'nodes': [ + '\x99/Gy\x02\x9a=\xf8\xd0fm\x00\xbb\x92OicN', + '\xa9\x88\xfbCX>\x87\x1d\x1e\xd5u\x0e\xe0t\xc6\xd8@\xbb\xbf\xc8', + '\xec\x80NH\x8c \x88\xc25\t\x9a\x10 u\x13\xbe\xcd\xc3\xdd\xa5', + '\x04\\\x7f9\'\xda\x13\xe7Z\xf8\xf0\xe4\xf0HI\xe4a\xa9x\x0f', + '7\x9c\xb0\xc2\xe6d\\y\xdd\xc5\x9a\x1dG\'\xa9\xfb\x83\n\xeb&' +], +'tree': '' + } + received frame(size=11; request=1; stream=2; streamflags=stream-begin; type=command-response; flags=continuation) + received frame(size=922; request=1; stream=2; streamflags=; type=command-response; flags=continuation) + received frame(size=0; request=1; stream=2; streamflags=; type=command-response; flags=eos) updating the branch cache new changesets 3390ef850073:caa2a465451d (3 drafts) @@ -101,6 +119,16 @@ o 0 3390ef850073fbc2f0dfff2244342c8e9229013a public +All manifests should have been transferred + + $ hg -R client-simple debugindex -m + rev linkrev nodeid p1 p2 + 0 0 992f4779029a + 1 1 a988fb43583e 992f4779029a + 2 2 ec804e488c20 a988fb43583e + 3 3 045c7f3927da 992f4779029a + 4 4 379cb0c2e664 045c7f3927da + Cloning only a specific revision works $ hg --debug clone -U -r 4432d83626e8 http://localhost:$HGPORT client-singlehead @@ -146,6 +174,21 @@ add changeset 3390ef850073 add changeset 4432d83626e8 checking for updated bookmarks + sending 1 commands + sending command manifestdata: { +'fields': set([ + 'parents', + 'revision' +]), +'nodes': [ + '\x99/Gy\x02\x9a=\xf8\xd0fm\x00\xbb\x92OicN', + '\xa9\x88\xfbCX>\x87\x1d\x1e\xd5u\x0e\xe0t\xc6\xd8@\xbb\xbf\xc8' +], +'tree': '' + } + received frame(size=11; request=1; stream=2; streamflags=stream-begin; type=command-response; flags=continuation) + received frame(size=376; request=1; stream=2; streamflags=; type=command-response; flags=continuation) + received frame(size=0; request=1; stream=2; streamflags=; type=command-response; flags=eos) updating the branch cache new changesets 3390ef850073:4432d83626e8 @@ -157,6 +200,11 @@ o 0 3390ef850073fbc2f0dfff2244342c8e9229013a public + $ hg debugindex -m + rev linkrev nodeid p1 p2 + 0 0 992f4779029a + 1 1 a988fb43583e 992f4779029a + Incremental pull works $ hg --debug pull @@ -204,6 +252,22 @@ add changeset e96ae20f4188 add changeset caa2a465451d checking for updated bookmarks + sending 1 commands + sending command manifestdata: { +'fields': set([ + 'parents', + 'revision' +]), +'nodes': [ + '\xec\x80NH\x8c \x88\xc25\t\x9a\x10 u\x13\xbe\xcd\xc3\xdd\xa5', + '\x04\\\x7f9\'\xda\x13\xe7Z\xf8\xf0\xe4\xf0HI\xe4a\xa9x\x0f', + '7\x9c\xb0\xc2\xe6d\\y\xdd\xc5\x9a\x1dG\'\xa9\xfb\x83\n\xeb&' +], +'tree': '' + } + received frame(size=11; request=1; stream=2; streamflags=stream-begin; type=command-response; flags=continuation) + received frame(size=559; request=1; stream=2; streamflags=; type=command-response; flags=continuation) + received frame(size=0; request=1; stream=2; streamflags=; type=command-response; flags=eos) updating the branch cache new changesets cd2534766bec:caa2a465451d (3 drafts) (run 'hg update' to get a working copy) @@ -220,6 +284,14 @@ o 0 3390ef850073fbc2f0dfff2244342c8e9229013a public + $ hg debugindex -m + rev linkrev nodeid p1 p2 + 0 0 992f4779029a + 1 1 a988fb43583e 992f4779029a + 2 2 ec804e488c20 a988fb43583e + 3 3 045c7f3927da 992f4779029a + 4 4 379cb0c2e664 045c7f3927da + Phase-only update works $ hg -R ../server-simple phase --public -r caa2a465451dd @@ -331,6 +403,24 @@ checking for updated bookmarks adding remote bookmark book-1 adding remote bookmark book-2 + sending 1 commands + sending command manifestdata: { +'fields': set([ + 'parents', + 'revision' +]), +'nodes': [ +
D4480: exchangev2: start to implement pull with wire protocol v2
indygreg updated this revision to Diff 10961. REPOSITORY rHG Mercurial CHANGES SINCE LAST UPDATE https://phab.mercurial-scm.org/D4480?vs=10793=10961 REVISION DETAIL https://phab.mercurial-scm.org/D4480 AFFECTED FILES mercurial/exchange.py mercurial/exchangev2.py mercurial/httppeer.py tests/test-wireproto-exchangev2.t tests/wireprotohelpers.sh CHANGE DETAILS diff --git a/tests/wireprotohelpers.sh b/tests/wireprotohelpers.sh --- a/tests/wireprotohelpers.sh +++ b/tests/wireprotohelpers.sh @@ -56,3 +56,10 @@ web.api.http-v2 = true EOF } + +enablehttpv2client() { + cat >> $HGRCPATH << EOF +[experimental] +httppeer.advertise-v2 = true +EOF +} diff --git a/tests/test-wireproto-exchangev2.t b/tests/test-wireproto-exchangev2.t new file mode 100644 --- /dev/null +++ b/tests/test-wireproto-exchangev2.t @@ -0,0 +1,53 @@ +Tests for wire protocol version 2 exchange. +Tests in this file should be folded into existing tests once protocol +v2 has enough features that it can be enabled via #testcase in existing +tests. + + $ . $TESTDIR/wireprotohelpers.sh + $ enablehttpv2client + + $ hg init server-simple + $ enablehttpv2 server-simple + $ cd server-simple + $ cat >> .hg/hgrc << EOF + > [phases] + > publish = false + > EOF + $ echo a0 > a + $ echo b0 > b + $ hg -q commit -A -m 'commit 0' + + $ echo a1 > a + $ hg commit -m 'commit 1' + $ hg phase --public -r . + $ echo a2 > a + $ hg commit -m 'commit 2' + + $ hg -q up -r 0 + $ echo b1 > b + $ hg -q commit -m 'head 2 commit 1' + $ echo b2 > b + $ hg -q commit -m 'head 2 commit 2' + + $ hg serve -p $HGPORT -d --pid-file hg.pid -E error.log + $ cat hg.pid > $DAEMON_PIDS + + $ cd .. + +Test basic clone + + $ hg --debug clone -U http://localhost:$HGPORT client-simple + using http://localhost:$HGPORT/ + sending capabilities command + query 1; heads + sending 2 commands + sending command heads: {} + sending command known: { +'nodes': [] + } + received frame(size=11; request=1; stream=2; streamflags=stream-begin; type=command-response; flags=continuation) + received frame(size=43; request=1; stream=2; streamflags=; type=command-response; flags=continuation) + received frame(size=0; request=1; stream=2; streamflags=; type=command-response; flags=eos) + received frame(size=11; request=3; stream=2; streamflags=; type=command-response; flags=continuation) + received frame(size=1; request=3; stream=2; streamflags=; type=command-response; flags=continuation) + received frame(size=0; request=3; stream=2; streamflags=; type=command-response; flags=eos) diff --git a/mercurial/httppeer.py b/mercurial/httppeer.py --- a/mercurial/httppeer.py +++ b/mercurial/httppeer.py @@ -802,7 +802,8 @@ return True # Other concepts. -if name in ('bundle2',): +# TODO remove exchangev2 once we have a command implemented. +if name in ('bundle2', 'exchangev2'): return True # Alias command-* to presence of command of that name. diff --git a/mercurial/exchangev2.py b/mercurial/exchangev2.py new file mode 100644 --- /dev/null +++ b/mercurial/exchangev2.py @@ -0,0 +1,55 @@ +# exchangev2.py - repository exchange for wire protocol version 2 +# +# Copyright 2018 Gregory Szorc +# +# 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 .node import ( +nullid, +) +from . import ( +setdiscovery, +) + +def pull(pullop): +"""Pull using wire protocol version 2.""" +repo = pullop.repo +remote = pullop.remote + +# Figure out what needs to be fetched. +common, fetch, remoteheads = _pullchangesetdiscovery( +repo, remote, pullop.heads, abortwhenunrelated=pullop.force) + +def _pullchangesetdiscovery(repo, remote, heads, abortwhenunrelated=True): +"""Determine which changesets need to be pulled.""" + +if heads: +knownnode = repo.changelog.hasnode +if all(knownnode(head) for head in heads): +return heads, False, heads + +# TODO wire protocol version 2 is capable of more efficient discovery +# than setdiscovery. Consider implementing something better. +common, fetch, remoteheads = setdiscovery.findcommonheads( +repo.ui, repo, remote, abortwhenunrelated=abortwhenunrelated) + +common = set(common) +remoteheads = set(remoteheads) + +# If a remote head is filtered locally, put it back in the common set. +# See the comment in exchange._pulldiscoverychangegroup() for more. + +if fetch and remoteheads: +nodemap = repo.unfiltered().changelog.nodemap + +common |= {head for head in remoteheads if head in nodemap} + +if set(remoteheads).issubset(common): +fetch = [] + +common.discard(nullid) + +return common, fetch, remoteheads diff --git a/mercurial/exchange.py b/mercurial/exchange.py --- a/mercurial/exchange.py +++
D4485: wireprotov2: add bookmarks to "changesetdata" command
indygreg updated this revision to Diff 10965. REPOSITORY rHG Mercurial CHANGES SINCE LAST UPDATE https://phab.mercurial-scm.org/D4485?vs=10798=10965 REVISION DETAIL https://phab.mercurial-scm.org/D4485 AFFECTED FILES mercurial/help/internals/wireprotocolv2.txt mercurial/wireprotov2server.py tests/test-wireproto-command-changesetdata.t CHANGE DETAILS diff --git a/tests/test-wireproto-command-changesetdata.t b/tests/test-wireproto-command-changesetdata.t --- a/tests/test-wireproto-command-changesetdata.t +++ b/tests/test-wireproto-command-changesetdata.t @@ -478,6 +478,213 @@ b'1b74476799ec8318045db759b1b4bcc9b839d0aa\ntest\n0 0\na\n\ncommit 3' ] +Bookmarks key isn't present if no bookmarks data + + $ sendhttpv2peer << EOF + > command changesetdata + > fields eval:[b'bookmarks'] + > noderange eval:[[], [b'\x0b\xb8\xad\x89\x4a\x15\xb1\x53\x80\xb2\xa2\xa5\xb1\x83\xe2\x0f\x2a\x4b\x28\xdd', b'\xea\xe5\xf8\x2c\x2e\x62\x23\x68\xd2\x7d\xae\xcb\x76\xb7\xe3\x93\xd0\xf2\x42\x11']] + > EOF + creating http peer for wire protocol version 2 + sending changesetdata command + s> POST /api/exp-http-v2-0001/ro/changesetdata HTTP/1.1\r\n + s> Accept-Encoding: identity\r\n + s> accept: application/mercurial-exp-framing-0005\r\n + s> content-type: application/mercurial-exp-framing-0005\r\n + s> content-length: 107\r\n + s> host: $LOCALIP:$HGPORT\r\n (glob) + s> user-agent: Mercurial debugwireproto\r\n + s> \r\n + s> c\x00\x00\x01\x00\x01\x01\x11\xa2Dargs\xa2Ffields\x81IbookmarksInoderange\x82\x80\x82T\x0b\xb8\xad\x89J\x15\xb1S\x80\xb2\xa2\xa5\xb1\x83\xe2\x0f*K(\xddT\xea\xe5\xf8,.b#h\xd2}\xae\xcbv\xb7\xe3\x93\xd0\xf2B\x11DnameMchangesetdata + s> makefile('rb', None) + s> HTTP/1.1 200 OK\r\n + s> Server: testing stub value\r\n + s> Date: $HTTP_DATE$\r\n + s> Content-Type: application/mercurial-exp-framing-0005\r\n + s> Transfer-Encoding: chunked\r\n + s> \r\n + s> 13\r\n + s> \x0b\x00\x00\x01\x00\x02\x011 + s> \xa1FstatusBok + s> \r\n + received frame(size=11; request=1; stream=2; streamflags=stream-begin; type=command-response; flags=continuation) + s> 81\r\n + s> y\x00\x00\x01\x00\x02\x001 + s> \xa1Jtotalitems\x04\xa1DnodeT3\x90\xef\x85\x00s\xfb\xc2\xf0\xdf\xff"D4,\x8e\x92)\x01:\xa1DnodeTu\x92\x91~\x1c>\x82g|\xb0\xa4\xbcq\\\xa2]\xd1-(\xc1\xa1DnodeT\x0b\xb8\xad\x89J\x15\xb1S\x80\xb2\xa2\xa5\xb1\x83\xe2\x0f*K(\xdd\xa1DnodeT\xea\xe5\xf8,.b#h\xd2}\xae\xcbv\xb7\xe3\x93\xd0\xf2B\x11 + s> \r\n + received frame(size=121; request=1; stream=2; streamflags=; type=command-response; flags=continuation) + s> 8\r\n + s> \x00\x00\x00\x01\x00\x02\x002 + s> \r\n + s> 0\r\n + s> \r\n + received frame(size=0; request=1; stream=2; streamflags=; type=command-response; flags=eos) + response: gen[ +{ + b'totalitems': 4 +}, +{ + b'node': b'3\x90\xef\x85\x00s\xfb\xc2\xf0\xdf\xff"D4,\x8e\x92)\x01:' +}, +{ + b'node': b'u\x92\x91~\x1c>\x82g|\xb0\xa4\xbcq\\\xa2]\xd1-(\xc1' +}, +{ + b'node': b'\x0b\xb8\xad\x89J\x15\xb1S\x80\xb2\xa2\xa5\xb1\x83\xe2\x0f*K(\xdd' +}, +{ + b'node': b'\xea\xe5\xf8,.b#h\xd2}\xae\xcbv\xb7\xe3\x93\xd0\xf2B\x11' +} + ] + +Bookmarks are sent when requested + + $ hg -R ../server bookmark -r 0bb8ad894a15b15380b2a2a5b183e20f2a4b28dd book-1 + $ hg -R ../server bookmark -r eae5f82c2e622368d27daecb76b7e393d0f24211 book-2 + $ hg -R ../server bookmark -r eae5f82c2e622368d27daecb76b7e393d0f24211 book-3 + + $ sendhttpv2peer << EOF + > command changesetdata + > fields eval:[b'bookmarks'] + > noderange eval:[[], [b'\x0b\xb8\xad\x89\x4a\x15\xb1\x53\x80\xb2\xa2\xa5\xb1\x83\xe2\x0f\x2a\x4b\x28\xdd', b'\xea\xe5\xf8\x2c\x2e\x62\x23\x68\xd2\x7d\xae\xcb\x76\xb7\xe3\x93\xd0\xf2\x42\x11']] + > EOF + creating http peer for wire protocol version 2 + sending changesetdata command + s> POST /api/exp-http-v2-0001/ro/changesetdata HTTP/1.1\r\n + s> Accept-Encoding: identity\r\n + s> accept: application/mercurial-exp-framing-0005\r\n + s> content-type: application/mercurial-exp-framing-0005\r\n + s> content-length: 107\r\n + s> host: $LOCALIP:$HGPORT\r\n (glob) + s> user-agent: Mercurial debugwireproto\r\n + s> \r\n + s> c\x00\x00\x01\x00\x01\x01\x11\xa2Dargs\xa2Ffields\x81IbookmarksInoderange\x82\x80\x82T\x0b\xb8\xad\x89J\x15\xb1S\x80\xb2\xa2\xa5\xb1\x83\xe2\x0f*K(\xddT\xea\xe5\xf8,.b#h\xd2}\xae\xcbv\xb7\xe3\x93\xd0\xf2B\x11DnameMchangesetdata + s> makefile('rb', None) + s> HTTP/1.1 200 OK\r\n + s> Server: testing stub value\r\n + s> Date: $HTTP_DATE$\r\n + s> Content-Type: application/mercurial-exp-framing-0005\r\n + s> Transfer-Encoding: chunked\r\n + s> \r\n + s> 13\r\n + s> \x0b\x00\x00\x01\x00\x02\x011 + s> \xa1FstatusBok + s> \r\n + received frame(size=11; request=1; stream=2;
D4486: exchangev2: fetch and apply bookmarks
indygreg updated this revision to Diff 10966. REPOSITORY rHG Mercurial CHANGES SINCE LAST UPDATE https://phab.mercurial-scm.org/D4486?vs=10799=10966 REVISION DETAIL https://phab.mercurial-scm.org/D4486 AFFECTED FILES mercurial/exchangev2.py tests/test-wireproto-exchangev2.t CHANGE DETAILS diff --git a/tests/test-wireproto-exchangev2.t b/tests/test-wireproto-exchangev2.t --- a/tests/test-wireproto-exchangev2.t +++ b/tests/test-wireproto-exchangev2.t @@ -54,6 +54,7 @@ sending 1 commands sending command changesetdata: { 'fields': set([ + 'bookmarks', 'parents', 'phase', 'revision' @@ -74,6 +75,7 @@ add changeset cd2534766bec add changeset e96ae20f4188 add changeset caa2a465451d + checking for updated bookmarks updating the branch cache new changesets 3390ef850073:caa2a465451d (3 drafts) @@ -126,6 +128,7 @@ sending 1 commands sending command changesetdata: { 'fields': set([ + 'bookmarks', 'parents', 'phase', 'revision' @@ -142,6 +145,7 @@ received frame(size=0; request=1; stream=2; streamflags=; type=command-response; flags=eos) add changeset 3390ef850073 add changeset 4432d83626e8 + checking for updated bookmarks updating the branch cache new changesets 3390ef850073:4432d83626e8 @@ -178,6 +182,7 @@ sending 1 commands sending command changesetdata: { 'fields': set([ + 'bookmarks', 'parents', 'phase', 'revision' @@ -198,6 +203,7 @@ add changeset cd2534766bec add changeset e96ae20f4188 add changeset caa2a465451d + checking for updated bookmarks updating the branch cache new changesets cd2534766bec:caa2a465451d (3 drafts) (run 'hg update' to get a working copy) @@ -241,6 +247,7 @@ sending 1 commands sending command changesetdata: { 'fields': set([ + 'bookmarks', 'parents', 'phase', 'revision' @@ -259,6 +266,7 @@ received frame(size=11; request=1; stream=2; streamflags=stream-begin; type=command-response; flags=continuation) received frame(size=92; request=1; stream=2; streamflags=; type=command-response; flags=continuation) received frame(size=0; request=1; stream=2; streamflags=; type=command-response; flags=eos) + checking for updated bookmarks 2 local changesets published (run 'hg update' to get a working copy) @@ -275,3 +283,113 @@ $ cd .. + +Bookmarks are transferred on clone + + $ hg -R server-simple bookmark -r 3390ef850073fbc2f0dfff2244342c8e9229013a book-1 + $ hg -R server-simple bookmark -r cd2534766bece138c7c1afdc6825302f0f62d81f book-2 + + $ hg --debug clone -U http://localhost:$HGPORT/ client-bookmarks + using http://localhost:$HGPORT/ + sending capabilities command + query 1; heads + sending 2 commands + sending command heads: {} + sending command known: { +'nodes': [] + } + received frame(size=11; request=1; stream=2; streamflags=stream-begin; type=command-response; flags=continuation) + received frame(size=43; request=1; stream=2; streamflags=; type=command-response; flags=continuation) + received frame(size=0; request=1; stream=2; streamflags=; type=command-response; flags=eos) + received frame(size=11; request=3; stream=2; streamflags=; type=command-response; flags=continuation) + received frame(size=1; request=3; stream=2; streamflags=; type=command-response; flags=continuation) + received frame(size=0; request=3; stream=2; streamflags=; type=command-response; flags=eos) + sending 1 commands + sending command changesetdata: { +'fields': set([ + 'bookmarks', + 'parents', + 'phase', + 'revision' +]), +'noderange': [ + [], + [ +'\xca\xa2\xa4eE\x1d\xd1\xfa\xcd\xa0\xf5\xb1#\x12\xc3UXA\x88\xa1', +'\xcd%4vk\xec\xe18\xc7\xc1\xaf\xdch%0/\x0fb\xd8\x1f' + ] +] + } + received frame(size=11; request=1; stream=2; streamflags=stream-begin; type=command-response; flags=continuation) + received frame(size=909; request=1; stream=2; streamflags=; type=command-response; flags=continuation) + received frame(size=0; request=1; stream=2; streamflags=; type=command-response; flags=eos) + add changeset 3390ef850073 + add changeset 4432d83626e8 + add changeset cd2534766bec + add changeset e96ae20f4188 + add changeset caa2a465451d + checking for updated bookmarks + adding remote bookmark book-1 + adding remote bookmark book-2 + updating the branch cache + new changesets 3390ef850073:caa2a465451d (1 drafts) + + $ hg -R client-bookmarks bookmarks + book-10:3390ef850073 + book-22:cd2534766bec + +Server-side bookmark moves are reflected during `hg pull` + + $ hg -R server-simple bookmark -r cd2534766bece138c7c1afdc6825302f0f62d81f book-1 + moving bookmark 'book-1' forward from 3390ef850073 + + $ hg -R client-bookmarks --debug pull + pulling from http://localhost:$HGPORT/ + using http://localhost:$HGPORT/ +
D4483: wireprotov2: add phases to "changesetdata" command
indygreg updated this revision to Diff 10963. REPOSITORY rHG Mercurial CHANGES SINCE LAST UPDATE https://phab.mercurial-scm.org/D4483?vs=10796=10963 REVISION DETAIL https://phab.mercurial-scm.org/D4483 AFFECTED FILES mercurial/help/internals/wireprotocolv2.txt mercurial/wireprotov2server.py tests/test-wireproto-command-changesetdata.t CHANGE DETAILS diff --git a/tests/test-wireproto-command-changesetdata.t b/tests/test-wireproto-command-changesetdata.t --- a/tests/test-wireproto-command-changesetdata.t +++ b/tests/test-wireproto-command-changesetdata.t @@ -3,6 +3,10 @@ $ hg init server $ enablehttpv2 server $ cd server + $ cat >> .hg/hgrc << EOF + > [phases] + > publish = false + > EOF $ echo a0 > a $ echo b0 > b @@ -13,6 +17,7 @@ $ hg commit -m 'commit 1' $ echo b2 > b $ hg commit -m 'commit 2' + $ hg phase --public -r . $ hg -q up -r 0 $ echo a2 > a @@ -365,6 +370,57 @@ } ] +Phase data is transferred upon request + + $ sendhttpv2peer << EOF + > command changesetdata + > fields eval:[b'phase'] + > nodes eval:[b'\x0b\xb8\xad\x89\x4a\x15\xb1\x53\x80\xb2\xa2\xa5\xb1\x83\xe2\x0f\x2a\x4b\x28\xdd'] + > EOF + creating http peer for wire protocol version 2 + sending changesetdata command + s> POST /api/exp-http-v2-0001/ro/changesetdata HTTP/1.1\r\n + s> Accept-Encoding: identity\r\n + s> accept: application/mercurial-exp-framing-0005\r\n + s> content-type: application/mercurial-exp-framing-0005\r\n + s> content-length: 76\r\n + s> host: $LOCALIP:$HGPORT\r\n (glob) + s> user-agent: Mercurial debugwireproto\r\n + s> \r\n + s> D\x00\x00\x01\x00\x01\x01\x11\xa2Dargs\xa2Ffields\x81EphaseEnodes\x81T\x0b\xb8\xad\x89J\x15\xb1S\x80\xb2\xa2\xa5\xb1\x83\xe2\x0f*K(\xddDnameMchangesetdata + s> makefile('rb', None) + s> HTTP/1.1 200 OK\r\n + s> Server: testing stub value\r\n + s> Date: $HTTP_DATE$\r\n + s> Content-Type: application/mercurial-exp-framing-0005\r\n + s> Transfer-Encoding: chunked\r\n + s> \r\n + s> 13\r\n + s> \x0b\x00\x00\x01\x00\x02\x011 + s> \xa1FstatusBok + s> \r\n + received frame(size=11; request=1; stream=2; streamflags=stream-begin; type=command-response; flags=continuation) + s> 3d\r\n + s> 5\x00\x00\x01\x00\x02\x001 + s> \xa1Jtotalitems\x01\xa2DnodeT\x0b\xb8\xad\x89J\x15\xb1S\x80\xb2\xa2\xa5\xb1\x83\xe2\x0f*K(\xddEphaseFpublic + s> \r\n + received frame(size=53; request=1; stream=2; streamflags=; type=command-response; flags=continuation) + s> 8\r\n + s> \x00\x00\x00\x01\x00\x02\x002 + s> \r\n + s> 0\r\n + s> \r\n + received frame(size=0; request=1; stream=2; streamflags=; type=command-response; flags=eos) + response: gen[ +{ + b'totalitems': 1 +}, +{ + b'node': b'\x0b\xb8\xad\x89J\x15\xb1S\x80\xb2\xa2\xa5\xb1\x83\xe2\x0f*K(\xdd', + b'phase': b'public' +} + ] + Revision data is transferred upon request $ sendhttpv2peer << EOF @@ -483,4 +539,101 @@ b'1b74476799ec8318045db759b1b4bcc9b839d0aa\ntest\n0 0\na\n\ncommit 3' ] +Base nodes have just their metadata (e.g. phase) transferred + + $ sendhttpv2peer << EOF + > command changesetdata + > fields eval:[b'phase', b'parents', b'revision'] + > noderange eval:[[b'\x33\x90\xef\x85\x00\x73\xfb\xc2\xf0\xdf\xff\x22\x44\x34\x2c\x8e\x92\x29\x01\x3a'], [b'\x0b\xb8\xad\x89\x4a\x15\xb1\x53\x80\xb2\xa2\xa5\xb1\x83\xe2\x0f\x2a\x4b\x28\xdd', b'\xea\xe5\xf8\x2c\x2e\x62\x23\x68\xd2\x7d\xae\xcb\x76\xb7\xe3\x93\xd0\xf2\x42\x11']] + > EOF + creating http peer for wire protocol version 2 + sending changesetdata command + s> POST /api/exp-http-v2-0001/ro/changesetdata HTTP/1.1\r\n + s> Accept-Encoding: identity\r\n + s> accept: application/mercurial-exp-framing-0005\r\n + s> content-type: application/mercurial-exp-framing-0005\r\n + s> content-length: 141\r\n + s> host: $LOCALIP:$HGPORT\r\n (glob) + s> user-agent: Mercurial debugwireproto\r\n + s> \r\n + s> \x85\x00\x00\x01\x00\x01\x01\x11\xa2Dargs\xa2Ffields\x83EphaseGparentsHrevisionInoderange\x82\x81T3\x90\xef\x85\x00s\xfb\xc2\xf0\xdf\xff"D4,\x8e\x92)\x01:\x82T\x0b\xb8\xad\x89J\x15\xb1S\x80\xb2\xa2\xa5\xb1\x83\xe2\x0f*K(\xddT\xea\xe5\xf8,.b#h\xd2}\xae\xcbv\xb7\xe3\x93\xd0\xf2B\x11DnameMchangesetdata + s> makefile('rb', None) + s> HTTP/1.1 200 OK\r\n + s> Server: testing stub value\r\n + s> Date: $HTTP_DATE$\r\n + s> Content-Type: application/mercurial-exp-framing-0005\r\n + s> Transfer-Encoding: chunked\r\n + s> \r\n + s> 13\r\n + s> \x0b\x00\x00\x01\x00\x02\x011 + s> \xa1FstatusBok + s> \r\n + received frame(size=11; request=1; stream=2; streamflags=stream-begin; type=command-response; flags=continuation) + s> 239\r\n + s> 1\x02\x00\x01\x00\x02\x001 + s>
D4484: exchangev2: fetch and apply phases data
indygreg updated this revision to Diff 10964. REPOSITORY rHG Mercurial CHANGES SINCE LAST UPDATE https://phab.mercurial-scm.org/D4484?vs=10797=10964 REVISION DETAIL https://phab.mercurial-scm.org/D4484 AFFECTED FILES mercurial/exchangev2.py tests/test-wireproto-exchangev2.t CHANGE DETAILS diff --git a/tests/test-wireproto-exchangev2.t b/tests/test-wireproto-exchangev2.t --- a/tests/test-wireproto-exchangev2.t +++ b/tests/test-wireproto-exchangev2.t @@ -55,6 +55,7 @@ sending command changesetdata: { 'fields': set([ 'parents', + 'phase', 'revision' ]), 'noderange': [ @@ -66,15 +67,15 @@ ] } received frame(size=11; request=1; stream=2; streamflags=stream-begin; type=command-response; flags=continuation) - received frame(size=809; request=1; stream=2; streamflags=; type=command-response; flags=continuation) + received frame(size=871; request=1; stream=2; streamflags=; type=command-response; flags=continuation) received frame(size=0; request=1; stream=2; streamflags=; type=command-response; flags=eos) add changeset 3390ef850073 add changeset 4432d83626e8 add changeset cd2534766bec add changeset e96ae20f4188 add changeset caa2a465451d updating the branch cache - new changesets 3390ef850073:caa2a465451d + new changesets 3390ef850073:caa2a465451d (3 drafts) All changesets should have been transferred @@ -87,11 +88,11 @@ 4 4 caa2a465451d e96ae20f4188 $ hg -R client-simple log -G -T '{rev} {node} {phase}\n' - o 4 caa2a465451dd1facda0f5b12312c355584188a1 public + o 4 caa2a465451dd1facda0f5b12312c355584188a1 draft | - o 3 e96ae20f4188487b9ae4ef3941c27c81143146e5 public + o 3 e96ae20f4188487b9ae4ef3941c27c81143146e5 draft | - | o 2 cd2534766bece138c7c1afdc6825302f0f62d81f public + | o 2 cd2534766bece138c7c1afdc6825302f0f62d81f draft | | | o 1 4432d83626e8a98655f062ec1f2a43b07f7fbbb0 public |/ @@ -126,6 +127,7 @@ sending command changesetdata: { 'fields': set([ 'parents', + 'phase', 'revision' ]), 'noderange': [ @@ -136,7 +138,7 @@ ] } received frame(size=11; request=1; stream=2; streamflags=stream-begin; type=command-response; flags=continuation) - received frame(size=327; request=1; stream=2; streamflags=; type=command-response; flags=continuation) + received frame(size=353; request=1; stream=2; streamflags=; type=command-response; flags=continuation) received frame(size=0; request=1; stream=2; streamflags=; type=command-response; flags=eos) add changeset 3390ef850073 add changeset 4432d83626e8 @@ -177,6 +179,7 @@ sending command changesetdata: { 'fields': set([ 'parents', + 'phase', 'revision' ]), 'noderange': [ @@ -190,21 +193,81 @@ ] } received frame(size=11; request=1; stream=2; streamflags=stream-begin; type=command-response; flags=continuation) - received frame(size=495; request=1; stream=2; streamflags=; type=command-response; flags=continuation) + received frame(size=571; request=1; stream=2; streamflags=; type=command-response; flags=continuation) received frame(size=0; request=1; stream=2; streamflags=; type=command-response; flags=eos) add changeset cd2534766bec add changeset e96ae20f4188 add changeset caa2a465451d updating the branch cache - new changesets cd2534766bec:caa2a465451d + new changesets cd2534766bec:caa2a465451d (3 drafts) + (run 'hg update' to get a working copy) + + $ hg log -G -T '{rev} {node} {phase}\n' + o 4 caa2a465451dd1facda0f5b12312c355584188a1 draft + | + o 3 e96ae20f4188487b9ae4ef3941c27c81143146e5 draft + | + | o 2 cd2534766bece138c7c1afdc6825302f0f62d81f draft + | | + | o 1 4432d83626e8a98655f062ec1f2a43b07f7fbbb0 public + |/ + o 0 3390ef850073fbc2f0dfff2244342c8e9229013a public + + +Phase-only update works + + $ hg -R ../server-simple phase --public -r caa2a465451dd + $ hg --debug pull + pulling from http://localhost:$HGPORT/ + using http://localhost:$HGPORT/ + sending capabilities command + query 1; heads + sending 2 commands + sending command heads: {} + sending command known: { +'nodes': [ + '\xcd%4vk\xec\xe18\xc7\xc1\xaf\xdch%0/\x0fb\xd8\x1f', + '\xca\xa2\xa4eE\x1d\xd1\xfa\xcd\xa0\xf5\xb1#\x12\xc3UXA\x88\xa1' +] + } + received frame(size=11; request=1; stream=2; streamflags=stream-begin; type=command-response; flags=continuation) + received frame(size=43; request=1; stream=2; streamflags=; type=command-response; flags=continuation) + received frame(size=0; request=1; stream=2; streamflags=; type=command-response; flags=eos) + received frame(size=11; request=3; stream=2; streamflags=; type=command-response; flags=continuation) + received frame(size=3; request=3; stream=2; streamflags=; type=command-response; flags=continuation) + received frame(size=0; request=3; stream=2; streamflags=; type=command-response; flags=eos) + searching
D4436: httppeer: expose capabilities for each command
indygreg updated this revision to Diff 10960. REPOSITORY rHG Mercurial CHANGES SINCE LAST UPDATE https://phab.mercurial-scm.org/D4436?vs=10761=10960 REVISION DETAIL https://phab.mercurial-scm.org/D4436 AFFECTED FILES mercurial/httppeer.py CHANGE DETAILS diff --git a/mercurial/httppeer.py b/mercurial/httppeer.py --- a/mercurial/httppeer.py +++ b/mercurial/httppeer.py @@ -805,6 +805,10 @@ if name in ('bundle2',): return True +# Alias command-* to presence of command of that name. +if name.startswith('command-'): +return name[len('command-'):] in self._descriptor['commands'] + return False def requirecap(self, name, purpose): To: indygreg, #hg-reviewers Cc: durin42, mercurial-devel ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
D4490: wireprotov2: define and implement "filedata" command
indygreg added a comment. In https://phab.mercurial-scm.org/D4490#69457, @durin42 wrote: > Oh, one more thing: I think this, as-stated, will make it at best challenging to have ACLed branches: we'd have to, on the server, walk the linknodes and see if the client was authorized to see any branch(es) that contain the node. > > That's probably okayer for us than it was for git (since we have linkrevs at least), but it's still worth considering. First, totally agree with you about wire protocol / command overhead. I plan to add bulk querying APIs later. Also, I wasn't aware of the ACL'd branches requirement. I'll have to think of ways to handle that. It may involve the server advertising the available mechanisms for requesting file data (e.g. "request by file node" and "request by changeset node") and the server not allowing certain modes. But that example would undercut raw data access. So maybe it gets advertised as a server preference. Or maybe we end up not doing the "request by file node" path in the common case and the server overhead isn't a problem in practice. I'll keep this use case in mind when writing future commits. REPOSITORY rHG Mercurial REVISION DETAIL https://phab.mercurial-scm.org/D4490 To: indygreg, #hg-reviewers, durin42 Cc: durin42, mercurial-devel ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
D4488: wireprotov2: define and implement "manifestdata" command
indygreg added a comment. In https://phab.mercurial-scm.org/D4488#69449, @durin42 wrote: > Could you add a TODO about the overhead of having to enumerate every node required? That'll be prohibitive fairly quickly I think. There are already TODOs in wireprotocolv2.txt. And, yes, the overhead is prohibitive fairly quickly and I plan to add more "bulk querying" capabilities in future commits. I'm trying to get the granular data access in first then optimize later. REPOSITORY rHG Mercurial REVISION DETAIL https://phab.mercurial-scm.org/D4488 To: indygreg, #hg-reviewers Cc: durin42, mercurial-devel ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
D4480: exchangev2: start to implement pull with wire protocol v2
indygreg planned changes to this revision. indygreg added inline comments. INLINE COMMENTS > durin42 wrote in exchange.py:1490 > What's the deal with this function-level import? It doesn't appear to be > avoiding a cycle... At one time the series introduced a cycle. But the current series doesn't do that. So I suppose this can be rewritten to a file-level import for now. REPOSITORY rHG Mercurial REVISION DETAIL https://phab.mercurial-scm.org/D4480 To: indygreg, #hg-reviewers Cc: durin42, mercurial-devel ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
D4436: httppeer: expose capabilities for each command
indygreg added a comment. In https://phab.mercurial-scm.org/D4436#69390, @durin42 wrote: > Hm, I worry this isn't explicit enough. Do you have a specific reason for why this is a thing we should do? Honestly, I did this to make the subsequent patches easier. The way I'm going with the partial clone work, it is likely we'll need the peer to consult the capabilities data structure directly instead of trying to map everything to a string lookup (which is what `capable(name)` is doing). Specifically, for things like `changesetdata`, we'll likely start exposing the available data fields in the capabilities dict and clients will want a way to check if a specific field is available. So there's a good chance `capable(name)` isn't long for this world. At least not on version 2 peers. Things are still evolving. REPOSITORY rHG Mercurial REVISION DETAIL https://phab.mercurial-scm.org/D4436 To: indygreg, #hg-reviewers Cc: durin42, mercurial-devel ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
D4545: error: ensure ProgrammingError message is always a str
This revision was automatically updated to reflect the committed changes. Closed by commit rHG921aeb9ac508: error: ensure ProgrammingError message is always a str (authored by durin42, committed by ). REPOSITORY rHG Mercurial CHANGES SINCE LAST UPDATE https://phab.mercurial-scm.org/D4545?vs=10958=10959 REVISION DETAIL https://phab.mercurial-scm.org/D4545 AFFECTED FILES mercurial/error.py CHANGE DETAILS diff --git a/mercurial/error.py b/mercurial/error.py --- a/mercurial/error.py +++ b/mercurial/error.py @@ -215,6 +215,16 @@ class ProgrammingError(Hint, RuntimeError): """Raised if a mercurial (core or extension) developer made a mistake""" + +def __init__(self, msg, *args, **kwargs): +if not isinstance(msg, str): +# This means we're on Python 3, because we got a +# bytes. Turn the message back into a string since this is +# an internal-only error that won't be printed except in a +# stack traces. +msg = msg.decode('utf8') +super(ProgrammingError, self).__init__(msg, *args, **kwargs) + __bytes__ = _tobytes class WdirUnsupported(Exception): To: durin42, #hg-reviewers, pulkit Cc: mercurial-devel ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
D4545: error: ensure ProgrammingError message is always a str
durin42 updated this revision to Diff 10958. REPOSITORY rHG Mercurial CHANGES SINCE LAST UPDATE https://phab.mercurial-scm.org/D4545?vs=10953=10958 REVISION DETAIL https://phab.mercurial-scm.org/D4545 AFFECTED FILES mercurial/error.py CHANGE DETAILS diff --git a/mercurial/error.py b/mercurial/error.py --- a/mercurial/error.py +++ b/mercurial/error.py @@ -215,6 +215,16 @@ class ProgrammingError(Hint, RuntimeError): """Raised if a mercurial (core or extension) developer made a mistake""" + +def __init__(self, msg, *args, **kwargs): +if not isinstance(msg, str): +# This means we're on Python 3, because we got a +# bytes. Turn the message back into a string since this is +# an internal-only error that won't be printed except in a +# stack traces. +msg = msg.decode('utf8') +super(ProgrammingError, self).__init__(msg, *args, **kwargs) + __bytes__ = _tobytes class WdirUnsupported(Exception): To: durin42, #hg-reviewers, pulkit Cc: mercurial-devel ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
mercurial@39547: 15 new changesets (1 on stable)
15 new changesets (1 on stable) in mercurial: https://www.mercurial-scm.org/repo/hg/rev/f6bcb4f9cd3c changeset: 39533:f6bcb4f9cd3c user:Yuya Nishihara date:Tue Sep 11 22:38:32 2018 +0900 summary: ancestor: remove alias of initrevs from _lazyancestorsiter() https://www.mercurial-scm.org/repo/hg/rev/fd9029d36c41 changeset: 39534:fd9029d36c41 user:Yuya Nishihara date:Mon Sep 10 21:46:19 2018 +0900 summary: ancestor: return early from _lazyancestorsiter() when reached to stoprev https://www.mercurial-scm.org/repo/hg/rev/b9ee9c2e10dd changeset: 39535:b9ee9c2e10dd user:Yuya Nishihara date:Mon Sep 10 21:54:40 2018 +0900 summary: ancestor: unroll loop of parents in _lazyancestorsiter() https://www.mercurial-scm.org/repo/hg/rev/bdb177923291 changeset: 39536:bdb177923291 user:Yuya Nishihara date:Mon Sep 10 21:58:59 2018 +0900 summary: ancestor: optimize _lazyancestorsiter() for contiguous chains https://www.mercurial-scm.org/repo/hg/rev/ca9983c35d89 changeset: 39537:ca9983c35d89 user:Yuya Nishihara date:Tue Sep 11 22:36:51 2018 +0900 summary: ancestor: rename local aliases of heapq functions in _lazyancestorsiter() https://www.mercurial-scm.org/repo/hg/rev/238a1480d7ad changeset: 39538:238a1480d7ad user:Yuya Nishihara date:Mon Sep 10 22:34:19 2018 +0900 summary: ancestor: use heapreplace() in place of heappop/heappush() https://www.mercurial-scm.org/repo/hg/rev/8d8e61df8259 changeset: 39539:8d8e61df8259 user:Gregory Szorc date:Tue Sep 11 15:28:41 2018 -0700 summary: narrowspec: validate patterns when loading and saving spec file https://www.mercurial-scm.org/repo/hg/rev/ce20caecacbd changeset: 39540:ce20caecacbd user:Gregory Szorc date:Tue Sep 11 10:59:21 2018 -0700 summary: narrow: validate patterns on incoming bundle2 part https://www.mercurial-scm.org/repo/hg/rev/8301741e1f89 changeset: 39541:8301741e1f89 user:Gregory Szorc date:Tue Sep 11 11:47:10 2018 -0700 summary: narrow: validate spec files are well-formed during clone (BC) https://www.mercurial-scm.org/repo/hg/rev/0a5f7e16ec96 changeset: 39542:0a5f7e16ec96 user:Martin von Zweigbergk date:Tue Sep 11 16:04:55 2018 -0700 summary: tests: drop extra "file:" prefix from paths in narrow test https://www.mercurial-scm.org/repo/hg/rev/2182e67ea912 changeset: 39543:2182e67ea912 user:Gregory Szorc date:Fri Sep 07 18:35:54 2018 -0700 summary: fastannotate: use repo.local() https://www.mercurial-scm.org/repo/hg/rev/10a8472f6662 changeset: 39544:10a8472f6662 user:Gregory Szorc date:Tue Sep 11 15:53:12 2018 -0700 summary: narrow: drop support for remote expansion (BC) https://www.mercurial-scm.org/repo/hg/rev/4afd2af36456 changeset: 39545:4afd2af36456 user:Gregory Szorc date:Tue Sep 11 15:40:33 2018 -0700 summary: narrow: set opts['narrow'] instead of local variable https://www.mercurial-scm.org/repo/hg/rev/41aa5dced975 changeset: 39546:41aa5dced975 bookmark:@ user:Gregory Szorc date:Fri Sep 07 15:57:55 2018 -0700 summary: localrepo: pass ui to newreporequirements() (API) https://www.mercurial-scm.org/repo/hg/rev/41ac8ea1bdd7 changeset: 39547:41ac8ea1bdd7 branch: stable tag: tip parent: 39455:6af7765bdb7c user:Matt Harbison date:Tue Sep 11 13:52:17 2018 -0400 summary: subrepo: mask out passwords embedded in the messages displaying a URL -- Repository URL: https://www.mercurial-scm.org/repo/hg ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
D4546: tests: handle Python 3 not quoting non-empty-directory error
This revision was automatically updated to reflect the committed changes. Closed by commit rHGcb1329738d64: tests: handle Python 3 not quoting non-empty-directory error (authored by durin42, committed by ). REPOSITORY rHG Mercurial CHANGES SINCE LAST UPDATE https://phab.mercurial-scm.org/D4546?vs=10954=10956 REVISION DETAIL https://phab.mercurial-scm.org/D4546 AFFECTED FILES tests/test-merge1.t tests/test-update-names.t CHANGE DETAILS diff --git a/tests/test-update-names.t b/tests/test-update-names.t --- a/tests/test-update-names.t +++ b/tests/test-update-names.t @@ -50,8 +50,8 @@ $ hg st ? name/file $ hg up 1 - abort: Unlinking directory not permitted: '$TESTTMP/r1/r2/name' (windows !) - abort: Directory not empty: '$TESTTMP/r1/r2/name' (no-windows !) + abort: Unlinking directory not permitted: '?$TESTTMP/r1/r2/name'? (re) (windows !) + abort: Directory not empty: '?\$TESTTMP/r1/r2/name'? (re) (no-windows !) [255] $ cat name/file text diff --git a/tests/test-merge1.t b/tests/test-merge1.t --- a/tests/test-merge1.t +++ b/tests/test-merge1.t @@ -30,8 +30,8 @@ $ mkdir b && touch b/nonempty $ hg up - abort: Unlinking directory not permitted: '$TESTTMP/t/b' (windows !) - abort: Directory not empty: '$TESTTMP/t/b' (no-windows !) + abort: Unlinking directory not permitted: '?\$TESTTMP/t/b'? (re) (windows !) + abort: Directory not empty: '?\$TESTTMP/t/b'? (re) (no-windows !) [255] $ hg ci abort: last update was interrupted To: durin42, #hg-reviewers, pulkit Cc: mercurial-devel ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
D4547: py3: whitelist a test caught by the ratchet
This revision was automatically updated to reflect the committed changes. Closed by commit rHGb781709799f6: py3: whitelist a test caught by the ratchet (authored by durin42, committed by ). REPOSITORY rHG Mercurial CHANGES SINCE LAST UPDATE https://phab.mercurial-scm.org/D4547?vs=10955=10957 REVISION DETAIL https://phab.mercurial-scm.org/D4547 AFFECTED FILES contrib/python3-whitelist CHANGE DETAILS diff --git a/contrib/python3-whitelist b/contrib/python3-whitelist --- a/contrib/python3-whitelist +++ b/contrib/python3-whitelist @@ -247,6 +247,7 @@ test-issue4074.t test-issue522.t test-issue586.t +test-issue5979.t test-issue612.t test-issue619.t test-issue660.t To: durin42, pulkit, #hg-reviewers Cc: mercurial-devel ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
D4546: tests: handle Python 3 not quoting non-empty-directory error
durin42 created this revision. Herald added a subscriber: mercurial-devel. Herald added a reviewer: hg-reviewers. REVISION SUMMARY I assume this happens on Windows too, so I did the same regex on both versions of the output. The whole message printed by these aborts comes from Python, so if we want to exert control over the quoting here it'll be a bit of a pain. REPOSITORY rHG Mercurial REVISION DETAIL https://phab.mercurial-scm.org/D4546 AFFECTED FILES tests/test-merge1.t tests/test-update-names.t CHANGE DETAILS diff --git a/tests/test-update-names.t b/tests/test-update-names.t --- a/tests/test-update-names.t +++ b/tests/test-update-names.t @@ -50,8 +50,8 @@ $ hg st ? name/file $ hg up 1 - abort: Unlinking directory not permitted: '$TESTTMP/r1/r2/name' (windows !) - abort: Directory not empty: '$TESTTMP/r1/r2/name' (no-windows !) + abort: Unlinking directory not permitted: '?$TESTTMP/r1/r2/name'? (re) (windows !) + abort: Directory not empty: '?\$TESTTMP/r1/r2/name'? (re) (no-windows !) [255] $ cat name/file text diff --git a/tests/test-merge1.t b/tests/test-merge1.t --- a/tests/test-merge1.t +++ b/tests/test-merge1.t @@ -30,8 +30,8 @@ $ mkdir b && touch b/nonempty $ hg up - abort: Unlinking directory not permitted: '$TESTTMP/t/b' (windows !) - abort: Directory not empty: '$TESTTMP/t/b' (no-windows !) + abort: Unlinking directory not permitted: '?\$TESTTMP/t/b'? (re) (windows !) + abort: Directory not empty: '?\$TESTTMP/t/b'? (re) (no-windows !) [255] $ hg ci abort: last update was interrupted To: durin42, #hg-reviewers Cc: mercurial-devel ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
D4547: py3: whitelist a test caught by the ratchet
durin42 created this revision. Herald added a reviewer: pulkit. Herald added a subscriber: mercurial-devel. Herald added a reviewer: hg-reviewers. REPOSITORY rHG Mercurial REVISION DETAIL https://phab.mercurial-scm.org/D4547 AFFECTED FILES contrib/python3-whitelist CHANGE DETAILS diff --git a/contrib/python3-whitelist b/contrib/python3-whitelist --- a/contrib/python3-whitelist +++ b/contrib/python3-whitelist @@ -247,6 +247,7 @@ test-issue4074.t test-issue522.t test-issue586.t +test-issue5979.t test-issue612.t test-issue619.t test-issue660.t To: durin42, pulkit, #hg-reviewers Cc: mercurial-devel ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
D4543: context: don't count deleted files as candidates for path conflicts in IMM
This revision was automatically updated to reflect the committed changes. Closed by commit rHGfa4d16daf1be: context: dont count deleted files as candidates for path conflicts in IMM (authored by pulkit, committed by ). REPOSITORY rHG Mercurial CHANGES SINCE LAST UPDATE https://phab.mercurial-scm.org/D4543?vs=10949=10952 REVISION DETAIL https://phab.mercurial-scm.org/D4543 AFFECTED FILES mercurial/context.py tests/test-rebase-inmemory.t CHANGE DETAILS diff --git a/tests/test-rebase-inmemory.t b/tests/test-rebase-inmemory.t --- a/tests/test-rebase-inmemory.t +++ b/tests/test-rebase-inmemory.t @@ -218,8 +218,25 @@ $ hg rebase -r . -d 5 rebasing 7:855e9797387e "added a back!" (tip) - abort: error: file 'a' cannot be written because 'a/' is a folder in 9b94b9373deb (containing 1 entries: a/a) - [255] + saved backup bundle to $TESTTMP/repo1/repo2/.hg/strip-backup/855e9797387e-81ee4c5d-rebase.hg + + $ hg tglog + @ 7: bb3f02be2688 'added a back!' + | + | o 6: d14530e5e3e6 'added bar' + | | + o | 5: 9b94b9373deb 'added foo' + |/ + o 4: c6ad37a4f250 'a/a' + | + | o 3: 844a7de3e617 'c' + | | + o | 2: 09c044d2cb43 'd' + | | + o | 1: fc055c3b4d33 'b' + |/ + o 0: b173517d0057 'a' + $ cd .. diff --git a/mercurial/context.py b/mercurial/context.py --- a/mercurial/context.py +++ b/mercurial/context.py @@ -1910,14 +1910,19 @@ # in p1 (test that p1 doesn't any paths matching `path/*`). match = matchmod.match('/', '', [path + '/'], default=b'relpath') matches = self.p1().manifest().matches(match) -if len(matches) > 0: -if len(matches) == 1 and matches.keys()[0] == path: +mfiles = matches.keys() +if len(mfiles) > 0: +if len(mfiles) == 1 and mfiles[0] == path: +return +# omit the files which are deleted in current IMM wctx +mfiles = [m for m in mfiles if self._cache[m]['exists']] +if not mfiles: return raise error.Abort("error: file '%s' cannot be written because " " '%s/' is a folder in %s (containing %d " "entries: %s)" - % (path, path, self.p1(), len(matches), - ', '.join(matches.keys( + % (path, path, self.p1(), len(mfiles), + ', '.join(mfiles))) def write(self, path, data, flags='', **kwargs): if data is None: To: pulkit, #hg-reviewers Cc: mercurial-devel ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
D4545: error: ensure ProgrammingError message is always a str
durin42 created this revision. Herald added a subscriber: mercurial-devel. Herald added a reviewer: hg-reviewers. REVISION SUMMARY Since this error is internal-only and a runtime error, let's give it a treatment that makes it behave identically when repr()d on both Python 2 and Python 3. REPOSITORY rHG Mercurial REVISION DETAIL https://phab.mercurial-scm.org/D4545 AFFECTED FILES mercurial/error.py CHANGE DETAILS diff --git a/mercurial/error.py b/mercurial/error.py --- a/mercurial/error.py +++ b/mercurial/error.py @@ -215,6 +215,16 @@ class ProgrammingError(Hint, RuntimeError): """Raised if a mercurial (core or extension) developer made a mistake""" + +def __init__(self, msg): +if not isinstance(msg, str): +# This means we're on Python 3, because we got a +# bytes. Turn the message back into a string since this is +# an internal-only error that won't be printed except in a +# stack traces. +msg = msg.decode('utf8') +super(ProgrammingError, self).__init__(msg) + __bytes__ = _tobytes class WdirUnsupported(Exception): To: durin42, #hg-reviewers Cc: mercurial-devel ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
D4544: rebase: add tests showing patch conflict detection needs to be smarter in IMM
This revision was automatically updated to reflect the committed changes. Closed by commit rHGaa022f8873ea: rebase: add tests showing patch conflict detection needs to be smarter in IMM (authored by pulkit, committed by ). REPOSITORY rHG Mercurial CHANGES SINCE LAST UPDATE https://phab.mercurial-scm.org/D4544?vs=10950=10951 REVISION DETAIL https://phab.mercurial-scm.org/D4544 AFFECTED FILES tests/test-rebase-inmemory.t CHANGE DETAILS diff --git a/tests/test-rebase-inmemory.t b/tests/test-rebase-inmemory.t --- a/tests/test-rebase-inmemory.t +++ b/tests/test-rebase-inmemory.t @@ -179,6 +179,48 @@ rebasing 4:daf7dfc139cb "a/a" (tip) saved backup bundle to $TESTTMP/repo1/repo2/.hg/strip-backup/daf7dfc139cb-fdbfcf4f-rebase.hg + $ hg tglog + @ 4: c6ad37a4f250 'a/a' + | + | o 3: 844a7de3e617 'c' + | | + o | 2: 09c044d2cb43 'd' + | | + o | 1: fc055c3b4d33 'b' + |/ + o 0: b173517d0057 'a' + + $ echo foo > foo + $ hg ci -Aqm "added foo" + $ hg up '.^' + 0 files updated, 0 files merged, 1 files removed, 0 files unresolved + $ echo bar > bar + $ hg ci -Aqm "added bar" + $ hg rm a/a + $ echo a > a + $ hg ci -Aqm "added a back!" + $ hg tglog + @ 7: 855e9797387e 'added a back!' + | + o 6: d14530e5e3e6 'added bar' + | + | o 5: 9b94b9373deb 'added foo' + |/ + o 4: c6ad37a4f250 'a/a' + | + | o 3: 844a7de3e617 'c' + | | + o | 2: 09c044d2cb43 'd' + | | + o | 1: fc055c3b4d33 'b' + |/ + o 0: b173517d0057 'a' + + $ hg rebase -r . -d 5 + rebasing 7:855e9797387e "added a back!" (tip) + abort: error: file 'a' cannot be written because 'a/' is a folder in 9b94b9373deb (containing 1 entries: a/a) + [255] + $ cd .. Test dry-run rebasing To: pulkit, #hg-reviewers Cc: mercurial-devel ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
reaping old phabricator patches?
Howdy folks, We've got a fair stack of dead-ish patches in phabricator. Would anyone object to automatically marking everything that hasn't been touched since, say, the end of March as abandoned for now? Thanks, Augie ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
D4490: wireprotov2: define and implement "filedata" command
durin42 added a comment. Oh, one more thing: I think this, as-stated, will make it at best challenging to have ACLed branches: we'd have to, on the server, walk the linknodes and see if the client was authorized to see any branch(es) that contain the node. That's probably okayer for us than it was for git (since we have linkrevs at least), but it's still worth considering. REPOSITORY rHG Mercurial REVISION DETAIL https://phab.mercurial-scm.org/D4490 To: indygreg, #hg-reviewers, durin42 Cc: durin42, mercurial-devel ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
D4490: wireprotov2: define and implement "filedata" command
durin42 accepted this revision. durin42 added a comment. This revision is now accepted and ready to land. In general I'm happy with where this is going, but I'm extremely uncomfortable with the manifest and filelog commands requiring so much client-server transfer to get everything, especially the rpc-per-file nature of this. It's elegant in terms of how easy it'll make remotefilelog et al, but it makes me worried about performance in the small-repo case where today we can just issue one big hoss RPC for everything and we get it all in one go. REPOSITORY rHG Mercurial REVISION DETAIL https://phab.mercurial-scm.org/D4490 To: indygreg, #hg-reviewers, durin42 Cc: durin42, mercurial-devel ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
D4488: wireprotov2: define and implement "manifestdata" command
durin42 added a comment. Could you add a TODO about the overhead of having to enumerate every node required? That'll be prohibitive fairly quickly I think. REPOSITORY rHG Mercurial REVISION DETAIL https://phab.mercurial-scm.org/D4488 To: indygreg, #hg-reviewers Cc: durin42, mercurial-devel ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
D4543: context: don't count deleted files as candidates for path conflicts in IMM
pulkit created this revision. Herald added a subscriber: mercurial-devel. Herald added a reviewer: hg-reviewers. REVISION SUMMARY This patch makes sure we don't consider the deleted files in our IMM wctx as potential conflicts while calculating paths conflicts. This fixes the bug demonstrated in previous patch. REPOSITORY rHG Mercurial REVISION DETAIL https://phab.mercurial-scm.org/D4543 AFFECTED FILES mercurial/context.py tests/test-rebase-inmemory.t CHANGE DETAILS diff --git a/tests/test-rebase-inmemory.t b/tests/test-rebase-inmemory.t --- a/tests/test-rebase-inmemory.t +++ b/tests/test-rebase-inmemory.t @@ -218,8 +218,25 @@ $ hg rebase -r . -d 5 rebasing 7:855e9797387e "added a back!" (tip) - abort: error: file 'a' cannot be written because 'a/' is a folder in 9b94b9373deb (containing 1 entries: a/a) - [255] + saved backup bundle to $TESTTMP/repo1/repo2/.hg/strip-backup/855e9797387e-81ee4c5d-rebase.hg + + $ hg tglog + @ 7: bb3f02be2688 'added a back!' + | + | o 6: d14530e5e3e6 'added bar' + | | + o | 5: 9b94b9373deb 'added foo' + |/ + o 4: c6ad37a4f250 'a/a' + | + | o 3: 844a7de3e617 'c' + | | + o | 2: 09c044d2cb43 'd' + | | + o | 1: fc055c3b4d33 'b' + |/ + o 0: b173517d0057 'a' + $ cd .. diff --git a/mercurial/context.py b/mercurial/context.py --- a/mercurial/context.py +++ b/mercurial/context.py @@ -1910,14 +1910,19 @@ # in p1 (test that p1 doesn't any paths matching `path/*`). match = matchmod.match('/', '', [path + '/'], default=b'relpath') matches = self.p1().manifest().matches(match) -if len(matches) > 0: -if len(matches) == 1 and matches.keys()[0] == path: +mfiles = matches.keys() +if len(mfiles) > 0: +if len(mfiles) == 1 and mfiles[0] == path: +return +# omit the files which are deleted in current IMM wctx +mfiles = [m for m in mfiles if self._cache[m]['exists']] +if not mfiles: return raise error.Abort("error: file '%s' cannot be written because " " '%s/' is a folder in %s (containing %d " "entries: %s)" - % (path, path, self.p1(), len(matches), - ', '.join(matches.keys( + % (path, path, self.p1(), len(mfiles), + ', '.join(mfiles))) def write(self, path, data, flags='', **kwargs): if data is None: To: pulkit, #hg-reviewers Cc: mercurial-devel ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
D4544: rebase: add tests showing patch conflict detection needs to be smarter in IMM
pulkit created this revision. Herald added a subscriber: mercurial-devel. Herald added a reviewer: hg-reviewers. REVISION SUMMARY This patch adds test which shows that you can't rebase a cset which removes a dir and adds a file of the same as that of dir as there are False positives path conflicts reported. I fixed the case when there is a file and we adds a dir of same name while removing the file, but missed testing the current case. Next patch will fix this. REPOSITORY rHG Mercurial REVISION DETAIL https://phab.mercurial-scm.org/D4544 AFFECTED FILES tests/test-rebase-inmemory.t CHANGE DETAILS diff --git a/tests/test-rebase-inmemory.t b/tests/test-rebase-inmemory.t --- a/tests/test-rebase-inmemory.t +++ b/tests/test-rebase-inmemory.t @@ -179,6 +179,48 @@ rebasing 4:daf7dfc139cb "a/a" (tip) saved backup bundle to $TESTTMP/repo1/repo2/.hg/strip-backup/daf7dfc139cb-fdbfcf4f-rebase.hg + $ hg tglog + @ 4: c6ad37a4f250 'a/a' + | + | o 3: 844a7de3e617 'c' + | | + o | 2: 09c044d2cb43 'd' + | | + o | 1: fc055c3b4d33 'b' + |/ + o 0: b173517d0057 'a' + + $ echo foo > foo + $ hg ci -Aqm "added foo" + $ hg up '.^' + 0 files updated, 0 files merged, 1 files removed, 0 files unresolved + $ echo bar > bar + $ hg ci -Aqm "added bar" + $ hg rm a/a + $ echo a > a + $ hg ci -Aqm "added a back!" + $ hg tglog + @ 7: 855e9797387e 'added a back!' + | + o 6: d14530e5e3e6 'added bar' + | + | o 5: 9b94b9373deb 'added foo' + |/ + o 4: c6ad37a4f250 'a/a' + | + | o 3: 844a7de3e617 'c' + | | + o | 2: 09c044d2cb43 'd' + | | + o | 1: fc055c3b4d33 'b' + |/ + o 0: b173517d0057 'a' + + $ hg rebase -r . -d 5 + rebasing 7:855e9797387e "added a back!" (tip) + abort: error: file 'a' cannot be written because 'a/' is a folder in 9b94b9373deb (containing 1 entries: a/a) + [255] + $ cd .. Test dry-run rebasing To: pulkit, #hg-reviewers Cc: mercurial-devel ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
D4519: zsh_completion: add new and remove deprecated flags
This revision was automatically updated to reflect the committed changes. Closed by commit rHGa2d17b699628: zsh_completion: add new and remove deprecated flags (authored by av6, committed by ). REPOSITORY rHG Mercurial CHANGES SINCE LAST UPDATE https://phab.mercurial-scm.org/D4519?vs=10854=10948 REVISION DETAIL https://phab.mercurial-scm.org/D4519 AFFECTED FILES contrib/zsh_completion CHANGE DETAILS diff --git a/contrib/zsh_completion b/contrib/zsh_completion --- a/contrib/zsh_completion +++ b/contrib/zsh_completion @@ -422,7 +422,9 @@ _hg_diff_opts=( $_hg_gitlike_opts '(--text -a)'{-a,--text}'[treat all files as text]' - '--nodates[omit dates from diff headers]') + '--binary[generate binary diffs in git mode (default)]' + '--nodates[omit dates from diff headers]' +) _hg_mergetool_opts=( '(--tool -t)'{-t+,--tool=}'[specify merge tool]:merge tool:_hg_merge_tools' @@ -511,8 +513,8 @@ _hg_cmd_backout() { _arguments -s -S : $_hg_global_opts $_hg_mergetool_opts $_hg_pat_opts \ '--merge[merge with old dirstate parent after backout]' \ +'--no-commit[do not commit]' \ '(--date -d)'{-d+,--date=}'[record the specified date as commit date]:date' \ -'--parent[parent to choose when backing out merge]' \ '(--user -u)'{-u+,--user=}'[record the specified user as committer]:user' \ '(--rev -r 1)'{-r+,--rev=}'[revision to backout]:revision:_hg_labels' \ '(--message -m)'{-m+,--message=}'[use as commit message]:text' \ @@ -612,7 +614,6 @@ '--noprefix[omit a/ and b/ prefixes from filenames]' \ '(--show-function -p)'{-p,--show-function}'[show which function each change is in]' \ '(--change -c)'{-c+,--change=}'[change made by revision]:revision:_hg_labels' \ - '(--text -a)'{-a,--text}'[treat all files as text]' \ '--reverse[produce a diff that undoes the changes]' \ '(--unified -U)'{-U+,--unified=}'[number of lines of context to show]:count' \ '--stat[output diffstat-style summary of changes]' \ @@ -634,6 +635,7 @@ _hg_cmd_export() { _arguments -s -S : $_hg_global_opts $_hg_diff_opts \ + '(--bookmark -B)'{-B+,--bookmark=}'[export changes only reachable by given bookmark]:bookmark:_hg_bookmarks' \ '(--output -o)'{-o+,--output=}'[print output to file with formatted name]:format string' \ '--switch-parent[diff against the second parent]' \ '*'{-r+,--rev=}'[revisions to export]:revision:_hg_labels' \ @@ -661,13 +663,16 @@ '(--continue -c --abort -a)'{-a,--abort}'[abort interrupted graft]' \ '(--edit -e)'{-e,--edit}'[invoke editor on commit messages]' \ '--log[append graft info to log message]' \ + "--no-commit[don't commit, just apply the changes in working directory]" \ + '(--force -f)'{-f,--force}'[force graft]' \ '*:revision:_hg_labels' } _hg_cmd_grep() { _arguments -s -S : $_hg_global_opts $_hg_pat_opts \ '(--print0 -0)'{-0,--print0}'[end fields with NUL]' \ - '--all[print all revisions with matches]' \ + '--diff[print all revisions when the term was introduced or removed]' \ + '(--text -a)'{-a,--text}'[treat all files as text]' \ '(--follow -f)'{-f,--follow}'[follow changeset history, or file history across copies and renames]' \ '(--ignore-case -i)'{-i,--ignore-case}'[ignore case when matching]' \ '(--files-with-matches -l)'{-l,--files-with-matches}'[print only filenames and revisions that match]' \ @@ -691,6 +696,7 @@ '(--extension -e)'{-e,--extension}'[show only help for extensions]' \ '(--command -c)'{-c,--command}'[show only help for commands]' \ '(--keyword -k)'{-k,--keyword}'[show topics matching keyword]' \ + '*'{-s+,--system=}'[show help for specific platform(s)]:platform:(windows vms plan9 unix)' \ '*:mercurial help topic:_hg_help_topics' } @@ -707,11 +713,11 @@ _hg_cmd_import() { _arguments -s -S : $_hg_global_opts $_hg_commit_opts \ '(--strip -p)'{-p+,--strip=}'[directory strip option for patch (default: 1)]:count' \ - '(--force -f)'{-f,--force}'[skip check for outstanding uncommitted changes]' \ '--bypass[apply patch without touching the working directory]' \ '--no-commit[do not commit, just update the working directory]' \ '--partial[commit even if some hunks fail]' \ '--exact[abort if patch would apply lossily]' \ + '--prefix=[apply patch to subdirectory]:directory:_files -/' \ '--import-branch[use any branch information in patch (implied by --exact)]' \ '(--date -d)'{-d+,--date=}'[record the specified date as commit date]:date' \ '(--user -u)'{-u+,--user=}'[record the specified user as committer]:user' \ @@ -744,11 +750,11 @@ _hg_cmd_log() { _arguments -s -S : $_hg_log_opts $_hg_pat_opts \ - '(--follow --follow-first -f)'{-f,--follow}'[follow changeset history, or file history across copies and renames]' \ - '(-f --follow)--follow-first[only follow the first parent of merge changesets]' \ + '(--follow -f)'{-f,--follow}'[follow changeset history, or file history across copies and renames]' \ '(--copies
D4518: zsh_completion: update various arguments, descriptions, metavariables
This revision was automatically updated to reflect the committed changes. Closed by commit rHG5f06c21d37de: zsh_completion: update various arguments, descriptions, metavariables (authored by av6, committed by ). REPOSITORY rHG Mercurial CHANGES SINCE LAST UPDATE https://phab.mercurial-scm.org/D4518?vs=10853=10947 REVISION DETAIL https://phab.mercurial-scm.org/D4518 AFFECTED FILES contrib/zsh_completion CHANGE DETAILS diff --git a/contrib/zsh_completion b/contrib/zsh_completion --- a/contrib/zsh_completion +++ b/contrib/zsh_completion @@ -384,7 +384,7 @@ '--cwd=[change working directory]:new working directory:_files -/' '(--noninteractive -y)'{-y,--noninteractive}'[do not prompt, automatically pick the first choice for all prompts]' '(--verbose -v)'{-v,--verbose}'[enable additional output]' -'*--config[set/override config option]:defined config items:_hg_config' +'*--config=[set/override config option]:defined config items:_hg_config' '(--quiet -q)'{-q,--quiet}'[suppress output]' '(--help -h)'{-h,--help}'[display help and exit]' '--debug[enable debugging output]' @@ -401,8 +401,8 @@ ) _hg_pat_opts=( - '*'{-I+,--include=}'[include names matching the given patterns]:dir:_files -W $(_hg_cmd root) -/' - '*'{-X+,--exclude=}'[exclude names matching the given patterns]:dir:_files -W $(_hg_cmd root) -/') + '*'{-I+,--include=}'[include names matching the given patterns]:pattern:_files -W $(_hg_cmd root) -/' + '*'{-X+,--exclude=}'[exclude names matching the given patterns]:pattern:_files -W $(_hg_cmd root) -/') _hg_clone_opts=( $_hg_remote_opts @@ -439,7 +439,7 @@ ) _hg_template_opts=( - '--template[display with template]:template' + '(--template -T)'{-T+,--template=}'[display with template]:template' ) _hg_log_opts=( @@ -558,24 +558,24 @@ '(2)*--base[a base changeset assumed to be available at the destination]:revision:_hg_labels' \ '*'{-b+,--branch=}'[a specific branch you would like to bundle]:branch:_hg_branches' \ '*'{-r+,--rev=}'[a changeset intended to be added to the destination]:revision:_hg_labels' \ - '--all[bundle all changesets in the repository]' \ + '(--all -a)'{-a,--all}'[bundle all changesets in the repository]' \ '--type[bundle compression type to use (default: bzip2)]:bundle type' \ ':output file:_files' \ ':destination repository:_files -/' } _hg_cmd_cat() { _arguments -s -S : $_hg_global_opts $_hg_pat_opts \ '(--output -o)'{-o+,--output=}'[print output to file with formatted name]:format string' \ - '(--rev -r)'{-r+,--rev=}'[revision]:revision:_hg_labels' \ + '(--rev -r)'{-r+,--rev=}'[print the given revision]:revision:_hg_labels' \ '--decode[apply any matching decode filter]' \ '*:file:_hg_files' } _hg_cmd_clone() { _arguments -s -S : $_hg_global_opts $_hg_clone_opts \ '*'{-r+,--rev=}'[do not clone everything, but include this changeset and its ancestors]:revision' \ - '(--updaterev -u)'{-u+,--updaterev=}'[revision, tag or branch to check out]:revision' \ + '(--updaterev -u)'{-u+,--updaterev=}'[revision, tag, or branch to check out]:revision' \ '*'{-b+,--branch=}"[do not clone everything, but include this branch's changesets and their ancestors]:branch" \ ':source repository:_hg_remote' \ ':destination:_hg_clone_dest' @@ -642,7 +642,7 @@ _hg_cmd_files() { _arguments -s -S : $_hg_global_opts $_hg_pat_opts $_hg_subrepos_opts \ - '(--rev -r)'{-r+,--rev=}'[search the repository as it is in REV]:revision:_hg_labels' \ + '(--rev -r)'{-r+,--rev=}'[search the repository as it is in revision]:revision:_hg_labels' \ '(--print0 -0)'{-0,--print0}'[end filenames with NUL, for use with xargs]' \ '*:file:_hg_files' } @@ -666,24 +666,24 @@ _hg_cmd_grep() { _arguments -s -S : $_hg_global_opts $_hg_pat_opts \ - '(--print0 -0)'{-0,--print0}'[end filenames with NUL]' \ + '(--print0 -0)'{-0,--print0}'[end fields with NUL]' \ '--all[print all revisions with matches]' \ - '(--follow -f)'{-f,--follow}'[follow changeset or file history]' \ + '(--follow -f)'{-f,--follow}'[follow changeset history, or file history across copies and renames]' \ '(--ignore-case -i)'{-i,--ignore-case}'[ignore case when matching]' \ - '(--files-with-matches -l)'{-l,--files-with-matches}'[print only filenames and revs that match]' \ + '(--files-with-matches -l)'{-l,--files-with-matches}'[print only filenames and revisions that match]' \ '(--line-number -n)'{-n,--line-number}'[print matching line numbers]' \ - '*'{-r+,--rev=}'[search in given revision range]:revision:_hg_revrange' \ - '(--user -u)'{-u,--user}'[print user who committed change]' \ - '(--date -d)'{-d,--date}'[print date of a changeset]' \ + '*'{-r+,--rev=}'[only search files changed within revision range]:revision:_hg_revrange' \ + '(--user -u)'{-u,--user}'[list the author (long with -v)]' \ + '(--date -d)'{-d,--date}'[list the date (short with -q)]' \ '1:search pattern:' \
D4475: setup: don't support py 3.5.0, 3.5.1, 3.5.2 because of bug in codecs
This revision was automatically updated to reflect the committed changes. Closed by commit rHGb6b9488aae4c: setup: dont support py 3.5.0, 3.5.1, 3.5.2 because of bug in codecs (authored by pulkit, committed by ). REPOSITORY rHG Mercurial CHANGES SINCE LAST UPDATE https://phab.mercurial-scm.org/D4475?vs=10772=10946 REVISION DETAIL https://phab.mercurial-scm.org/D4475 AFFECTED FILES setup.py CHANGE DETAILS diff --git a/setup.py b/setup.py --- a/setup.py +++ b/setup.py @@ -11,6 +11,9 @@ # Mercurial will never work on Python 3 before 3.5 due to a lack # of % formatting on bytestrings, and can't work on 3.6.0 or 3.6.1 # due to a bug in % formatting in bytestrings. +# We cannot support Python 3.5.0, 3.5.1, 3.5.2 because of bug in +# codecs.escape_encode() where it raises SystemError on empty bytestring +# bug link: https://bugs.python.org/issue25270 # # TODO: when we actually work on Python 3, use this string as the # actual supportedpy string. @@ -21,6 +24,9 @@ '!=3.2.*', '!=3.3.*', '!=3.4.*', +'!=3.5.0', +'!=3.5.1', +'!=3.5.2', '!=3.6.0', '!=3.6.1', ]) To: pulkit, #hg-reviewers, indygreg Cc: indygreg, durin42, mercurial-devel ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
D4506: util: update lrucachedict order during get()
This revision was automatically updated to reflect the committed changes. Closed by commit rHG8f2c0d1b454c: util: update lrucachedict order during get() (authored by indygreg, committed by ). REPOSITORY rHG Mercurial CHANGES SINCE LAST UPDATE https://phab.mercurial-scm.org/D4506?vs=10831=10945 REVISION DETAIL https://phab.mercurial-scm.org/D4506 AFFECTED FILES mercurial/util.py tests/test-lrucachedict.py CHANGE DETAILS diff --git a/tests/test-lrucachedict.py b/tests/test-lrucachedict.py --- a/tests/test-lrucachedict.py +++ b/tests/test-lrucachedict.py @@ -67,6 +67,18 @@ for key in ('a', 'b'): self.assertIn(key, d) +def testget(self): +d = util.lrucachedict(4) +d['a'] = 'va' +d['b'] = 'vb' +d['c'] = 'vc' + +self.assertIsNone(d.get('missing')) +self.assertEqual(list(d), ['c', 'b', 'a']) + +self.assertEqual(d.get('a'), 'va') +self.assertEqual(list(d), ['a', 'c', 'b']) + def testcopypartial(self): d = util.lrucachedict(4) d.insert('a', 'va', cost=4) diff --git a/mercurial/util.py b/mercurial/util.py --- a/mercurial/util.py +++ b/mercurial/util.py @@ -1332,7 +1332,7 @@ def get(self, k, default=None): try: -return self._cache[k].value +return self.__getitem__(k) except KeyError: return default To: indygreg, #hg-reviewers Cc: mercurial-devel ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
D4503: util: teach lrucachedict to enforce a max total cost
This revision was automatically updated to reflect the committed changes. Closed by commit rHG842cd0bdda75: util: teach lrucachedict to enforce a max total cost (authored by indygreg, committed by ). REPOSITORY rHG Mercurial CHANGES SINCE LAST UPDATE https://phab.mercurial-scm.org/D4503?vs=10822=10942 REVISION DETAIL https://phab.mercurial-scm.org/D4503 AFFECTED FILES contrib/perf.py mercurial/util.py tests/test-lrucachedict.py CHANGE DETAILS diff --git a/tests/test-lrucachedict.py b/tests/test-lrucachedict.py --- a/tests/test-lrucachedict.py +++ b/tests/test-lrucachedict.py @@ -133,6 +133,22 @@ for key in ('a', 'b', 'c', 'd'): self.assertEqual(d[key], 'v%s' % key) +d = util.lrucachedict(4, maxcost=42) +d.insert('a', 'va', cost=5) +d.insert('b', 'vb', cost=4) +d.insert('c', 'vc', cost=3) +dc = d.copy() +self.assertEqual(dc.maxcost, 42) +self.assertEqual(len(dc), 3) + +# Max cost can be lowered as part of copy. +dc = d.copy(maxcost=10) +self.assertEqual(dc.maxcost, 10) +self.assertEqual(len(dc), 2) +self.assertEqual(dc.totalcost, 7) +self.assertIn('b', dc) +self.assertIn('c', dc) + def testcopydecreasecapacity(self): d = util.lrucachedict(5) d.insert('a', 'va', cost=4) @@ -217,5 +233,93 @@ d['a'] = 'va' self.assertEqual(d.popoldest(), ('b', 'vb')) +def testmaxcost(self): +# Item cost is zero by default. +d = util.lrucachedict(6, maxcost=10) +d['a'] = 'va' +d['b'] = 'vb' +d['c'] = 'vc' +d['d'] = 'vd' +self.assertEqual(len(d), 4) +self.assertEqual(d.totalcost, 0) + +d.clear() + +# Insertion to exact cost threshold works without eviction. +d.insert('a', 'va', cost=6) +d.insert('b', 'vb', cost=4) + +self.assertEqual(len(d), 2) +self.assertEqual(d['a'], 'va') +self.assertEqual(d['b'], 'vb') + +# Inserting a new element with 0 cost works. +d['c'] = 'vc' +self.assertEqual(len(d), 3) + +# Inserting a new element with cost putting us above high +# water mark evicts oldest single item. +d.insert('d', 'vd', cost=1) +self.assertEqual(len(d), 3) +self.assertEqual(d.totalcost, 5) +self.assertNotIn('a', d) +for key in ('b', 'c', 'd'): +self.assertEqual(d[key], 'v%s' % key) + +# Inserting a new element with enough room for just itself +# evicts all items before. +d.insert('e', 've', cost=10) +self.assertEqual(len(d), 1) +self.assertEqual(d.totalcost, 10) +self.assertIn('e', d) + +# Inserting a new element with cost greater than threshold +# still retains that item. +d.insert('f', 'vf', cost=11) +self.assertEqual(len(d), 1) +self.assertEqual(d.totalcost, 11) +self.assertIn('f', d) + +# Inserting a new element will evict the last item since it is +# too large. +d['g'] = 'vg' +self.assertEqual(len(d), 1) +self.assertEqual(d.totalcost, 0) +self.assertIn('g', d) + +d.clear() + +d.insert('a', 'va', cost=7) +d.insert('b', 'vb', cost=3) +self.assertEqual(len(d), 2) + +# Replacing a value with smaller cost won't result in eviction. +d.insert('b', 'vb2', cost=2) +self.assertEqual(len(d), 2) + +# Replacing a value with a higher cost will evict when threshold +# exceeded. +d.insert('b', 'vb3', cost=4) +self.assertEqual(len(d), 1) +self.assertNotIn('a', d) + +def testmaxcostcomplex(self): +d = util.lrucachedict(100, maxcost=100) +d.insert('a', 'va', cost=9) +d.insert('b', 'vb', cost=21) +d.insert('c', 'vc', cost=7) +d.insert('d', 'vc', cost=50) +self.assertEqual(d.totalcost, 87) + +# Inserting new element should free multiple elements so we hit +# low water mark. +d.insert('e', 'vd', cost=25) +self.assertEqual(len(d), 3) +self.assertNotIn('a', d) +self.assertNotIn('b', d) +self.assertIn('c', d) +self.assertIn('d', d) +self.assertIn('e', d) + if __name__ == '__main__': silenttestrunner.main(__name__) diff --git a/mercurial/util.py b/mercurial/util.py --- a/mercurial/util.py +++ b/mercurial/util.py @@ -1240,16 +1240,23 @@ Items in the cache can be inserted with an optional "cost" value. This is simply an integer that is specified by the caller. The cache can be queried for the total cost of all items presently in the cache. + +The cache can also define a maximum cost. If a cache insertion would +cause the total cost of the cache to go beyond the maximum cost limit, +nodes will be evicted to make room for the new code. This can be used +
D4502: util: allow lrucachedict to track cost of entries
This revision was automatically updated to reflect the committed changes. Closed by commit rHGee087f0d7db5: util: allow lrucachedict to track cost of entries (authored by indygreg, committed by ). REPOSITORY rHG Mercurial CHANGES SINCE LAST UPDATE https://phab.mercurial-scm.org/D4502?vs=10832=10941 REVISION DETAIL https://phab.mercurial-scm.org/D4502 AFFECTED FILES contrib/perf.py mercurial/util.py tests/test-lrucachedict.py CHANGE DETAILS diff --git a/tests/test-lrucachedict.py b/tests/test-lrucachedict.py --- a/tests/test-lrucachedict.py +++ b/tests/test-lrucachedict.py @@ -12,27 +12,33 @@ def testsimple(self): d = util.lrucachedict(4) self.assertEqual(d.capacity, 4) -d['a'] = 'va' +d.insert('a', 'va', cost=2) d['b'] = 'vb' d['c'] = 'vc' -d['d'] = 'vd' +d.insert('d', 'vd', cost=42) self.assertEqual(d['a'], 'va') self.assertEqual(d['b'], 'vb') self.assertEqual(d['c'], 'vc') self.assertEqual(d['d'], 'vd') +self.assertEqual(d.totalcost, 44) + # 'a' should be dropped because it was least recently used. d['e'] = 've' self.assertNotIn('a', d) - self.assertIsNone(d.get('a')) +self.assertEqual(d.totalcost, 42) self.assertEqual(d['b'], 'vb') self.assertEqual(d['c'], 'vc') self.assertEqual(d['d'], 'vd') self.assertEqual(d['e'], 've') +# Replacing item with different cost adjusts totalcost. +d.insert('e', 've', cost=4) +self.assertEqual(d.totalcost, 46) + # Touch entries in some order (both get and set). d['e'] d['c'] = 'vc2' @@ -63,12 +69,13 @@ def testcopypartial(self): d = util.lrucachedict(4) -d['a'] = 'va' -d['b'] = 'vb' +d.insert('a', 'va', cost=4) +d.insert('b', 'vb', cost=2) dc = d.copy() self.assertEqual(len(dc), 2) +self.assertEqual(dc.totalcost, 6) for key in ('a', 'b'): self.assertIn(key, dc) self.assertEqual(dc[key], 'v%s' % key) @@ -80,8 +87,10 @@ d['c'] = 'vc' del d['b'] +self.assertEqual(d.totalcost, 4) dc = d.copy() self.assertEqual(len(dc), 2) +self.assertEqual(dc.totalcost, 4) for key in ('a', 'c'): self.assertIn(key, dc) self.assertEqual(dc[key], 'v%s' % key) @@ -93,7 +102,7 @@ def testcopyfull(self): d = util.lrucachedict(4) -d['a'] = 'va' +d.insert('a', 'va', cost=42) d['b'] = 'vb' d['c'] = 'vc' d['d'] = 'vd' @@ -104,13 +113,19 @@ self.assertIn(key, dc) self.assertEqual(dc[key], 'v%s' % key) +self.assertEqual(d.totalcost, 42) +self.assertEqual(dc.totalcost, 42) + # 'a' should be dropped because it was least recently used. dc['e'] = 've' self.assertNotIn('a', dc) for key in ('b', 'c', 'd', 'e'): self.assertIn(key, dc) self.assertEqual(dc[key], 'v%s' % key) +self.assertEqual(d.totalcost, 42) +self.assertEqual(dc.totalcost, 0) + # Contents and order of original dict should remain unchanged. dc['b'] = 'vb_new' @@ -120,25 +135,28 @@ def testcopydecreasecapacity(self): d = util.lrucachedict(5) -d['a'] = 'va' -d['b'] = 'vb' +d.insert('a', 'va', cost=4) +d.insert('b', 'vb', cost=2) d['c'] = 'vc' d['d'] = 'vd' dc = d.copy(2) +self.assertEqual(dc.totalcost, 0) for key in ('a', 'b'): self.assertNotIn(key, dc) for key in ('c', 'd'): self.assertIn(key, dc) self.assertEqual(dc[key], 'v%s' % key) -dc['e'] = 've' +dc.insert('e', 've', cost=7) +self.assertEqual(dc.totalcost, 7) self.assertNotIn('c', dc) for key in ('d', 'e'): self.assertIn(key, dc) self.assertEqual(dc[key], 'v%s' % key) # Original should remain unchanged. +self.assertEqual(d.totalcost, 6) for key in ('a', 'b', 'c', 'd'): self.assertIn(key, d) self.assertEqual(d[key], 'v%s' % key) @@ -174,14 +192,16 @@ def testpopoldest(self): d = util.lrucachedict(4) -d['a'] = 'va' -d['b'] = 'vb' +d.insert('a', 'va', cost=10) +d.insert('b', 'vb', cost=5) self.assertEqual(len(d), 2) self.assertEqual(d.popoldest(), ('a', 'va')) self.assertEqual(len(d), 1) +self.assertEqual(d.totalcost, 5) self.assertEqual(d.popoldest(), ('b', 'vb')) self.assertEqual(len(d), 0) +self.assertEqual(d.totalcost, 0) self.assertIsNone(d.popoldest()) d['a'] = 'va' diff --git a/mercurial/util.py b/mercurial/util.py ---
D4505: util: lower water mark when removing nodes after cost limit reached
This revision was automatically updated to reflect the committed changes. Closed by commit rHGf296c0b366c8: util: lower water mark when removing nodes after cost limit reached (authored by indygreg, committed by ). REPOSITORY rHG Mercurial CHANGES SINCE LAST UPDATE https://phab.mercurial-scm.org/D4505?vs=10824=10944 REVISION DETAIL https://phab.mercurial-scm.org/D4505 AFFECTED FILES mercurial/util.py tests/test-lrucachedict.py CHANGE DETAILS diff --git a/tests/test-lrucachedict.py b/tests/test-lrucachedict.py --- a/tests/test-lrucachedict.py +++ b/tests/test-lrucachedict.py @@ -314,10 +314,10 @@ # Inserting new element should free multiple elements so we hit # low water mark. d.insert('e', 'vd', cost=25) -self.assertEqual(len(d), 3) +self.assertEqual(len(d), 2) self.assertNotIn('a', d) self.assertNotIn('b', d) -self.assertIn('c', d) +self.assertNotIn('c', d) self.assertIn('d', d) self.assertIn('e', d) diff --git a/mercurial/util.py b/mercurial/util.py --- a/mercurial/util.py +++ b/mercurial/util.py @@ -1472,11 +1472,21 @@ # to walk the linked list and doing this in a loop would be # quadratic. So we find the first non-empty node and then # walk nodes until we free up enough capacity. +# +# If we only removed the minimum number of nodes to free enough +# cost at insert time, chances are high that the next insert would +# also require pruning. This would effectively constitute quadratic +# behavior for insert-heavy workloads. To mitigate this, we set a +# target cost that is a percentage of the max cost. This will tend +# to free more nodes when the high water mark is reached, which +# lowers the chances of needing to prune on the subsequent insert. +targetcost = int(self.maxcost * 0.75) + n = self._head.prev while n.key is _notset: n = n.prev -while len(self) > 1 and self.totalcost > self.maxcost: +while len(self) > 1 and self.totalcost > targetcost: del self._cache[n.key] self.totalcost -= n.cost n.markempty() To: indygreg, #hg-reviewers Cc: mercurial-devel ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
D4504: util: optimize cost auditing on insert
This revision was automatically updated to reflect the committed changes. Closed by commit rHGcc23c09bc562: util: optimize cost auditing on insert (authored by indygreg, committed by ). REPOSITORY rHG Mercurial CHANGES SINCE LAST UPDATE https://phab.mercurial-scm.org/D4504?vs=10823=10943 REVISION DETAIL https://phab.mercurial-scm.org/D4504 AFFECTED FILES mercurial/util.py CHANGE DETAILS diff --git a/mercurial/util.py b/mercurial/util.py --- a/mercurial/util.py +++ b/mercurial/util.py @@ -1464,8 +1464,23 @@ # This should run after an insertion. It should only be called if total # cost limits are being enforced. # The most recently inserted node is never evicted. +if len(self) <= 1 or self.totalcost <= self.maxcost: +return + +# This is logically equivalent to calling popoldest() until we +# free up enough cost. We don't do that since popoldest() needs +# to walk the linked list and doing this in a loop would be +# quadratic. So we find the first non-empty node and then +# walk nodes until we free up enough capacity. +n = self._head.prev +while n.key is _notset: +n = n.prev + while len(self) > 1 and self.totalcost > self.maxcost: -self.popoldest() +del self._cache[n.key] +self.totalcost -= n.cost +n.markempty() +n = n.prev def lrucachefunc(func): '''cache most recent results of function calls''' To: indygreg, #hg-reviewers Cc: mercurial-devel ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
D4501: util: add a popoldest() method to lrucachedict
This revision was automatically updated to reflect the committed changes. Closed by commit rHGbd9d3a89f07b: util: add a popoldest() method to lrucachedict (authored by indygreg, committed by ). REPOSITORY rHG Mercurial CHANGES SINCE LAST UPDATE https://phab.mercurial-scm.org/D4501?vs=10820=10940 REVISION DETAIL https://phab.mercurial-scm.org/D4501 AFFECTED FILES mercurial/util.py tests/test-lrucachedict.py CHANGE DETAILS diff --git a/tests/test-lrucachedict.py b/tests/test-lrucachedict.py --- a/tests/test-lrucachedict.py +++ b/tests/test-lrucachedict.py @@ -172,5 +172,30 @@ self.assertIn(key, d) self.assertEqual(d[key], 'v%s' % key) +def testpopoldest(self): +d = util.lrucachedict(4) +d['a'] = 'va' +d['b'] = 'vb' + +self.assertEqual(len(d), 2) +self.assertEqual(d.popoldest(), ('a', 'va')) +self.assertEqual(len(d), 1) +self.assertEqual(d.popoldest(), ('b', 'vb')) +self.assertEqual(len(d), 0) +self.assertIsNone(d.popoldest()) + +d['a'] = 'va' +d['b'] = 'vb' +d['c'] = 'vc' +d['d'] = 'vd' + +self.assertEqual(d.popoldest(), ('a', 'va')) +self.assertEqual(len(d), 3) +for key in ('b', 'c', 'd'): +self.assertEqual(d[key], 'v%s' % key) + +d['a'] = 'va' +self.assertEqual(d.popoldest(), ('b', 'vb')) + if __name__ == '__main__': silenttestrunner.main(__name__) diff --git a/mercurial/util.py b/mercurial/util.py --- a/mercurial/util.py +++ b/mercurial/util.py @@ -1341,6 +1341,28 @@ return result +def popoldest(self): +"""Remove the oldest item from the cache. + +Returns the (key, value) describing the removed cache entry. +""" +if not self._cache: +return + +# Walk the linked list backwards starting at tail node until we hit +# a non-empty node. +n = self._head.prev +while n.key is _notset: +n = n.prev + +key, value = n.key, n.value + +# And remove it from the cache and mark it as empty. +del self._cache[n.key] +n.markempty() + +return key, value + def _movetohead(self, node): """Mark a node as the newest, making it the new head. To: indygreg, #hg-reviewers Cc: mercurial-devel ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
D4500: util: ability to change capacity when copying lrucachedict
This revision was automatically updated to reflect the committed changes. Closed by commit rHG2dcc68c7d25b: util: ability to change capacity when copying lrucachedict (authored by indygreg, committed by ). REPOSITORY rHG Mercurial CHANGES SINCE LAST UPDATE https://phab.mercurial-scm.org/D4500?vs=10819=10939 REVISION DETAIL https://phab.mercurial-scm.org/D4500 AFFECTED FILES mercurial/util.py tests/test-lrucachedict.py CHANGE DETAILS diff --git a/tests/test-lrucachedict.py b/tests/test-lrucachedict.py --- a/tests/test-lrucachedict.py +++ b/tests/test-lrucachedict.py @@ -118,5 +118,59 @@ for key in ('a', 'b', 'c', 'd'): self.assertEqual(d[key], 'v%s' % key) +def testcopydecreasecapacity(self): +d = util.lrucachedict(5) +d['a'] = 'va' +d['b'] = 'vb' +d['c'] = 'vc' +d['d'] = 'vd' + +dc = d.copy(2) +for key in ('a', 'b'): +self.assertNotIn(key, dc) +for key in ('c', 'd'): +self.assertIn(key, dc) +self.assertEqual(dc[key], 'v%s' % key) + +dc['e'] = 've' +self.assertNotIn('c', dc) +for key in ('d', 'e'): +self.assertIn(key, dc) +self.assertEqual(dc[key], 'v%s' % key) + +# Original should remain unchanged. +for key in ('a', 'b', 'c', 'd'): +self.assertIn(key, d) +self.assertEqual(d[key], 'v%s' % key) + +def testcopyincreasecapacity(self): +d = util.lrucachedict(5) +d['a'] = 'va' +d['b'] = 'vb' +d['c'] = 'vc' +d['d'] = 'vd' + +dc = d.copy(6) +for key in ('a', 'b', 'c', 'd'): +self.assertIn(key, dc) +self.assertEqual(dc[key], 'v%s' % key) + +dc['e'] = 've' +dc['f'] = 'vf' +for key in ('a', 'b', 'c', 'd', 'e', 'f'): +self.assertIn(key, dc) +self.assertEqual(dc[key], 'v%s' % key) + +dc['g'] = 'vg' +self.assertNotIn('a', dc) +for key in ('b', 'c', 'd', 'e', 'f', 'g'): +self.assertIn(key, dc) +self.assertEqual(dc[key], 'v%s' % key) + +# Original should remain unchanged. +for key in ('a', 'b', 'c', 'd'): +self.assertIn(key, d) +self.assertEqual(d[key], 'v%s' % key) + if __name__ == '__main__': silenttestrunner.main(__name__) diff --git a/mercurial/util.py b/mercurial/util.py --- a/mercurial/util.py +++ b/mercurial/util.py @@ -1311,8 +1311,19 @@ self._cache.clear() -def copy(self): -result = lrucachedict(self.capacity) +def copy(self, capacity=None): +"""Create a new cache as a copy of the current one. + +By default, the new cache has the same capacity as the existing one. +But, the cache capacity can be changed as part of performing the +copy. + +Items in the copy have an insertion/access order matching this +instance. +""" + +capacity = capacity or self.capacity +result = lrucachedict(capacity) # We copy entries by iterating in oldest-to-newest order so the copy # has the correct ordering. @@ -1322,6 +1333,8 @@ while n.key is _notset and n is not self._head: n = n.prev +# We could potentially skip the first N items when decreasing capacity. +# But let's keep it simple unless it is a performance problem. for i in range(len(self._cache)): result[n.key] = n.value n = n.prev To: indygreg, #hg-reviewers Cc: mjpieters, mercurial-devel ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
D4499: util: make capacity a public attribute on lrucachedict
This revision was automatically updated to reflect the committed changes. Closed by commit rHG5d75a3c16193: util: make capacity a public attribute on lrucachedict (authored by indygreg, committed by ). REPOSITORY rHG Mercurial CHANGES SINCE LAST UPDATE https://phab.mercurial-scm.org/D4499?vs=10818=10938 REVISION DETAIL https://phab.mercurial-scm.org/D4499 AFFECTED FILES mercurial/util.py tests/test-lrucachedict.py CHANGE DETAILS diff --git a/tests/test-lrucachedict.py b/tests/test-lrucachedict.py --- a/tests/test-lrucachedict.py +++ b/tests/test-lrucachedict.py @@ -11,6 +11,7 @@ class testlrucachedict(unittest.TestCase): def testsimple(self): d = util.lrucachedict(4) +self.assertEqual(d.capacity, 4) d['a'] = 'va' d['b'] = 'vb' d['c'] = 'vc' diff --git a/mercurial/util.py b/mercurial/util.py --- a/mercurial/util.py +++ b/mercurial/util.py @@ -1241,7 +1241,7 @@ head.prev = head head.next = head self._size = 1 -self._capacity = max +self.capacity = max def __len__(self): return len(self._cache) @@ -1269,7 +1269,7 @@ self._movetohead(node) return -if self._size < self._capacity: +if self._size < self.capacity: node = self._addcapacity() else: # Grab the last/oldest item. @@ -1312,7 +1312,7 @@ self._cache.clear() def copy(self): -result = lrucachedict(self._capacity) +result = lrucachedict(self.capacity) # We copy entries by iterating in oldest-to-newest order so the copy # has the correct ordering. To: indygreg, #hg-reviewers Cc: mercurial-devel ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
D4475: setup: don't support py 3.5.0, 3.5.1, 3.5.2 because of bug in codecs
durin42 added a comment. In https://phab.mercurial-scm.org/D4475#68453, @indygreg wrote: > I'm a bit wary of version sniffing for the same reason that `User-Agent` sniffing is bad in web design: it assumes that version number strings map to behavior. The best way to test for compatibility is to actually test for the feature/behavior and then act appropriately. For example, `setup.py` would try running `codecs.escape_encode(b'')` and then bail if the buggy behavior is encountered. The version-sniffing here is actually done by pip when considering what wheels etc to download, so it will actually help the user out considerably as I understand it. REPOSITORY rHG Mercurial REVISION DETAIL https://phab.mercurial-scm.org/D4475 To: pulkit, #hg-reviewers, indygreg Cc: indygreg, durin42, mercurial-devel ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
D4498: util: properly copy lrucachedict instances
This revision was automatically updated to reflect the committed changes. Closed by commit rHGb31b01f93b11: util: properly copy lrucachedict instances (authored by indygreg, committed by ). REPOSITORY rHG Mercurial CHANGES SINCE LAST UPDATE https://phab.mercurial-scm.org/D4498?vs=10817=10937 REVISION DETAIL https://phab.mercurial-scm.org/D4498 AFFECTED FILES mercurial/util.py tests/test-lrucachedict.py CHANGE DETAILS diff --git a/tests/test-lrucachedict.py b/tests/test-lrucachedict.py --- a/tests/test-lrucachedict.py +++ b/tests/test-lrucachedict.py @@ -68,12 +68,28 @@ dc = d.copy() self.assertEqual(len(dc), 2) -# TODO this fails -return for key in ('a', 'b'): self.assertIn(key, dc) self.assertEqual(dc[key], 'v%s' % key) +self.assertEqual(len(d), 2) +for key in ('a', 'b'): +self.assertIn(key, d) +self.assertEqual(d[key], 'v%s' % key) + +d['c'] = 'vc' +del d['b'] +dc = d.copy() +self.assertEqual(len(dc), 2) +for key in ('a', 'c'): +self.assertIn(key, dc) +self.assertEqual(dc[key], 'v%s' % key) + +def testcopyempty(self): +d = util.lrucachedict(4) +dc = d.copy() +self.assertEqual(len(dc), 0) + def testcopyfull(self): d = util.lrucachedict(4) d['a'] = 'va' diff --git a/mercurial/util.py b/mercurial/util.py --- a/mercurial/util.py +++ b/mercurial/util.py @@ -1313,11 +1313,19 @@ def copy(self): result = lrucachedict(self._capacity) + +# We copy entries by iterating in oldest-to-newest order so the copy +# has the correct ordering. + +# Find the first non-empty entry. n = self._head.prev -# Iterate in oldest-to-newest order, so the copy has the right ordering +while n.key is _notset and n is not self._head: +n = n.prev + for i in range(len(self._cache)): result[n.key] = n.value n = n.prev + return result def _movetohead(self, node): To: indygreg, #hg-reviewers Cc: martinvonz, mercurial-devel ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
D4497: tests: rewrite test-lrucachedict.py to use unittest
This revision was automatically updated to reflect the committed changes. Closed by commit rHG067f7d2c7d60: tests: rewrite test-lrucachedict.py to use unittest (authored by indygreg, committed by ). REPOSITORY rHG Mercurial CHANGES SINCE LAST UPDATE https://phab.mercurial-scm.org/D4497?vs=10816=10936 REVISION DETAIL https://phab.mercurial-scm.org/D4497 AFFECTED FILES tests/test-lrucachedict.py tests/test-lrucachedict.py.out CHANGE DETAILS diff --git a/tests/test-lrucachedict.py.out b/tests/test-lrucachedict.py.out deleted file mode 100644 --- a/tests/test-lrucachedict.py.out +++ /dev/null @@ -1,62 +0,0 @@ -'a' in d: True -d['a']: va -'b' in d: True -d['b']: vb -'c' in d: True -d['c']: vc -'d' in d: True -d['d']: vd -'a' in d: False -'b' in d: True -d['b']: vb -'c' in d: True -d['c']: vc -'d' in d: True -d['d']: vd -'e' in d: True -d['e']: ve -'b' in d: True -d['b']: vb2 -'c' in d: True -d['c']: vc2 -'d' in d: True -d['d']: vd -'e' in d: False -'f' in d: True -d['f']: vf -'b' in d: False -'c' in d: False -'d' in d: False -'e' in d: False -'f' in d: False -'a' in d: True -d['a']: 1 -'b' in d: True -d['b']: 2 - -All of these should be present: -'a' in dc: True -dc['a']: va3 -'b' in dc: True -dc['b']: vb3 -'c' in dc: True -dc['c']: vc3 -'d' in dc: True -dc['d']: vd3 - -All of these except 'a' should be present: -'a' in dc: False -'b' in dc: True -dc['b']: vb3 -'c' in dc: True -dc['c']: vc3 -'d' in dc: True -dc['d']: vd3 -'e' in dc: True -dc['e']: ve3 - -These should be in reverse alphabetical order and read 'v?3': -d['d']: vd3 -d['c']: vc3 -d['b']: vb3 -d['a']: va3 diff --git a/tests/test-lrucachedict.py b/tests/test-lrucachedict.py --- a/tests/test-lrucachedict.py +++ b/tests/test-lrucachedict.py @@ -1,77 +1,105 @@ from __future__ import absolute_import, print_function +import unittest + +import silenttestrunner + from mercurial import ( util, ) -def printifpresent(d, xs, name='d'): -for x in xs: -present = x in d -print("'%s' in %s: %s" % (x, name, present)) -if present: -print("%s['%s']: %s" % (name, x, d[x])) +class testlrucachedict(unittest.TestCase): +def testsimple(self): +d = util.lrucachedict(4) +d['a'] = 'va' +d['b'] = 'vb' +d['c'] = 'vc' +d['d'] = 'vd' -def test_lrucachedict(): -d = util.lrucachedict(4) -d['a'] = 'va' -d['b'] = 'vb' -d['c'] = 'vc' -d['d'] = 'vd' +self.assertEqual(d['a'], 'va') +self.assertEqual(d['b'], 'vb') +self.assertEqual(d['c'], 'vc') +self.assertEqual(d['d'], 'vd') -# all of these should be present -printifpresent(d, ['a', 'b', 'c', 'd']) +# 'a' should be dropped because it was least recently used. +d['e'] = 've' +self.assertNotIn('a', d) + +self.assertIsNone(d.get('a')) -# 'a' should be dropped because it was least recently used -d['e'] = 've' -printifpresent(d, ['a', 'b', 'c', 'd', 'e']) +self.assertEqual(d['b'], 'vb') +self.assertEqual(d['c'], 'vc') +self.assertEqual(d['d'], 'vd') +self.assertEqual(d['e'], 've') -assert d.get('a') is None -assert d.get('e') == 've' +# Touch entries in some order (both get and set). +d['e'] +d['c'] = 'vc2' +d['d'] +d['b'] = 'vb2' -# touch entries in some order (get or set). -d['e'] -d['c'] = 'vc2' -d['d'] -d['b'] = 'vb2' +# 'e' should be dropped now +d['f'] = 'vf' +self.assertNotIn('e', d) +self.assertEqual(d['b'], 'vb2') +self.assertEqual(d['c'], 'vc2') +self.assertEqual(d['d'], 'vd') +self.assertEqual(d['f'], 'vf') -# 'e' should be dropped now -d['f'] = 'vf' -printifpresent(d, ['b', 'c', 'd', 'e', 'f']) +d.clear() +for key in ('a', 'b', 'c', 'd', 'e', 'f'): +self.assertNotIn(key, d) -d.clear() -printifpresent(d, ['b', 'c', 'd', 'e', 'f']) +def testunfull(self): +d = util.lrucachedict(4) +d['a'] = 1 +d['b'] = 2 +d['a'] +d['b'] + +for key in ('a', 'b'): +self.assertIn(key, d) -# Now test dicts that aren't full. -d = util.lrucachedict(4) -d['a'] = 1 -d['b'] = 2 -d['a'] -d['b'] -printifpresent(d, ['a', 'b']) +def testcopypartial(self): +d = util.lrucachedict(4) +d['a'] = 'va' +d['b'] = 'vb' + +dc = d.copy() + +self.assertEqual(len(dc), 2) +# TODO this fails +return +for key in ('a', 'b'): +self.assertIn(key, dc) +self.assertEqual(dc[key], 'v%s' % key) -# test copy method -d = util.lrucachedict(4) -d['a'] = 'va3' -d['b'] = 'vb3' -d['c'] = 'vc3' -d['d'] = 'vd3' +def testcopyfull(self): +d = util.lrucachedict(4) +d['a'] = 'va' +d['b'] = 'vb' +d['c'] = 'vc' +d['d'] =
D4472: wireprotov2: implement commands as a generator of objects
This revision was automatically updated to reflect the committed changes. Closed by commit rHG07b58266bce3: wireprotov2: implement commands as a generator of objects (authored by indygreg, committed by ). REPOSITORY rHG Mercurial CHANGES SINCE LAST UPDATE https://phab.mercurial-scm.org/D4472?vs=10791=10933 REVISION DETAIL https://phab.mercurial-scm.org/D4472 AFFECTED FILES mercurial/error.py mercurial/help/internals/wireprotocolrpc.txt mercurial/wireprotoframing.py mercurial/wireprototypes.py mercurial/wireprotov2peer.py mercurial/wireprotov2server.py tests/test-http-api-httpv2.t tests/test-http-protocol.t tests/test-wireproto-command-branchmap.t tests/test-wireproto-command-capabilities.t tests/test-wireproto-command-heads.t tests/test-wireproto-command-known.t tests/test-wireproto-command-listkeys.t tests/test-wireproto-command-lookup.t tests/test-wireproto-command-pushkey.t tests/wireprotohelpers.sh CHANGE DETAILS diff --git a/tests/wireprotohelpers.sh b/tests/wireprotohelpers.sh --- a/tests/wireprotohelpers.sh +++ b/tests/wireprotohelpers.sh @@ -26,15 +26,15 @@ @wireprotov2server.wireprotocommand(b'customreadonly', permission=b'pull') def customreadonlyv2(repo, proto): -return wireprototypes.cborresponse(b'customreadonly bytes response') +yield b'customreadonly bytes response' @wireprotov1server.wireprotocommand(b'customreadwrite', permission=b'push') def customreadwrite(repo, proto): return wireprototypes.bytesresponse(b'customreadwrite bytes response') @wireprotov2server.wireprotocommand(b'customreadwrite', permission=b'push') def customreadwritev2(repo, proto): -return wireprototypes.cborresponse(b'customreadwrite bytes response') +yield b'customreadwrite bytes response' EOF cat >> $HGRCPATH << EOF diff --git a/tests/test-wireproto-command-pushkey.t b/tests/test-wireproto-command-pushkey.t --- a/tests/test-wireproto-command-pushkey.t +++ b/tests/test-wireproto-command-pushkey.t @@ -46,13 +46,22 @@ s> Content-Type: application/mercurial-exp-framing-0005\r\n s> Transfer-Encoding: chunked\r\n s> \r\n - s> 14\r\n - s> \x0c\x00\x00\x01\x00\x02\x012 - s> \xa1FstatusBok\xf5 + s> 13\r\n + s> \x0b\x00\x00\x01\x00\x02\x011 + s> \xa1FstatusBok s> \r\n - received frame(size=12; request=1; stream=2; streamflags=stream-begin; type=command-response; flags=eos) + received frame(size=11; request=1; stream=2; streamflags=stream-begin; type=command-response; flags=continuation) + s> 9\r\n + s> \x01\x00\x00\x01\x00\x02\x001 + s> \xf5 + s> \r\n + received frame(size=1; request=1; stream=2; streamflags=; type=command-response; flags=continuation) + s> 8\r\n + s> \x00\x00\x00\x01\x00\x02\x002 + s> \r\n s> 0\r\n s> \r\n + received frame(size=0; request=1; stream=2; streamflags=; type=command-response; flags=eos) response: True $ sendhttpv2peer << EOF @@ -77,13 +86,22 @@ s> Content-Type: application/mercurial-exp-framing-0005\r\n s> Transfer-Encoding: chunked\r\n s> \r\n - s> 40\r\n - s> 8\x00\x00\x01\x00\x02\x012 - s> \xa1FstatusBok\xa1A@X(426bada5c67598ca65036d57d9e4b64b0c1ce7a0 + s> 13\r\n + s> \x0b\x00\x00\x01\x00\x02\x011 + s> \xa1FstatusBok s> \r\n - received frame(size=56; request=1; stream=2; streamflags=stream-begin; type=command-response; flags=eos) + received frame(size=11; request=1; stream=2; streamflags=stream-begin; type=command-response; flags=continuation) + s> 35\r\n + s> -\x00\x00\x01\x00\x02\x001 + s> \xa1A@X(426bada5c67598ca65036d57d9e4b64b0c1ce7a0 + s> \r\n + received frame(size=45; request=1; stream=2; streamflags=; type=command-response; flags=continuation) + s> 8\r\n + s> \x00\x00\x00\x01\x00\x02\x002 + s> \r\n s> 0\r\n s> \r\n + received frame(size=0; request=1; stream=2; streamflags=; type=command-response; flags=eos) response: { b'@': b'426bada5c67598ca65036d57d9e4b64b0c1ce7a0' } diff --git a/tests/test-wireproto-command-lookup.t b/tests/test-wireproto-command-lookup.t --- a/tests/test-wireproto-command-lookup.t +++ b/tests/test-wireproto-command-lookup.t @@ -43,13 +43,22 @@ s> Content-Type: application/mercurial-exp-framing-0005\r\n s> Transfer-Encoding: chunked\r\n s> \r\n - s> 28\r\n - s> \x00\x00\x01\x00\x02\x012 - s> \xa1FstatusBokTBk\xad\xa5\xc6u\x98\xcae\x03mW\xd9\xe4\xb6K\x0c\x1c\xe7\xa0 + s> 13\r\n + s> \x0b\x00\x00\x01\x00\x02\x011 + s> \xa1FstatusBok s> \r\n - received frame(size=32; request=1; stream=2; streamflags=stream-begin; type=command-response; flags=eos) + received frame(size=11; request=1; stream=2; streamflags=stream-begin; type=command-response; flags=continuation) + s> 1d\r\n + s> \x15\x00\x00\x01\x00\x02\x001 + s>
D4474: wireprotov2peer: stream decoded responses
This revision was automatically updated to reflect the committed changes. Closed by commit rHGd06834e0f48e: wireprotov2peer: stream decoded responses (authored by indygreg, committed by ). REPOSITORY rHG Mercurial CHANGES SINCE LAST UPDATE https://phab.mercurial-scm.org/D4474?vs=10792=10935 REVISION DETAIL https://phab.mercurial-scm.org/D4474 AFFECTED FILES mercurial/debugcommands.py mercurial/wireprotov2peer.py tests/test-http-api-httpv2.t tests/test-wireproto-command-capabilities.t CHANGE DETAILS diff --git a/tests/test-wireproto-command-capabilities.t b/tests/test-wireproto-command-capabilities.t --- a/tests/test-wireproto-command-capabilities.t +++ b/tests/test-wireproto-command-capabilities.t @@ -349,10 +349,7 @@ s> 0\r\n s> \r\n received frame(size=0; request=1; stream=2; streamflags=; type=command-response; flags=eos) - response: [ -{ - b'status': b'ok' -}, + response: gen[ { b'commands': { b'branchmap': { diff --git a/tests/test-http-api-httpv2.t b/tests/test-http-api-httpv2.t --- a/tests/test-http-api-httpv2.t +++ b/tests/test-http-api-httpv2.t @@ -225,10 +225,7 @@ s> 0\r\n s> \r\n received frame(size=0; request=1; stream=2; streamflags=; type=command-response; flags=eos) - response: [ -{ - b'status': b'ok' -}, + response: gen[ b'customreadonly bytes response' ] diff --git a/mercurial/wireprotov2peer.py b/mercurial/wireprotov2peer.py --- a/mercurial/wireprotov2peer.py +++ b/mercurial/wireprotov2peer.py @@ -7,11 +7,12 @@ from __future__ import absolute_import +import threading + from .i18n import _ from . import ( encoding, error, -util, wireprotoframing, ) from .utils import ( @@ -34,20 +35,101 @@ return b''.join(chunks) class commandresponse(object): -"""Represents the response to a command request.""" +"""Represents the response to a command request. + +Instances track the state of the command and hold its results. + +An external entity is required to update the state of the object when +events occur. +""" def __init__(self, requestid, command): self.requestid = requestid self.command = command -self.b = util.bytesio() +# Whether all remote input related to this command has been +# received. +self._inputcomplete = False + +# We have a lock that is acquired when important object state is +# mutated. This is to prevent race conditions between 1 thread +# sending us new data and another consuming it. +self._lock = threading.RLock() + +# An event is set when state of the object changes. This event +# is waited on by the generator emitting objects. +self._serviceable = threading.Event() + +self._pendingevents = [] +self._decoder = cborutil.bufferingdecoder() +self._seeninitial = False + +def _oninputcomplete(self): +with self._lock: +self._inputcomplete = True +self._serviceable.set() + +def _onresponsedata(self, data): +available, readcount, wanted = self._decoder.decode(data) + +if not available: +return + +with self._lock: +for o in self._decoder.getavailable(): +if not self._seeninitial: +self._handleinitial(o) +continue + +self._pendingevents.append(o) + +self._serviceable.set() -def cborobjects(self): -"""Obtain decoded CBOR objects from this response.""" -self.b.seek(0) +def _handleinitial(self, o): +self._seeninitial = True +if o[b'status'] == 'ok': +return + +atoms = [{'msg': o[b'error'][b'message']}] +if b'args' in o[b'error']: +atoms[0]['args'] = o[b'error'][b'args'] + +raise error.RepoError(formatrichmessage(atoms)) + +def objects(self): +"""Obtained decoded objects from this response. + +This is a generator of data structures that were decoded from the +command response. + +Obtaining the next member of the generator may block due to waiting +on external data to become available. -for v in cborutil.decodeall(self.b.getvalue()): -yield v +If the server encountered an error in the middle of serving the data +or if another error occurred, an exception may be raised when +advancing the generator. +""" +while True: +# TODO this can infinite loop if self._inputcomplete is never +# set. We likely want to tie the lifetime of this object/state +# to that of the background thread receiving frames and updating +# our state. +self._serviceable.wait(1.0) + +with self._lock: +self._serviceable.clear() + +# Make copies because
D4473: wireprotoframing: buffer emitted data to reduce frame count
This revision was automatically updated to reflect the committed changes. Closed by commit rHG84bf6ded9317: wireprotoframing: buffer emitted data to reduce frame count (authored by indygreg, committed by ). REPOSITORY rHG Mercurial CHANGES SINCE LAST UPDATE https://phab.mercurial-scm.org/D4473?vs=10770=10934 REVISION DETAIL https://phab.mercurial-scm.org/D4473 AFFECTED FILES mercurial/wireprotoframing.py CHANGE DETAILS diff --git a/mercurial/wireprotoframing.py b/mercurial/wireprotoframing.py --- a/mercurial/wireprotoframing.py +++ b/mercurial/wireprotoframing.py @@ -511,6 +511,98 @@ flags=0, payload=payload) +class bufferingcommandresponseemitter(object): +"""Helper object to emit command response frames intelligently. + +Raw command response data is likely emitted in chunks much smaller +than what can fit in a single frame. This class exists to buffer +chunks until enough data is available to fit in a single frame. + +TODO we'll need something like this when compression is supported. +So it might make sense to implement this functionality at the stream +level. +""" +def __init__(self, stream, requestid, maxframesize=DEFAULT_MAX_FRAME_SIZE): +self._stream = stream +self._requestid = requestid +self._maxsize = maxframesize +self._chunks = [] +self._chunkssize = 0 + +def send(self, data): +"""Send new data for emission. + +Is a generator of new frames that were derived from the new input. + +If the special input ``None`` is received, flushes all buffered +data to frames. +""" + +if data is None: +for frame in self._flush(): +yield frame +return + +# There is a ton of potential to do more complicated things here. +# Our immediate goal is to coalesce small chunks into big frames, +# not achieve the fewest number of frames possible. So we go with +# a simple implementation: +# +# * If a chunk is too large for a frame, we flush and emit frames +# for the new chunk. +# * If a chunk can be buffered without total buffered size limits +# being exceeded, we do that. +# * If a chunk causes us to go over our buffering limit, we flush +# and then buffer the new chunk. + +if len(data) > self._maxsize: +for frame in self._flush(): +yield frame + +# Now emit frames for the big chunk. +offset = 0 +while True: +chunk = data[offset:offset + self._maxsize] +offset += len(chunk) + +yield self._stream.makeframe( +self._requestid, +typeid=FRAME_TYPE_COMMAND_RESPONSE, +flags=FLAG_COMMAND_RESPONSE_CONTINUATION, +payload=chunk) + +if offset == len(data): +return + +# If we don't have enough to constitute a full frame, buffer and +# return. +if len(data) + self._chunkssize < self._maxsize: +self._chunks.append(data) +self._chunkssize += len(data) +return + +# Else flush what we have and buffer the new chunk. We could do +# something more intelligent here, like break the chunk. Let's +# keep things simple for now. +for frame in self._flush(): +yield frame + +self._chunks.append(data) +self._chunkssize = len(data) + +def _flush(self): +payload = b''.join(self._chunks) +assert len(payload) <= self._maxsize + +self._chunks[:] = [] +self._chunkssize = 0 + +yield self._stream.makeframe( +self._requestid, +typeid=FRAME_TYPE_COMMAND_RESPONSE, +flags=FLAG_COMMAND_RESPONSE_CONTINUATION, +payload=payload) + class stream(object): """Represents a logical unidirectional series of frames.""" @@ -716,10 +808,14 @@ def sendframes(): emitted = False +emitter = bufferingcommandresponseemitter(stream, requestid) while True: try: o = next(objs) except StopIteration: +for frame in emitter.send(None): +yield frame + if emitted: yield createcommandresponseeosframe(stream, requestid) break @@ -743,11 +839,10 @@ yield createcommandresponseokframe(stream, requestid) emitted = True -# TODO buffer chunks so emitted frame payloads can be -# larger. -for frame in createbytesresponseframesfromgen( -stream, requestid, cborutil.streamencode(o)):
D4443: internals: extract frame-based protocol docs to own document
This revision was automatically updated to reflect the committed changes. Closed by commit rHGb0e0db1565d1: internals: extract frame-based protocol docs to own document (authored by indygreg, committed by ). REPOSITORY rHG Mercurial CHANGES SINCE LAST UPDATE https://phab.mercurial-scm.org/D4443?vs=10700=10932 REVISION DETAIL https://phab.mercurial-scm.org/D4443 AFFECTED FILES contrib/wix/help.wxs mercurial/help/internals/wireprotocol.txt mercurial/help/internals/wireprotocolrpc.txt CHANGE DETAILS diff --git a/mercurial/help/internals/wireprotocol.txt b/mercurial/help/internals/wireprotocolrpc.txt copy from mercurial/help/internals/wireprotocol.txt copy to mercurial/help/internals/wireprotocolrpc.txt --- a/mercurial/help/internals/wireprotocol.txt +++ b/mercurial/help/internals/wireprotocolrpc.txt @@ -1,530 +1,32 @@ -The Mercurial wire protocol is a request-response based protocol -with multiple wire representations. - -Each request is modeled as a command name, a dictionary of arguments, and -optional raw input. Command arguments and their types are intrinsic -properties of commands. So is the response type of the command. This means -clients can't always send arbitrary arguments to servers and servers can't -return multiple response types. - -The protocol is synchronous and does not support multiplexing (concurrent -commands). - -Handshake -= - -It is required or common for clients to perform a *handshake* when connecting -to a server. The handshake serves the following purposes: - -* Negotiating protocol/transport level options -* Allows the client to learn about server capabilities to influence - future requests -* Ensures the underlying transport channel is in a *clean* state - -An important goal of the handshake is to allow clients to use more modern -wire protocol features. By default, clients must assume they are talking -to an old version of Mercurial server (possibly even the very first -implementation). So, clients should not attempt to call or utilize modern -wire protocol features until they have confirmation that the server -supports them. The handshake implementation is designed to allow both -ends to utilize the latest set of features and capabilities with as -few round trips as possible. - -The handshake mechanism varies by transport and protocol and is documented -in the sections below. - -HTTP Protocol -= - -Handshake -- - -The client sends a ``capabilities`` command request (``?cmd=capabilities``) -as soon as HTTP requests may be issued. - -By default, the server responds with a version 1 capabilities string, which -the client parses to learn about the server's abilities. The ``Content-Type`` -for this response is ``application/mercurial-0.1`` or -``application/mercurial-0.2`` depending on whether the client advertised -support for version ``0.2`` in its request. (Clients aren't supposed to -advertise support for ``0.2`` until the capabilities response indicates -the server's support for that media type. However, a client could -conceivably cache this metadata and issue the capabilities request in such -a way to elicit an ``application/mercurial-0.2`` response.) - -Clients wishing to switch to a newer API service may send an -``X-HgUpgrade-`` header containing a space-delimited list of API service -names the client is capable of speaking. The request MUST also include an -``X-HgProto-`` header advertising a known serialization format for the -response. ``cbor`` is currently the only defined serialization format. - -If the request contains these headers, the response ``Content-Type`` MAY -be for a different media type. e.g. ``application/mercurial-cbor`` if the -client advertises support for CBOR. - -The response MUST be deserializable to a map with the following keys: - -apibase - URL path to API services, relative to the repository root. e.g. ``api/``. - -apis - A map of API service names to API descriptors. An API descriptor contains - more details about that API. In the case of the HTTP Version 2 Transport, - it will be the normal response to a ``capabilities`` command. - - Only the services advertised by the client that are also available on - the server are advertised. - -v1capabilities - The capabilities string that would be returned by a version 1 response. - -The client can then inspect the server-advertised APIs and decide which -API to use, including continuing to use the HTTP Version 1 Transport. - -HTTP Version 1 Transport - - -Commands are issued as HTTP/1.0 or HTTP/1.1 requests. Commands are -sent to the base URL of the repository with the command name sent in -the ``cmd`` query string parameter. e.g. -``https://example.com/repo?cmd=capabilities``. The HTTP method is ``GET`` -or ``POST`` depending on the command and whether there is a request -body. - -Command arguments can be sent multiple ways. - -The simplest is part of the URL query string using ``x-www-form-urlencoded`` -encoding
D4480: exchangev2: start to implement pull with wire protocol v2
durin42 added inline comments. INLINE COMMENTS > exchange.py:1490 > +if remote.capable('exchangev2'): > +from . import exchangev2 > +exchangev2.pull(pullop) What's the deal with this function-level import? It doesn't appear to be avoiding a cycle... REPOSITORY rHG Mercurial REVISION DETAIL https://phab.mercurial-scm.org/D4480 To: indygreg, #hg-reviewers Cc: durin42, mercurial-devel ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
D4436: httppeer: expose capabilities for each command
durin42 added a comment. Hm, I worry this isn't explicit enough. Do you have a specific reason for why this is a thing we should do? REPOSITORY rHG Mercurial REVISION DETAIL https://phab.mercurial-scm.org/D4436 To: indygreg, #hg-reviewers Cc: durin42, mercurial-devel ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
D2679: [PoC] obsolete: config option to enable local only obsolescence mode
durin42 added a comment. In https://phab.mercurial-scm.org/D2679#68489, @lothiraldan wrote: > To take a step back, I'm wondering what's the end goal? I remember there was a discussion about having rebase enabled by default, is it related? Getting rebase (and maybe histedit?) enabled by default is my recollection of the rough goal. > The behavior target by this series ("unobsolete" re-pulled changeset) conflicts with the final behavior we want for Changeset Evolution. Intermediate steps are a good way to make progress. I feel like it is important to write down a clear plan when it comes to adding behavior that does not match our final goals. How are we planning to transition from the local-only step to full (ie, distributed) Evolution? I'm slowly becoming convinced that the long-unquestioned axiom that "all markers are distributed globally" isn't correct, and this is part of why: it's potentially of great value to be able to restore a change by re-pulling it, even though the obsmarkers would normally cause it to be deleted. It's _super confusing_ when I `hg import` a patch and it seems to work but also immediately disappears, so I've got more sympathy for this PoC series than I do the theoretical purity of markers having any kind of globalness. Does that make sense? REPOSITORY rHG Mercurial REVISION DETAIL https://phab.mercurial-scm.org/D2679 To: indygreg, #hg-reviewers Cc: durin42, lothiraldan, pulkit, mercurial-devel ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
[Bug 5985] New: abort: this diff is too large to be displayed
https://bz.mercurial-scm.org/show_bug.cgi?id=5985 Bug ID: 5985 Summary: abort: this diff is too large to be displayed Product: Mercurial Version: stable branch Hardware: PC OS: Linux Status: UNCONFIRMED Severity: feature Priority: wish Component: record Assignee: bugzi...@mercurial-scm.org Reporter: g...@sjeng.org CC: mercurial-devel@mercurial-scm.org morbo@mozwell:~/hg/firefox$ hg commit --interactive starting interactive selection abort: this diff is too large to be displayed I have a workstation with 32G memory. Mercurial doesn't come close to exhausting that when running the above command. So what exactly is "too large" supposed to mean? morbo@mozwell:~/hg/firefox$ hg --version Mercurial Distributed SCM (version 4.6.2) (see https://mercurial-scm.org for more information) -- You are receiving this mail because: You are on the CC list for the bug. ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
Re: [PATCH 1 of 2] narrowspec: remove parseserverpatterns() which isn't used anymore
On Wed, Sep 12, 2018 at 4:32 PM Yuya Nishihara wrote: > # HG changeset patch > # User Yuya Nishihara > # Date 1536758143 -32400 > # Wed Sep 12 22:15:43 2018 +0900 > # Node ID c8ea5c7ec99d1ca4f349025c236c768081dd5084 > # Parent cb675e95a2c2d6b248a9deb459aa7e75edb649a7 > narrowspec: remove parseserverpatterns() which isn't used anymore > > Follows up 10a8472f6662, "narrow: drop support for remote expansion." > Queued this series, many thanks! ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
[PATCH 2 of 2] narrow: remove hack to write narrowspec to shared .hg directory
# HG changeset patch # User Yuya Nishihara # Date 1536758369 -32400 # Wed Sep 12 22:19:29 2018 +0900 # Node ID 7934af554124813b0a2bda1a9437a519ab3c04f1 # Parent c8ea5c7ec99d1ca4f349025c236c768081dd5084 narrow: remove hack to write narrowspec to shared .hg directory AFAIK, we no longer need it since the narrowspec file was move to the store directory in 576eef1ab43d, "narrow: move .hg/narrowspec to .hg/store/narrowspec." diff --git a/mercurial/localrepo.py b/mercurial/localrepo.py --- a/mercurial/localrepo.py +++ b/mercurial/localrepo.py @@ -841,11 +841,7 @@ class localrepository(object): return self._narrowmatch def setnarrowpats(self, newincludes, newexcludes): -target = self -if self.shared(): -from . import hg -target = hg.sharedreposource(self) -narrowspec.save(target, newincludes, newexcludes) +narrowspec.save(self, newincludes, newexcludes) self.invalidate(clearfilecache=True) def __getitem__(self, changeid): ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
[PATCH 1 of 2] narrowspec: remove parseserverpatterns() which isn't used anymore
# HG changeset patch # User Yuya Nishihara # Date 1536758143 -32400 # Wed Sep 12 22:15:43 2018 +0900 # Node ID c8ea5c7ec99d1ca4f349025c236c768081dd5084 # Parent cb675e95a2c2d6b248a9deb459aa7e75edb649a7 narrowspec: remove parseserverpatterns() which isn't used anymore Follows up 10a8472f6662, "narrow: drop support for remote expansion." diff --git a/mercurial/narrowspec.py b/mercurial/narrowspec.py --- a/mercurial/narrowspec.py +++ b/mercurial/narrowspec.py @@ -29,27 +29,6 @@ VALID_PREFIXES = ( b'rootfilesin:', ) -def parseserverpatterns(text): -"""Parses the narrowspec format that's returned by the server.""" -includepats = set() -excludepats = set() - -# We get one entry per line, in the format " ". -# It's OK for value to contain other spaces. -for kp in (l.split(' ', 1) for l in text.splitlines()): -if len(kp) != 2: -raise error.Abort(_('Invalid narrowspec pattern line: "%s"') % kp) -key = kp[0] -pat = kp[1] -if key == 'include': -includepats.add(pat) -elif key == 'exclude': -excludepats.add(pat) -else: -raise error.Abort(_('Invalid key "%s" in server response') % key) - -return includepats, excludepats - def normalizesplitpattern(kind, pat): """Returns the normalized version of a pattern and kind. ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
mercurial@39532: 5 new changesets
5 new changesets in mercurial: https://www.mercurial-scm.org/repo/hg/rev/2862e9b868c5 changeset: 39528:2862e9b868c5 user:Martin von Zweigbergk date:Tue Sep 11 11:03:15 2018 -0700 summary: narrow: check "narrow" wire protocol capability, not bundle2 capability https://www.mercurial-scm.org/repo/hg/rev/e82da0fcc7c5 changeset: 39529:e82da0fcc7c5 user:Martin von Zweigbergk date:Tue Sep 11 10:50:46 2018 -0700 summary: narrow: move wire proto capabilities to narrowwirepeer https://www.mercurial-scm.org/repo/hg/rev/576b92928cc7 changeset: 39530:576b92928cc7 user:Martin von Zweigbergk date:Tue Sep 11 10:54:20 2018 -0700 summary: narrow: mark wire proto capability names experimental and versioned https://www.mercurial-scm.org/repo/hg/rev/0d572769046a changeset: 39531:0d572769046a user:Gregory Szorc date:Tue Sep 11 15:25:35 2018 -0700 summary: narrowspec: limit patterns to path: and rootfilesin: (BC) https://www.mercurial-scm.org/repo/hg/rev/55eea29833d2 changeset: 39532:55eea29833d2 bookmark:@ tag: tip user:Gregory Szorc date:Tue Sep 11 10:36:07 2018 -0700 summary: narrow: validate patterns returned by expandnarrow -- Repository URL: https://www.mercurial-scm.org/repo/hg ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
D4538: commands: pass include and exclude options to hg.clone()
This revision was automatically updated to reflect the committed changes. Closed by commit rHG4c807ec07888: commands: pass include and exclude options to hg.clone() (authored by indygreg, committed by ). REPOSITORY rHG Mercurial CHANGES SINCE LAST UPDATE https://phab.mercurial-scm.org/D4538?vs=10915=10928 REVISION DETAIL https://phab.mercurial-scm.org/D4538 AFFECTED FILES mercurial/commands.py tests/test-narrow-clone.t tests/test-narrow.t CHANGE DETAILS diff --git a/tests/test-narrow.t b/tests/test-narrow.t --- a/tests/test-narrow.t +++ b/tests/test-narrow.t @@ -38,15 +38,12 @@ Error if '.' or '..' are in the directory to track. $ hg clone --narrow ssh://user@dummy/master foo --include ./asdf - requesting all changes abort: "." and ".." are not allowed in narrowspec paths [255] $ hg clone --narrow ssh://user@dummy/master foo --include asdf/.. - requesting all changes abort: "." and ".." are not allowed in narrowspec paths [255] $ hg clone --narrow ssh://user@dummy/master foo --include a/./c - requesting all changes abort: "." and ".." are not allowed in narrowspec paths [255] diff --git a/tests/test-narrow-clone.t b/tests/test-narrow-clone.t --- a/tests/test-narrow-clone.t +++ b/tests/test-narrow-clone.t @@ -19,13 +19,11 @@ Only path: and rootfilesin: pattern prefixes are allowed $ hg clone --narrow ssh://user@dummy/master badnarrow --noupdate --include 'glob:**' - requesting all changes abort: invalid prefix on narrow pattern: glob:** (narrow patterns must begin with one of the following: path:, rootfilesin:) [255] $ hg clone --narrow ssh://user@dummy/master badnarrow --noupdate --exclude 'set:ignored' - requesting all changes abort: invalid prefix on narrow pattern: set:ignored (narrow patterns must begin with one of the following: path:, rootfilesin:) [255] @@ -67,7 +65,6 @@ $ hg clone --narrow ssh://user@dummy/master narrow_fail --noupdate --include 'dir/src/f10 > ' - requesting all changes abort: newlines are not allowed in narrowspec paths [255] diff --git a/mercurial/commands.py b/mercurial/commands.py --- a/mercurial/commands.py +++ b/mercurial/commands.py @@ -43,6 +43,7 @@ hg, logcmdutil, merge as mergemod, +narrowspec, obsolete, obsutil, patch, @@ -1466,13 +1467,29 @@ if opts.get('noupdate') and opts.get('updaterev'): raise error.Abort(_("cannot specify both --noupdate and --updaterev")) +# --include/--exclude can come from narrow or sparse. +includepats, excludepats = None, None + +# hg.clone() differentiates between None and an empty set. So make sure +# patterns are sets if narrow is requested without patterns. +if opts.get('narrow'): +includepats = set() +excludepats = set() + +if opts.get('include'): +includepats = narrowspec.parsepatterns(opts.get('include')) +if opts.get('exclude'): +excludepats = narrowspec.parsepatterns(opts.get('exclude')) + r = hg.clone(ui, opts, source, dest, pull=opts.get('pull'), stream=opts.get('stream') or opts.get('uncompressed'), revs=opts.get('rev'), update=opts.get('updaterev') or not opts.get('noupdate'), branch=opts.get('branch'), - shareopts=opts.get('shareopts')) + shareopts=opts.get('shareopts'), + storeincludepats=includepats, + storeexcludepats=excludepats) return r is None To: indygreg, durin42, #hg-reviewers Cc: mercurial-devel ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
D4541: hg: write narrow patterns after repo creation
This revision was automatically updated to reflect the committed changes. Closed by commit rHGcb675e95a2c2: hg: write narrow patterns after repo creation (authored by indygreg, committed by ). REPOSITORY rHG Mercurial CHANGES SINCE LAST UPDATE https://phab.mercurial-scm.org/D4541?vs=10918=10931 REVISION DETAIL https://phab.mercurial-scm.org/D4541 AFFECTED FILES hgext/narrow/narrowcommands.py mercurial/hg.py CHANGE DETAILS diff --git a/mercurial/hg.py b/mercurial/hg.py --- a/mercurial/hg.py +++ b/mercurial/hg.py @@ -737,6 +737,10 @@ revs = None local = destpeer.local() if local: +if narrow: +with local.lock(): +local.setnarrowpats(storeincludepats, storeexcludepats) + u = util.url(abspath) defaulturl = bytes(u) local.ui.setconfig('paths', 'default', defaulturl, 'clone') diff --git a/hgext/narrow/narrowcommands.py b/hgext/narrow/narrowcommands.py --- a/hgext/narrow/narrowcommands.py +++ b/hgext/narrow/narrowcommands.py @@ -92,19 +92,6 @@ if opts['narrow']: def pullbundle2extraprepare_widen(orig, pullop, kwargs): -# Create narrow spec patterns from clone flags -includepats = narrowspec.parsepatterns(opts['include']) -excludepats = narrowspec.parsepatterns(opts['exclude']) - -if not includepats and excludepats: -# If nothing was included, we assume the user meant to include -# everything, except what they asked to exclude. -includepats = {'path:.'} - -pullop.repo.setnarrowpats(includepats, excludepats) - -# This will populate 'includepats' etc with the values from the -# narrowspec we just saved. orig(pullop, kwargs) if opts.get('depth'): To: indygreg, durin42, #hg-reviewers Cc: yuja, mercurial-devel ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
D4539: exchange: support defining narrow file patterns for pull
This revision was automatically updated to reflect the committed changes. Closed by commit rHG130e5df346d5: exchange: support defining narrow file patterns for pull (authored by indygreg, committed by ). REPOSITORY rHG Mercurial CHANGES SINCE LAST UPDATE https://phab.mercurial-scm.org/D4539?vs=10916=10929 REVISION DETAIL https://phab.mercurial-scm.org/D4539 AFFECTED FILES mercurial/exchange.py mercurial/hg.py CHANGE DETAILS diff --git a/mercurial/hg.py b/mercurial/hg.py --- a/mercurial/hg.py +++ b/mercurial/hg.py @@ -749,7 +749,9 @@ overrides = {('ui', 'quietbookmarkmove'): True} with local.ui.configoverride(overrides, 'clone'): exchange.pull(local, srcpeer, revs, - streamclonerequested=stream) + streamclonerequested=stream, + includepats=storeincludepats, + excludepats=storeexcludepats) elif srcrepo: # TODO lift restriction once exchange.push() accepts narrow # push. diff --git a/mercurial/exchange.py b/mercurial/exchange.py --- a/mercurial/exchange.py +++ b/mercurial/exchange.py @@ -1313,7 +1313,8 @@ """ def __init__(self, repo, remote, heads=None, force=False, bookmarks=(), - remotebookmarks=None, streamclonerequested=None): + remotebookmarks=None, streamclonerequested=None, + includepats=None, excludepats=None): # repo we pull into self.repo = repo # repo we pull from @@ -1343,6 +1344,10 @@ self.stepsdone = set() # Whether we attempted a clone from pre-generated bundles. self.clonebundleattempted = False +# Set of file patterns to include. +self.includepats = includepats +# Set of file patterns to exclude. +self.excludepats = excludepats @util.propertycache def pulledsubset(self): @@ -1447,7 +1452,7 @@ pullop.rheads = set(pullop.rheads) - pullop.common def pull(repo, remote, heads=None, force=False, bookmarks=(), opargs=None, - streamclonerequested=None): + streamclonerequested=None, includepats=None, excludepats=None): """Fetch repository data from a remote. This is the main function used to retrieve data from a remote repository. @@ -1465,13 +1470,29 @@ of revlogs from the server. This only works when the local repository is empty. The default value of ``None`` means to respect the server configuration for preferring stream clones. +``includepats`` and ``excludepats`` define explicit file patterns to +include and exclude in storage, respectively. If not defined, narrow +patterns from the repo instance are used, if available. Returns the ``pulloperation`` created for this pull. """ if opargs is None: opargs = {} + +# We allow the narrow patterns to be passed in explicitly to provide more +# flexibility for API consumers. +if includepats or excludepats: +includepats = includepats or set() +excludepats = excludepats or set() +else: +includepats, excludepats = repo.narrowpats + +narrowspec.validatepatterns(includepats) +narrowspec.validatepatterns(excludepats) + pullop = pulloperation(repo, remote, heads, force, bookmarks=bookmarks, streamclonerequested=streamclonerequested, + includepats=includepats, excludepats=excludepats, **pycompat.strkwargs(opargs)) peerlocal = pullop.remote.local() To: indygreg, #hg-reviewers Cc: mercurial-devel ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
D4540: narrow: don't wrap exchange.pull() during clone
This revision was automatically updated to reflect the committed changes. Closed by commit rHG841c82d1a973: narrow: dont wrap exchange.pull() during clone (authored by indygreg, committed by ). REPOSITORY rHG Mercurial CHANGES SINCE LAST UPDATE https://phab.mercurial-scm.org/D4540?vs=10917=10930 REVISION DETAIL https://phab.mercurial-scm.org/D4540 AFFECTED FILES hgext/narrow/narrowcommands.py CHANGE DETAILS diff --git a/hgext/narrow/narrowcommands.py b/hgext/narrow/narrowcommands.py --- a/hgext/narrow/narrowcommands.py +++ b/hgext/narrow/narrowcommands.py @@ -112,16 +112,7 @@ wrappedextraprepare = extensions.wrappedfunction(exchange, '_pullbundle2extraprepare', pullbundle2extraprepare_widen) -def pullnarrow(orig, repo, *args, **kwargs): -if opts['narrow']: -repo.requirements.add(repository.NARROW_REQUIREMENT) -repo._writerequirements() - -return orig(repo, *args, **kwargs) - -wrappedpull = extensions.wrappedfunction(exchange, 'pull', pullnarrow) - -with wrappedextraprepare, wrappedpull: +with wrappedextraprepare: return orig(ui, repo, *args, **pycompat.strkwargs(opts)) def pullnarrowcmd(orig, ui, repo, *args, **opts): To: indygreg, durin42, #hg-reviewers Cc: mercurial-devel ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
D4535: hg: allow extra arguments to be passed to repo creation
This revision was automatically updated to reflect the committed changes. Closed by commit rHG089fc0db0954: hg: allow extra arguments to be passed to repo creation (API) (authored by indygreg, committed by ). CHANGED PRIOR TO COMMIT https://phab.mercurial-scm.org/D4535?vs=10912=10925#toc REPOSITORY rHG Mercurial CHANGES SINCE LAST UPDATE https://phab.mercurial-scm.org/D4535?vs=10912=10925 REVISION DETAIL https://phab.mercurial-scm.org/D4535 AFFECTED FILES hgext/schemes.py mercurial/bundlerepo.py mercurial/hg.py mercurial/httppeer.py mercurial/localrepo.py mercurial/sshpeer.py mercurial/statichttprepo.py mercurial/unionrepo.py CHANGE DETAILS diff --git a/mercurial/unionrepo.py b/mercurial/unionrepo.py --- a/mercurial/unionrepo.py +++ b/mercurial/unionrepo.py @@ -233,7 +233,7 @@ def getcwd(self): return pycompat.getcwd() # always outside the repo -def instance(ui, path, create, intents=None): +def instance(ui, path, create, intents=None, createopts=None): if create: raise error.Abort(_('cannot create new union repository')) parentpath = ui.config("bundle", "mainreporoot") diff --git a/mercurial/statichttprepo.py b/mercurial/statichttprepo.py --- a/mercurial/statichttprepo.py +++ b/mercurial/statichttprepo.py @@ -215,7 +215,7 @@ def _writecaches(self): pass # statichttprepository are read only -def instance(ui, path, create, intents=None): +def instance(ui, path, create, intents=None, createopts=None): if create: raise error.Abort(_('cannot create new static-http repository')) return statichttprepository(ui, path[7:]) diff --git a/mercurial/sshpeer.py b/mercurial/sshpeer.py --- a/mercurial/sshpeer.py +++ b/mercurial/sshpeer.py @@ -597,7 +597,7 @@ raise error.RepoError(_('unknown version of SSH protocol: %s') % protoname) -def instance(ui, path, create, intents=None): +def instance(ui, path, create, intents=None, createopts=None): """Create an SSH peer. The returned object conforms to the ``wireprotov1peer.wirepeer`` interface. @@ -620,6 +620,14 @@ args = procutil.sshargs(sshcmd, u.host, u.user, u.port) if create: +# We /could/ do this, but only if the remote init command knows how to +# handle them. We don't yet make any assumptions about that. And without +# querying the remote, there's no way of knowing if the remote even +# supports said requested feature. +if createopts: +raise error.RepoError(_('cannot create remote SSH repositories ' +'with extra options')) + cmd = '%s %s %s' % (sshcmd, args, procutil.shellquote('%s init %s' % (_serverquote(remotecmd), _serverquote(remotepath diff --git a/mercurial/localrepo.py b/mercurial/localrepo.py --- a/mercurial/localrepo.py +++ b/mercurial/localrepo.py @@ -2380,26 +2380,28 @@ assert name.startswith('journal') return os.path.join(base, name.replace('journal', 'undo', 1)) -def instance(ui, path, create, intents=None): +def instance(ui, path, create, intents=None, createopts=None): if create: vfs = vfsmod.vfs(path, expandpath=True, realpath=True) if vfs.exists('.hg'): raise error.RepoError(_('repository %s already exists') % path) -createrepository(ui, vfs) +createrepository(ui, vfs, createopts=createopts) return localrepository(ui, util.urllocalpath(path), intents=intents) def islocal(path): return True -def newreporequirements(ui): +def newreporequirements(ui, createopts=None): """Determine the set of requirements for a new local repository. Extensions can wrap this function to specify custom requirements for new repositories. """ +createopts = createopts or {} + requirements = {'revlogv1'} if ui.configbool('format', 'usestore'): requirements.add('store') @@ -2440,13 +2442,43 @@ return requirements -def createrepository(ui, wdirvfs): +def filterknowncreateopts(ui, createopts): +"""Filters a dict of repo creation options against options that are known. + +Receives a dict of repo creation options and returns a dict of those +options that we don't know how to handle. + +This function is called as part of repository creation. If the +returned dict contains any items, repository creation will not +be allowed, as it means there was a request to create a repository +with options not recognized by loaded code. + +Extensions can wrap this function to filter out creation options +they know how to handle. +""" +return dict(createopts) + +def createrepository(ui, wdirvfs, createopts=None): """Create a new repository in a vfs. ``wdirvfs`` is a vfs instance pointing at the working directory. ``requirements`` is a set of requirements for the new repository. """ -requirements =
D4537: localrepo: add requirement when narrow files creation option present
This revision was automatically updated to reflect the committed changes. Closed by commit rHG261f1e8dc300: localrepo: add requirement when narrow files creation option present (authored by indygreg, committed by ). REPOSITORY rHG Mercurial CHANGES SINCE LAST UPDATE https://phab.mercurial-scm.org/D4537?vs=10914=10927 REVISION DETAIL https://phab.mercurial-scm.org/D4537 AFFECTED FILES mercurial/localrepo.py CHANGE DETAILS diff --git a/mercurial/localrepo.py b/mercurial/localrepo.py --- a/mercurial/localrepo.py +++ b/mercurial/localrepo.py @@ -2440,6 +2440,9 @@ if ui.configbool('format', 'internal-phase'): requirements.add('internal-phase') +if createopts.get('narrowfiles'): +requirements.add(repository.NARROW_REQUIREMENT) + return requirements def filterknowncreateopts(ui, createopts): @@ -2456,7 +2459,9 @@ Extensions can wrap this function to filter out creation options they know how to handle. """ -return dict(createopts) +known = {'narrowfiles'} + +return {k: v for k, v in createopts.items() if k not in known} def createrepository(ui, wdirvfs, createopts=None): """Create a new repository in a vfs. To: indygreg, #hg-reviewers Cc: mercurial-devel ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
D4534: localrepo: move repo creation logic out of localrepository.__init__
This revision was automatically updated to reflect the committed changes. Closed by commit rHG7ce9dea3a14a: localrepo: move repo creation logic out of localrepository.__init__ (API) (authored by indygreg, committed by ). REPOSITORY rHG Mercurial CHANGES SINCE LAST UPDATE https://phab.mercurial-scm.org/D4534?vs=10911=10924 REVISION DETAIL https://phab.mercurial-scm.org/D4534 AFFECTED FILES hgext/keyword.py mercurial/localrepo.py tests/test-status-inprocess.py CHANGE DETAILS diff --git a/tests/test-status-inprocess.py b/tests/test-status-inprocess.py --- a/tests/test-status-inprocess.py +++ b/tests/test-status-inprocess.py @@ -22,7 +22,7 @@ u = uimod.ui.load() print('% creating repo') -repo = localrepo.localrepository(u, b'.', create=True) +repo = localrepo.instance(u, b'.', create=True) f = open('test.py', 'w') try: diff --git a/mercurial/localrepo.py b/mercurial/localrepo.py --- a/mercurial/localrepo.py +++ b/mercurial/localrepo.py @@ -426,7 +426,13 @@ 'bisect.state', } -def __init__(self, baseui, path, create=False, intents=None): +def __init__(self, baseui, path, intents=None): +"""Create a new local repository instance. + +Most callers should use ``hg.repository()`` or ``localrepo.instance()`` +for obtaining a new repository object. +""" + self.requirements = set() self.filtername = None # wvfs: rooted at the repository root, used to access the working copy @@ -475,31 +481,12 @@ self.supported.add('exp-compression-%s' % name) if not self.vfs.isdir(): -if create: -self.requirements = newreporequirements(self.ui) - -if not self.wvfs.exists(): -self.wvfs.makedirs() -self.vfs.makedir(notindexed=True) - -if 'store' in self.requirements: -self.vfs.mkdir("store") - -# create an invalid changelog -self.vfs.append( -"00changelog.i", -'\0\0\0\2' # represents revlogv2 -' dummy changelog to prevent using the old repo layout' -) -else: -try: -self.vfs.stat() -except OSError as inst: -if inst.errno != errno.ENOENT: -raise -raise error.RepoError(_("repository %s not found") % path) -elif create: -raise error.RepoError(_("repository %s already exists") % path) +try: +self.vfs.stat() +except OSError as inst: +if inst.errno != errno.ENOENT: +raise +raise error.RepoError(_("repository %s not found") % path) else: try: self.requirements = scmutil.readrequires( @@ -546,8 +533,6 @@ else: # standard vfs self.svfs.audit = self._getsvfsward(self.svfs.audit) self._applyopenerreqs() -if create: -self._writerequirements() self._dirstatevalidatewarned = False @@ -2396,8 +2381,15 @@ return os.path.join(base, name.replace('journal', 'undo', 1)) def instance(ui, path, create, intents=None): -return localrepository(ui, util.urllocalpath(path), create, - intents=intents) +if create: +vfs = vfsmod.vfs(path, expandpath=True, realpath=True) + +if vfs.exists('.hg'): +raise error.RepoError(_('repository %s already exists') % path) + +createrepository(ui, vfs) + +return localrepository(ui, util.urllocalpath(path), intents=intents) def islocal(path): return True @@ -2447,3 +2439,34 @@ requirements.add('internal-phase') return requirements + +def createrepository(ui, wdirvfs): +"""Create a new repository in a vfs. + +``wdirvfs`` is a vfs instance pointing at the working directory. +``requirements`` is a set of requirements for the new repository. +""" +requirements = newreporequirements(ui) + +if not wdirvfs.exists(): +wdirvfs.makedirs() + +hgvfs = vfsmod.vfs(wdirvfs.join(b'.hg')) +hgvfs.makedir(notindexed=True) + +if b'store' in requirements: +hgvfs.mkdir(b'store') + +# We create an invalid changelog outside the store so very old +# Mercurial versions (which didn't know about the requirements +# file) encounter an error on reading the changelog. This +# effectively locks out old clients and prevents them from +# mucking with a repo in an unknown format. +# +# The revlog header has version 2, which won't be recognized by +# such old clients. +hgvfs.append(b'00changelog.i', + b'\0\0\0\2 dummy changelog to prevent using the old repo ' + b'layout') + +
D4536: hg: recognize include and exclude patterns when cloning
This revision was automatically updated to reflect the committed changes. Closed by commit rHG65b5900f30be: hg: recognize include and exclude patterns when cloning (authored by indygreg, committed by ). REPOSITORY rHG Mercurial CHANGES SINCE LAST UPDATE https://phab.mercurial-scm.org/D4536?vs=10913=10926 REVISION DETAIL https://phab.mercurial-scm.org/D4536 AFFECTED FILES mercurial/hg.py CHANGE DETAILS diff --git a/mercurial/hg.py b/mercurial/hg.py --- a/mercurial/hg.py +++ b/mercurial/hg.py @@ -35,6 +35,7 @@ logcmdutil, logexchange, merge as mergemod, +narrowspec, node, phases, scmutil, @@ -500,7 +501,8 @@ util.copyfile(srcbranchcache, dstbranchcache) def clone(ui, peeropts, source, dest=None, pull=False, revs=None, - update=True, stream=False, branch=None, shareopts=None): + update=True, stream=False, branch=None, shareopts=None, + storeincludepats=None, storeexcludepats=None): """Make a copy of an existing repository. Create a copy of an existing repository in a new directory. The @@ -542,6 +544,13 @@ repository. "identity" means the name is derived from the node of the first changeset in the repository. "remote" means the name is derived from the remote's path/URL. Defaults to "identity." + +storeincludepats and storeexcludepats: sets of file patterns to include and +exclude in the repository copy, respectively. If not defined, all files +will be included (a "full" clone). Otherwise a "narrow" clone containing +only the requested files will be performed. If ``storeincludepats`` is not +defined but ``storeexcludepats`` is, ``storeincludepats`` is assumed to be +``path:.``. If both are empty sets, no files will be cloned. """ if isinstance(source, bytes): @@ -574,6 +583,24 @@ elif destvfs.listdir(): raise error.Abort(_("destination '%s' is not empty") % dest) +createopts = {} +narrow = False + +if storeincludepats is not None: +narrowspec.validatepatterns(storeincludepats) +narrow = True + +if storeexcludepats is not None: +narrowspec.validatepatterns(storeexcludepats) +narrow = True + +if narrow: +# Include everything by default if only exclusion patterns defined. +if storeexcludepats and not storeincludepats: +storeincludepats = {'path:.'} + +createopts['narrowfiles'] = True + shareopts = shareopts or {} sharepool = shareopts.get('pool') sharenamemode = shareopts.get('mode') @@ -605,6 +632,11 @@ raise error.Abort(_('unknown share naming mode: %s') % sharenamemode) +# TODO this is a somewhat arbitrary restriction. +if narrow: +ui.status(_('(pooled storage not supported for narrow clones)\n')) +sharepath = None + if sharepath: return clonewithshare(ui, peeropts, sharepath, source, srcpeer, dest, pull=pull, rev=revs, update=update, @@ -625,6 +657,10 @@ and not phases.hassecret(srcrepo)): copy = not pull and not revs +# TODO this is a somewhat arbitrary restriction. +if narrow: +copy = False + if copy: try: # we use a lock here because if we race with commit, we @@ -671,8 +707,9 @@ node=node.hex(node.nullid)) else: try: -destpeer = peer(srcrepo or ui, peeropts, dest, create=True) -# only pass ui when no srcrepo +# only pass ui when no srcrepo +destpeer = peer(srcrepo or ui, peeropts, dest, create=True, +createopts=createopts) except OSError as inst: if inst.errno == errno.EEXIST: cleandir = None @@ -714,6 +751,12 @@ exchange.pull(local, srcpeer, revs, streamclonerequested=stream) elif srcrepo: +# TODO lift restriction once exchange.push() accepts narrow +# push. +if narrow: +raise error.Abort(_('narrow clone not available for ' +'remote destinations')) + exchange.push(srcrepo, destpeer, revs=revs, bookmarks=srcrepo._bookmarks.keys()) else: To: indygreg, #hg-reviewers Cc: mercurial-devel ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
D4541: hg: write narrow patterns after repo creation
yuja added a comment. Looks good. Queued the series, thanks. REPOSITORY rHG Mercurial REVISION DETAIL https://phab.mercurial-scm.org/D4541 To: indygreg, durin42, #hg-reviewers Cc: yuja, mercurial-devel ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
Re: D4541: hg: write narrow patterns after repo creation
Looks good. Queued the series, thanks. ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
D4535: hg: allow extra arguments to be passed to repo creation
yuja added a comment. > +def filterknowncreateopts(ui, createopts): > +"""Filters a dict of repo creation options against options that are known. Nit: I thought this would select only known options. > +raise error.Abort(_('unable to create repository because of unknown ' > +'creation option: %s') % > + ', '.sorted(unknownopts.keys()), Removed `.keys()` to make it clearer that we don't need a new list on Py2. REPOSITORY rHG Mercurial REVISION DETAIL https://phab.mercurial-scm.org/D4535 To: indygreg, #hg-reviewers Cc: yuja, mercurial-devel ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
Re: D4535: hg: allow extra arguments to be passed to repo creation
> +def filterknowncreateopts(ui, createopts): > +"""Filters a dict of repo creation options against options that are > known. Nit: I thought this would select only known options. > +raise error.Abort(_('unable to create repository because of unknown ' > +'creation option: %s') % > + ', '.sorted(unknownopts.keys()), Removed `.keys()` to make it clearer that we don't need a new list on Py2. ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
D4533: localrepo: pass ui to newreporequirements()
This revision was automatically updated to reflect the committed changes. Closed by commit rHGc20301a2bd87: localrepo: pass ui to newreporequirements() (authored by indygreg, committed by ). REPOSITORY rHG Mercurial CHANGES SINCE LAST UPDATE https://phab.mercurial-scm.org/D4533?vs=10910=10923 REVISION DETAIL https://phab.mercurial-scm.org/D4533 AFFECTED FILES mercurial/localrepo.py mercurial/upgrade.py tests/simplestorerepo.py CHANGE DETAILS diff --git a/tests/simplestorerepo.py b/tests/simplestorerepo.py --- a/tests/simplestorerepo.py +++ b/tests/simplestorerepo.py @@ -712,9 +712,9 @@ def featuresetup(ui, supported): supported.add(REQUIREMENT) -def newreporequirements(orig, repo): +def newreporequirements(orig, ui): """Modifies default requirements for new repos to use the simple store.""" -requirements = orig(repo) +requirements = orig(ui) # These requirements are only used to affect creation of the store # object. We have our own store. So we can remove them. diff --git a/mercurial/upgrade.py b/mercurial/upgrade.py --- a/mercurial/upgrade.py +++ b/mercurial/upgrade.py @@ -198,8 +198,8 @@ _requirement = None @staticmethod -def _newreporequirements(repo): -return localrepo.newreporequirements(repo) +def _newreporequirements(ui): +return localrepo.newreporequirements(ui) @classmethod def fromrepo(cls, repo): @@ -209,7 +209,7 @@ @classmethod def fromconfig(cls, repo): assert cls._requirement is not None -return cls._requirement in cls._newreporequirements(repo) +return cls._requirement in cls._newreporequirements(repo.ui) @registerformatvariant class fncache(requirementformatvariant): @@ -751,7 +751,7 @@ # FUTURE there is potentially a need to control the wanted requirements via # command arguments or via an extension hook point. -newreqs = localrepo.newreporequirements(repo) +newreqs = localrepo.newreporequirements(repo.ui) newreqs.update(preservedrequirements(repo)) noremovereqs = (repo.requirements - newreqs - diff --git a/mercurial/localrepo.py b/mercurial/localrepo.py --- a/mercurial/localrepo.py +++ b/mercurial/localrepo.py @@ -476,7 +476,7 @@ if not self.vfs.isdir(): if create: -self.requirements = newreporequirements(self) +self.requirements = newreporequirements(self.ui) if not self.wvfs.exists(): self.wvfs.makedirs() @@ -2402,13 +2402,12 @@ def islocal(path): return True -def newreporequirements(repo): +def newreporequirements(ui): """Determine the set of requirements for a new local repository. Extensions can wrap this function to specify custom requirements for new repositories. """ -ui = repo.ui requirements = {'revlogv1'} if ui.configbool('format', 'usestore'): requirements.add('store') @@ -2444,7 +2443,7 @@ requirements.discard('generaldelta') requirements.add(REVLOGV2_REQUIREMENT) # experimental config: format.internal-phase -if repo.ui.configbool('format', 'internal-phase'): +if ui.configbool('format', 'internal-phase'): requirements.add('internal-phase') return requirements To: indygreg, #hg-reviewers, pulkit Cc: mercurial-devel ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel