D1376: bundlerepo: don't assume there are only two bundle classes
indygreg created this revision. Herald added a subscriber: mercurial-devel. Herald added a reviewer: hg-reviewers. REVISION SUMMARY exchange.readbundle() can return a type that represents a stream clone bundle. Explicitly handle the bundle1 type and raise a reasonable error message for unhandled bundle types. REPOSITORY rHG Mercurial REVISION DETAIL https://phab.mercurial-scm.org/D1376 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 @@ -296,13 +296,16 @@ if not hadchangegroup: raise error.Abort(_("No changegroups found")) - -elif self.bundle.compressed(): -f = self._writetempbundle(self.bundle.read, '.hg10un', - header='HG10UN') -self.bundlefile = self.bundle = exchange.readbundle(ui, f, -bundlepath, -self.vfs) +elif isinstance(self.bundle, changegroup.cg1unpacker): +if self.bundle.compressed(): +f = self._writetempbundle(self.bundle.read, '.hg10un', + header='HG10UN') +self.bundlefile = self.bundle = exchange.readbundle(ui, f, +bundlepath, +self.vfs) +else: +raise error.Abort(_('bundle type %s cannot be read') % + type(self.bundle)) # dict with the mapping 'filename' -> position in the bundle self.bundlefilespos = {} 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
D1375: bundlerepo: add docstring for bundlerepository class
indygreg 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/D1375 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 @@ -256,6 +256,14 @@ return bundlefilespos class bundlerepository(localrepo.localrepository): +"""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. +""" def __init__(self, ui, repopath, bundlepath): self._tempparent = None try: 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
D1378: bundlerepo: assign bundle attributes in bundle type blocks
indygreg created this revision. Herald added a subscriber: mercurial-devel. Herald added a reviewer: hg-reviewers. REVISION SUMMARY It is a bit wonky to assign the same object to multiple attributes and then possibly overwrite them later. Refactor the code to use a local variable and defer attribute assignment until the final values are ready. This required passing the bundle instance to _handlebundle2part(). The only use of this method I could find is Facebook's treemanifest extension. Since it is a private method, I don't think it warrants an API callout. REPOSITORY rHG Mercurial REVISION DETAIL https://phab.mercurial-scm.org/D1378 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 @@ -281,47 +281,52 @@ self.tempfile = None f = util.posixfile(bundlepath, "rb") -self._bundlefile = self._bundle = exchange.readbundle(ui, f, bundlepath) +bundle = exchange.readbundle(ui, f, bundlepath) -if isinstance(self._bundle, bundle2.unbundle20): +if isinstance(bundle, bundle2.unbundle20): +self._bundlefile = bundle +self._bundle = None + hadchangegroup = False -for part in self._bundle.iterparts(): +for part in bundle.iterparts(): if part.type == 'changegroup': if hadchangegroup: raise NotImplementedError("can't process " "multiple changegroups") hadchangegroup = True -self._handlebundle2part(part) +self._handlebundle2part(bundle, part) if not hadchangegroup: raise error.Abort(_("No changegroups found")) -elif isinstance(self._bundle, changegroup.cg1unpacker): -if self._bundle.compressed(): -f = self._writetempbundle(self._bundle.read, '.hg10un', +elif isinstance(bundle, changegroup.cg1unpacker): +if bundle.compressed(): +f = self._writetempbundle(bundle.read, '.hg10un', header='HG10UN') -self._bundlefile = self._bundle = exchange.readbundle( -ui, f, bundlepath, self.vfs) +bundle = exchange.readbundle(ui, f, bundlepath, self.vfs) + +self._bundlefile = bundle +self._bundle = bundle else: raise error.Abort(_('bundle type %s cannot be read') % - type(self._bundle)) + type(bundle)) # dict with the mapping 'filename' -> position in the bundle self.bundlefilespos = {} self.firstnewrev = self.changelog.repotiprev + 1 phases.retractboundary(self, None, phases.draft, [ctx.node() for ctx in self[self.firstnewrev:]]) -def _handlebundle2part(self, part): +def _handlebundle2part(self, bundle, part): if part.type == 'changegroup': cgstream = part version = part.params.get('version', '01') legalcgvers = changegroup.supportedincomingversions(self) if version not in legalcgvers: msg = _('Unsupported changegroup version: %s') raise error.Abort(msg % version) -if self._bundle.compressed(): +if bundle.compressed(): cgstream = self._writetempbundle(part.read, ".cg%sun" % version) 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
D1379: bundlerepo: rename _bundle to _cgunpacker
indygreg created this revision. Herald added a subscriber: mercurial-devel. Herald added a reviewer: hg-reviewers. REVISION SUMMARY _bundle is really a changegroup unpacker instance. Rename the variable accordingly. REPOSITORY rHG Mercurial REVISION DETAIL https://phab.mercurial-scm.org/D1379 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 @@ -285,7 +285,7 @@ if isinstance(bundle, bundle2.unbundle20): self._bundlefile = bundle -self._bundle = None +self._cgunpacker = None hadchangegroup = False for part in bundle.iterparts(): @@ -306,7 +306,7 @@ bundle = exchange.readbundle(ui, f, bundlepath, self.vfs) self._bundlefile = bundle -self._bundle = bundle +self._cgunpacker = bundle else: raise error.Abort(_('bundle type %s cannot be read') % type(bundle)) @@ -330,7 +330,8 @@ cgstream = self._writetempbundle(part.read, ".cg%sun" % version) -self._bundle = changegroup.getunbundler(version, cgstream, 'UN') +self._cgunpacker = changegroup.getunbundler(version, cgstream, + 'UN') def _writetempbundle(self, readfn, suffix, header=''): """Write a temporary file to disk @@ -356,28 +357,28 @@ @localrepo.unfilteredpropertycache def changelog(self): # consume the header if it exists -self._bundle.changelogheader() -c = bundlechangelog(self.svfs, self._bundle) -self.manstart = self._bundle.tell() +self._cgunpacker.changelogheader() +c = bundlechangelog(self.svfs, self._cgunpacker) +self.manstart = self._cgunpacker.tell() return c def _constructmanifest(self): -self._bundle.seek(self.manstart) +self._cgunpacker.seek(self.manstart) # consume the header if it exists -self._bundle.manifestheader() +self._cgunpacker.manifestheader() linkmapper = self.unfiltered().changelog.rev -m = bundlemanifest(self.svfs, self._bundle, linkmapper) -self.filestart = self._bundle.tell() +m = bundlemanifest(self.svfs, self._cgunpacker, linkmapper) +self.filestart = self._cgunpacker.tell() return m def _consumemanifest(self): """Consumes the manifest portion of the bundle, setting filestart so the file portion can be read.""" -self._bundle.seek(self.manstart) -self._bundle.manifestheader() -for delta in self._bundle.deltaiter(): +self._cgunpacker.seek(self.manstart) +self._cgunpacker.manifestheader() +for delta in self._cgunpacker.deltaiter(): pass -self.filestart = self._bundle.tell() +self.filestart = self._cgunpacker.tell() @localrepo.unfilteredpropertycache def manstart(self): @@ -402,13 +403,13 @@ def file(self, f): if not self.bundlefilespos: -self._bundle.seek(self.filestart) -self.bundlefilespos = _getfilestarts(self._bundle) +self._cgunpacker.seek(self.filestart) +self.bundlefilespos = _getfilestarts(self._cgunpacker) if f in self.bundlefilespos: -self._bundle.seek(self.bundlefilespos[f]) +self._cgunpacker.seek(self.bundlefilespos[f]) linkmapper = self.unfiltered().changelog.rev -return bundlefilelog(self.svfs, f, self._bundle, linkmapper) +return bundlefilelog(self.svfs, f, self._cgunpacker, linkmapper) else: return filelog.filelog(self.svfs, f) 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
D1377: bundlerepo: make bundle and bundlefile attributes private
indygreg created this revision. Herald added a subscriber: mercurial-devel. Herald added a reviewer: hg-reviewers. REVISION SUMMARY These attributes are implementation details and shouldn't be exposed outside the class. .. api:: bundlerepo.bundlerepository.bundle and bundlerepo.bundlerepository.bundlefile are now prefixed with an underscore. REPOSITORY rHG Mercurial REVISION DETAIL https://phab.mercurial-scm.org/D1377 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 @@ -281,11 +281,11 @@ self.tempfile = None f = util.posixfile(bundlepath, "rb") -self.bundlefile = self.bundle = exchange.readbundle(ui, f, bundlepath) +self._bundlefile = self._bundle = exchange.readbundle(ui, f, bundlepath) -if isinstance(self.bundle, bundle2.unbundle20): +if isinstance(self._bundle, bundle2.unbundle20): hadchangegroup = False -for part in self.bundle.iterparts(): +for part in self._bundle.iterparts(): if part.type == 'changegroup': if hadchangegroup: raise NotImplementedError("can't process " @@ -296,16 +296,15 @@ if not hadchangegroup: raise error.Abort(_("No changegroups found")) -elif isinstance(self.bundle, changegroup.cg1unpacker): -if self.bundle.compressed(): -f = self._writetempbundle(self.bundle.read, '.hg10un', +elif isinstance(self._bundle, changegroup.cg1unpacker): +if self._bundle.compressed(): +f = self._writetempbundle(self._bundle.read, '.hg10un', header='HG10UN') -self.bundlefile = self.bundle = exchange.readbundle(ui, f, -bundlepath, -self.vfs) +self._bundlefile = self._bundle = exchange.readbundle( +ui, f, bundlepath, self.vfs) else: raise error.Abort(_('bundle type %s cannot be read') % - type(self.bundle)) + type(self._bundle)) # dict with the mapping 'filename' -> position in the bundle self.bundlefilespos = {} @@ -322,11 +321,11 @@ if version not in legalcgvers: msg = _('Unsupported changegroup version: %s') raise error.Abort(msg % version) -if self.bundle.compressed(): +if self._bundle.compressed(): cgstream = self._writetempbundle(part.read, ".cg%sun" % version) -self.bundle = changegroup.getunbundler(version, cgstream, 'UN') +self._bundle = changegroup.getunbundler(version, cgstream, 'UN') def _writetempbundle(self, readfn, suffix, header=''): """Write a temporary file to disk @@ -352,28 +351,28 @@ @localrepo.unfilteredpropertycache def changelog(self): # consume the header if it exists -self.bundle.changelogheader() -c = bundlechangelog(self.svfs, self.bundle) -self.manstart = self.bundle.tell() +self._bundle.changelogheader() +c = bundlechangelog(self.svfs, self._bundle) +self.manstart = self._bundle.tell() return c def _constructmanifest(self): -self.bundle.seek(self.manstart) +self._bundle.seek(self.manstart) # consume the header if it exists -self.bundle.manifestheader() +self._bundle.manifestheader() linkmapper = self.unfiltered().changelog.rev -m = bundlemanifest(self.svfs, self.bundle, linkmapper) -self.filestart = self.bundle.tell() +m = bundlemanifest(self.svfs, self._bundle, linkmapper) +self.filestart = self._bundle.tell() return m def _consumemanifest(self): """Consumes the manifest portion of the bundle, setting filestart so the file portion can be read.""" -self.bundle.seek(self.manstart) -self.bundle.manifestheader() -for delta in self.bundle.deltaiter(): +self._bundle.seek(self.manstart) +self._bundle.manifestheader() +for delta in self._bundle.deltaiter(): pass -self.filestart = self.bundle.tell() +self.filestart = self._bundle.tell() @localrepo.unfilteredpropertycache def manstart(self): @@ -398,19 +397,19 @@ def file(self, f): if not self.bundlefilespos: -self.bundle.seek(self.filestart) -self.bundlefilespos = _getfilestarts(self.bundle) +self._bundle.seek(self.filestart) +self.bundlefilespos = _getfilestarts(self._bu
D1374: bundlerepo: rename arguments to bundlerepository.__init__
indygreg created this revision. Herald added a subscriber: mercurial-devel. Herald added a reviewer: hg-reviewers. REVISION SUMMARY To reflect what they actually are. REPOSITORY rHG Mercurial REVISION DETAIL https://phab.mercurial-scm.org/D1374 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 @@ -256,24 +256,24 @@ return bundlefilespos class bundlerepository(localrepo.localrepository): -def __init__(self, ui, path, bundlename): +def __init__(self, ui, repopath, bundlepath): self._tempparent = None try: -localrepo.localrepository.__init__(self, ui, path) +localrepo.localrepository.__init__(self, ui, repopath) except error.RepoError: self._tempparent = tempfile.mkdtemp() localrepo.instance(ui, self._tempparent, 1) localrepo.localrepository.__init__(self, ui, self._tempparent) self.ui.setconfig('phases', 'publish', False, 'bundlerepo') -if path: -self._url = 'bundle:' + util.expandpath(path) + '+' + bundlename +if repopath: +self._url = 'bundle:' + util.expandpath(repopath) + '+' + bundlepath else: -self._url = 'bundle:' + bundlename +self._url = 'bundle:' + bundlepath self.tempfile = None -f = util.posixfile(bundlename, "rb") -self.bundlefile = self.bundle = exchange.readbundle(ui, f, bundlename) +f = util.posixfile(bundlepath, "rb") +self.bundlefile = self.bundle = exchange.readbundle(ui, f, bundlepath) if isinstance(self.bundle, bundle2.unbundle20): hadchangegroup = False @@ -293,7 +293,7 @@ f = self._writetempbundle(self.bundle.read, '.hg10un', header='HG10UN') self.bundlefile = self.bundle = exchange.readbundle(ui, f, -bundlename, +bundlepath, self.vfs) # dict with the mapping 'filename' -> position in the bundle 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
D1372: bundlerepo: make methods agree with base class
indygreg created this revision. Herald added a subscriber: mercurial-devel. Herald added a reviewer: hg-reviewers. REVISION SUMMARY My editor was complaining about mismatches between method signatures. For methods that are implemented, we change arguments to match the base. For those that aren't, we use variable arguments because it shouldn't matter. REPOSITORY rHG Mercurial REVISION DETAIL https://phab.mercurial-scm.org/D1372 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 @@ -86,7 +86,7 @@ self.bundlerevs.add(n) n += 1 -def _chunk(self, rev): +def _chunk(self, rev, df=None): # Warning: in case of bundle, the diff is against what we stored as # delta base, not against rev - 1 # XXX: could use some caching @@ -108,7 +108,7 @@ return mdiff.textdiff(self.revision(rev1, raw=True), self.revision(rev2, raw=True)) -def revision(self, nodeorrev, raw=False): +def revision(self, nodeorrev, _df=None, raw=False): """return an uncompressed revision of a given node or revision number. """ @@ -152,12 +152,15 @@ # needs to override 'baserevision' and make more specific call here. return revlog.revlog.revision(self, nodeorrev, raw=True) -def addrevision(self, text, transaction, link, p1=None, p2=None, d=None): +def addrevision(self, *args, **kwargs): +raise NotImplementedError + +def addgroup(self, *args, **kwargs): raise NotImplementedError -def addgroup(self, deltas, transaction, addrevisioncb=None): + +def strip(self, *args, **kwargs): raise NotImplementedError -def strip(self, rev, minlink): -raise NotImplementedError + def checksize(self): raise NotImplementedError 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
D1373: bundlerepo: use suffix variable
indygreg created this revision. Herald added a subscriber: mercurial-devel. Herald added a reviewer: hg-reviewers. REVISION SUMMARY It looks like the refactor in https://phab.mercurial-scm.org/rHG702a26fec3e2e85f05af3ebeaf0fc037027ad2b6 attempted to establish this method argument but failed to use it. My editor caught it. REPOSITORY rHG Mercurial REVISION DETAIL https://phab.mercurial-scm.org/D1373 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 @@ -321,7 +321,7 @@ """Write a temporary file to disk """ fdtemp, temp = self.vfs.mkstemp(prefix="hg-bundle-", -suffix=".hg10un") +suffix=suffix) self.tempfile = temp with os.fdopen(fdtemp, pycompat.sysstr('wb')) as fptemp: 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
D1370: bundle2: use os.SEEK_* constants
indygreg created this revision. Herald added a subscriber: mercurial-devel. Herald added a reviewer: hg-reviewers. REVISION SUMMARY Constants make code easier to read than magic numbers. I also threw in an explicit argument in a caller to further increase code comprehension. REPOSITORY rHG Mercurial REVISION DETAIL https://phab.mercurial-scm.org/D1370 AFFECTED FILES mercurial/bundle2.py CHANGE DETAILS diff --git a/mercurial/bundle2.py b/mercurial/bundle2.py --- a/mercurial/bundle2.py +++ b/mercurial/bundle2.py @@ -148,6 +148,7 @@ from __future__ import absolute_import, division import errno +import os import re import string import struct @@ -362,7 +363,7 @@ self.count = count self.current = p yield p -p.seek(0, 2) +p.seek(0, os.SEEK_END) self.current = None self.iterator = func() return self.iterator @@ -384,11 +385,11 @@ try: if self.current: # consume the part content to not corrupt the stream. -self.current.seek(0, 2) +self.current.seek(0, os.SEEK_END) for part in self.iterator: # consume the bundle content -part.seek(0, 2) +part.seek(0, os.SEEK_END) except Exception: seekerror = True @@ -858,8 +859,8 @@ # Seek to the end of the part to force it's consumption so the next # part can be read. But then seek back to the beginning so the # code consuming this generator has a part that starts at 0. -part.seek(0, 2) -part.seek(0) +part.seek(0, os.SEEK_END) +part.seek(0, os.SEEK_SET) headerblock = self._readpartheader() indebug(self.ui, 'end of bundle2 stream') @@ -1164,7 +1165,7 @@ raise finally: if not hardabort: -part.seek(0, 2) +part.seek(0, os.SEEK_END) self.ui.debug('bundle2-input-stream-interrupt:' ' closing out of band context\n') @@ -1330,12 +1331,12 @@ def tell(self): return self._pos -def seek(self, offset, whence=0): -if whence == 0: +def seek(self, offset, whence=os.SEEK_SET): +if whence == os.SEEK_SET: newpos = offset -elif whence == 1: +elif whence == os.SEEK_CUR: newpos = self._pos + offset -elif whence == 2: +elif whence == os.SEEK_END: if not self.consumed: self.read() newpos = self._chunkindex[-1][0] - offset 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
D1336: remove: print message for each file in verbose mode only while using `-A`
mharbison72 added a comment. Looks good to me, thanks. REPOSITORY rHG Mercurial REVISION DETAIL https://phab.mercurial-scm.org/D1336 To: pavanpc, #hg-reviewers Cc: mitrandir, mharbison72, mercurial-devel ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
D1336: remove: print message for each file in verbose mode only while using `-A`
pavanpc updated this revision to Diff 3424. REPOSITORY rHG Mercurial CHANGES SINCE LAST UPDATE https://phab.mercurial-scm.org/D1336?vs=3423&id=3424 REVISION DETAIL https://phab.mercurial-scm.org/D1336 AFFECTED FILES mercurial/cmdutil.py tests/test-remove.t CHANGE DETAILS diff --git a/tests/test-remove.t b/tests/test-remove.t --- a/tests/test-remove.t +++ b/tests/test-remove.t @@ -168,11 +168,11 @@ \r (no-eol) (esc) 1 files updated, 0 files merged, 0 files removed, 0 files unresolved -20 state added, options -A +20 state added, options -Av $ echo b > bar $ hg add bar - $ remove -A bar + $ remove -Av bar \r (no-eol) (esc) deleting [===>] 1/1\r (no-eol) (esc) \r (no-eol) (esc) @@ -189,9 +189,9 @@ \r (no-eol) (esc) 0 files updated, 0 files merged, 0 files removed, 0 files unresolved -21 state clean, options -A +21 state clean, options -Av - $ remove -A foo + $ remove -Av foo \r (no-eol) (esc) deleting [===>] 1/1\r (no-eol) (esc) \r (no-eol) (esc) @@ -205,10 +205,10 @@ ./foo 0 files updated, 0 files merged, 0 files removed, 0 files unresolved -22 state modified, options -A +22 state modified, options -Av $ echo b >> foo - $ remove -A foo + $ remove -Av foo \r (no-eol) (esc) deleting [===>] 1/1\r (no-eol) (esc) \r (no-eol) (esc) @@ -357,10 +357,10 @@ \r (no-eol) (esc) 2 files updated, 0 files merged, 0 files removed, 0 files unresolved -dir, options -A +dir, options -Av $ rm test/bar - $ remove -A test + $ remove -Av test \r (no-eol) (esc) deleting [===>] 1/1\r (no-eol) (esc) \r (no-eol) (esc) diff --git a/mercurial/cmdutil.py b/mercurial/cmdutil.py --- a/mercurial/cmdutil.py +++ b/mercurial/cmdutil.py @@ -2975,8 +2975,9 @@ for f in remaining: count += 1 ui.progress(_('skipping'), count, total=total, unit=_('files')) -warnings.append(_('not removing %s: file still exists\n') -% m.rel(f)) +if ui.verbose: +warnings.append(_('not removing %s: file still exists\n') +% m.rel(f)) ret = 1 ui.progress(_('skipping'), None) else: To: pavanpc, #hg-reviewers Cc: mitrandir, mharbison72, mercurial-devel ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
[PATCH 4 of 4 STABLE] dispatch: abort if early boolean options can't be parsed
# HG changeset patch # User Yuya Nishihara # Date 1510376561 -32400 # Sat Nov 11 14:02:41 2017 +0900 # Branch stable # Node ID a8d8c3229692d77881a6242329160803cb5ab8c5 # Parent ed13a7f6d26a28f73593a091a6a57c756678245b dispatch: abort if early boolean options can't be parsed Perhaps we'll need to restrict the parsing rules of --debugger and --profile, where this patch will help us know why the --debugger option doesn't work. I have another series to extend this feature to --config/--cwd/-R, but even with that, shell aliases can be used to get around the restriction. diff --git a/mercurial/dispatch.py b/mercurial/dispatch.py --- a/mercurial/dispatch.py +++ b/mercurial/dispatch.py @@ -55,6 +55,9 @@ class request(object): self.fout = fout self.ferr = ferr +# remember options pre-parsed by _earlyreqopt*() +self.earlyoptions = {} + # reposetups which run before extensions, useful for chg to pre-fill # low-level repo state (for example, changelog) before extensions. self.prereposetups = prereposetups or [] @@ -707,19 +710,19 @@ def _earlyreqoptbool(req, name, aliases) >>> req = request([b'x', b'--', b'--debugger']) >>> _earlyreqoptbool(req, b'debugger', [b'--debugger']) -False """ try: argcount = req.args.index("--") except ValueError: argcount = len(req.args) -value = False +value = None pos = 0 while pos < argcount: arg = req.args[pos] if arg in aliases: value = True pos += 1 +req.earlyoptions[name] = value return value def runcommand(lui, repo, cmd, fullargs, ui, options, d, cmdpats, cmdoptions): @@ -849,6 +852,9 @@ def _dispatch(req): raise error.Abort(_( "option -R has to be separated from other options (e.g. not " "-qR) and --repository may only be abbreviated as --repo!")) +if options["debugger"] != req.earlyoptions["debugger"]: +raise error.Abort(_("option --debugger may not be abbreviated!")) +# don't validate --profile/--traceback, which can be enabled from now if options["encoding"]: encoding.encoding = options["encoding"] diff --git a/tests/test-dispatch.t b/tests/test-dispatch.t --- a/tests/test-dispatch.t +++ b/tests/test-dispatch.t @@ -51,6 +51,12 @@ Parsing of early options should stop at --debugger: no such file in rev cb9a9f314b8b [1] +Unparsable form of early options: + + $ hg cat --debugg + abort: option --debugger may not be abbreviated! + [255] + [defaults] $ hg cat a ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
[PATCH 2 of 4 STABLE] dispatch: extract stub function to peek boolean command option
# HG changeset patch # User Yuya Nishihara # Date 1510320159 -32400 # Fri Nov 10 22:22:39 2017 +0900 # Branch stable # Node ID e8c581ae8e8835cf7fc83e749a84919aea11f63a # Parent ffd80f114a5568161658da273af2942f471e05bc dispatch: extract stub function to peek boolean command option We should at least stop parsing at "--". The 'name' argument is passed for future extension. diff --git a/mercurial/dispatch.py b/mercurial/dispatch.py --- a/mercurial/dispatch.py +++ b/mercurial/dispatch.py @@ -147,7 +147,7 @@ def dispatch(req): try: if not req.ui: req.ui = uimod.ui.load() -if '--traceback' in req.args: +if _earlyreqoptbool(req, 'traceback', ['--traceback']): req.ui.setconfig('ui', 'traceback', 'on', '--traceback') # set ui streams from the request @@ -275,7 +275,7 @@ def _runcatch(req): if not debugger or ui.plain(): # if we are in HGPLAIN mode, then disable custom debugging debugger = 'pdb' -elif '--debugger' in req.args: +elif _earlyreqoptbool(req, 'debugger', ['--debugger']): # This import can be slow for fancy debuggers, so only # do it when absolutely necessary, i.e. when actual # debugging has been requested @@ -289,7 +289,7 @@ def _runcatch(req): debugmortem[debugger] = debugmod.post_mortem # enter the debugger before command execution -if '--debugger' in req.args: +if _earlyreqoptbool(req, 'debugger', ['--debugger']): ui.warn(_("entering debugger - " "type c to continue starting hg or h for help\n")) @@ -305,7 +305,7 @@ def _runcatch(req): ui.flush() except: # re-raises # enter the debugger when we hit an exception -if '--debugger' in req.args: +if _earlyreqoptbool(req, 'debugger', ['--debugger']): traceback.print_exc() debugmortem[debugger](sys.exc_info()[2]) raise @@ -698,6 +698,10 @@ def _earlygetopt(aliases, args): pos += 1 return values +def _earlyreqoptbool(req, name, aliases): +assert len(aliases) == 1 +return aliases[0] in req.args + def runcommand(lui, repo, cmd, fullargs, ui, options, d, cmdpats, cmdoptions): # run pre-hook, and abort if it fails hook.hook(lui, repo, "pre-%s" % cmd, True, args=" ".join(fullargs), @@ -785,7 +789,7 @@ def _dispatch(req): if req.repo: uis.add(req.repo.ui) -if '--profile' in args: +if _earlyreqoptbool(req, 'profile', ['--profile']): for ui_ in uis: ui_.setconfig('profiling', 'enabled', 'true', '--profile') ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
[PATCH 3 of 4 STABLE] dispatch: stop parsing of early boolean option at "--"
# HG changeset patch # User Yuya Nishihara # Date 1510320446 -32400 # Fri Nov 10 22:27:26 2017 +0900 # Branch stable # Node ID ed13a7f6d26a28f73593a091a6a57c756678245b # Parent e8c581ae8e8835cf7fc83e749a84919aea11f63a dispatch: stop parsing of early boolean option at "--" diff --git a/mercurial/dispatch.py b/mercurial/dispatch.py --- a/mercurial/dispatch.py +++ b/mercurial/dispatch.py @@ -699,8 +699,28 @@ def _earlygetopt(aliases, args): return values def _earlyreqoptbool(req, name, aliases): -assert len(aliases) == 1 -return aliases[0] in req.args +"""Peek a boolean option without using a full options table + +>>> req = request([b'x', b'--debugger']) +>>> _earlyreqoptbool(req, b'debugger', [b'--debugger']) +True + +>>> req = request([b'x', b'--', b'--debugger']) +>>> _earlyreqoptbool(req, b'debugger', [b'--debugger']) +False +""" +try: +argcount = req.args.index("--") +except ValueError: +argcount = len(req.args) +value = False +pos = 0 +while pos < argcount: +arg = req.args[pos] +if arg in aliases: +value = True +pos += 1 +return value def runcommand(lui, repo, cmd, fullargs, ui, options, d, cmdpats, cmdoptions): # run pre-hook, and abort if it fails diff --git a/tests/test-dispatch.t b/tests/test-dispatch.t --- a/tests/test-dispatch.t +++ b/tests/test-dispatch.t @@ -42,6 +42,15 @@ Missing parameter for early option: hg log [OPTION]... [FILE] (use 'hg log -h' to show more help) +Parsing of early options should stop at "--": + + $ hg cat -- --config=hooks.pre-cat=false + --config=hooks.pre-cat=false: no such file in rev cb9a9f314b8b + [1] + $ hg cat -- --debugger + --debugger: no such file in rev cb9a9f314b8b + [1] + [defaults] $ hg cat a ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
[PATCH 1 of 4 STABLE] dispatch: do not drop unpaired argument at _earlygetopt()
# HG changeset patch # User Yuya Nishihara # Date 1510369759 -32400 # Sat Nov 11 12:09:19 2017 +0900 # Branch stable # Node ID ffd80f114a5568161658da273af2942f471e05bc # Parent 691524f0bbf6cd44fc26ebfce046e6c4888a1b0f dispatch: do not drop unpaired argument at _earlygetopt() Before, "hg log -R" just worked. diff --git a/mercurial/dispatch.py b/mercurial/dispatch.py --- a/mercurial/dispatch.py +++ b/mercurial/dispatch.py @@ -661,6 +661,10 @@ def _earlygetopt(aliases, args): >>> args = [b'x', b'-Rbar', b'y'] >>> _earlygetopt([b'-R'], args), args (['bar'], ['x', 'y']) + +>>> args = [b'x', b'-R', b'--', b'y'] +>>> _earlygetopt([b'-R'], args), args +([], ['x', '-R', '--', 'y']) """ try: argcount = args.index("--") @@ -675,14 +679,15 @@ def _earlygetopt(aliases, args): if equals > -1: arg = arg[:equals] if arg in aliases: -del args[pos] if equals > -1: +del args[pos] values.append(fullarg[equals + 1:]) argcount -= 1 else: if pos + 1 >= argcount: # ignore and let getopt report an error if there is no value break +del args[pos] values.append(args.pop(pos)) argcount -= 2 elif arg[:2] in shortopts: diff --git a/tests/test-bookmarks-pushpull.t b/tests/test-bookmarks-pushpull.t --- a/tests/test-bookmarks-pushpull.t +++ b/tests/test-bookmarks-pushpull.t @@ -175,7 +175,7 @@ divergent bookmarks Z 1:0d2164f0ce0d $ cd ../b - $ hg up --config + $ hg up 1 files updated, 0 files merged, 0 files removed, 0 files unresolved updating bookmark foobar $ echo c2 > f2 diff --git a/tests/test-dispatch.t b/tests/test-dispatch.t --- a/tests/test-dispatch.t +++ b/tests/test-dispatch.t @@ -30,6 +30,18 @@ Missing arg: (use 'hg cat -h' to show more help) [255] +Missing parameter for early option: + + $ hg log -R 2>&1 | grep 'hg log' + hg log: option -R requires argument + hg log [OPTION]... [FILE] + (use 'hg log -h' to show more help) + + $ hg log -R -- 2>&1 | grep 'hg log' + hg log: option -R requires argument + hg log [OPTION]... [FILE] + (use 'hg log -h' to show more help) + [defaults] $ hg cat a diff --git a/tests/test-setdiscovery.t b/tests/test-setdiscovery.t --- a/tests/test-setdiscovery.t +++ b/tests/test-setdiscovery.t @@ -17,7 +17,7 @@ Function to test discovery between two r > hg -R a debugdiscovery b --verbose --debug --config progress.debug=true > echo > echo "% -- b -> a tree" - > hg -R b debugdiscovery a --verbose --old --config + > hg -R b debugdiscovery a --verbose --old > echo > echo "% -- b -> a set" > hg -R b debugdiscovery a --verbose --debug --config progress.debug=true ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
D1336: remove: print message for each file in verbose mode only while using `-A`
pavanpc updated this revision to Diff 3423. pavanpc marked an inline comment as done. REPOSITORY rHG Mercurial CHANGES SINCE LAST UPDATE https://phab.mercurial-scm.org/D1336?vs=3391&id=3423 REVISION DETAIL https://phab.mercurial-scm.org/D1336 AFFECTED FILES mercurial/cmdutil.py tests/test-remove.t CHANGE DETAILS diff --git a/tests/test-remove.t b/tests/test-remove.t --- a/tests/test-remove.t +++ b/tests/test-remove.t @@ -168,11 +168,11 @@ \r (no-eol) (esc) 1 files updated, 0 files merged, 0 files removed, 0 files unresolved -20 state added, options -A +20 state added, options -Av $ echo b > bar $ hg add bar - $ remove -A bar + $ remove -Av bar \r (no-eol) (esc) deleting [===>] 1/1\r (no-eol) (esc) \r (no-eol) (esc) @@ -189,9 +189,9 @@ \r (no-eol) (esc) 0 files updated, 0 files merged, 0 files removed, 0 files unresolved -21 state clean, options -A +21 state clean, options -Av - $ remove -A foo + $ remove -Av foo \r (no-eol) (esc) deleting [===>] 1/1\r (no-eol) (esc) \r (no-eol) (esc) @@ -205,10 +205,10 @@ ./foo 0 files updated, 0 files merged, 0 files removed, 0 files unresolved -22 state modified, options -A +22 state modified, options -Av $ echo b >> foo - $ remove -A foo + $ remove -Av foo \r (no-eol) (esc) deleting [===>] 1/1\r (no-eol) (esc) \r (no-eol) (esc) @@ -357,10 +357,10 @@ \r (no-eol) (esc) 2 files updated, 0 files merged, 0 files removed, 0 files unresolved -dir, options -A +dir, options -Av $ rm test/bar - $ remove -A test + $ remove -Av test \r (no-eol) (esc) deleting [===>] 1/1\r (no-eol) (esc) \r (no-eol) (esc) @@ -448,7 +448,7 @@ [1] $ hg add d1/a $ rm d1/a - $ hg rm --after d1 + $ hg rm --after d1 \r (no-eol) (esc) deleting [===>] 1/1\r (no-eol) (esc) \r (no-eol) (esc) diff --git a/mercurial/cmdutil.py b/mercurial/cmdutil.py --- a/mercurial/cmdutil.py +++ b/mercurial/cmdutil.py @@ -2975,8 +2975,9 @@ for f in remaining: count += 1 ui.progress(_('skipping'), count, total=total, unit=_('files')) -warnings.append(_('not removing %s: file still exists\n') -% m.rel(f)) +if ui.verbose: +warnings.append(_('not removing %s: file still exists\n') +% m.rel(f)) ret = 1 ui.progress(_('skipping'), None) else: To: pavanpc, #hg-reviewers Cc: mitrandir, mharbison72, mercurial-devel ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
D971: uncommit: unify functions _uncommitdirstate and _unamenddirstate to one
pulkit updated this revision to Diff 3422. REPOSITORY rHG Mercurial CHANGES SINCE LAST UPDATE https://phab.mercurial-scm.org/D971?vs=2494&id=3422 REVISION DETAIL https://phab.mercurial-scm.org/D971 AFFECTED FILES hgext/uncommit.py CHANGE DETAILS diff --git a/hgext/uncommit.py b/hgext/uncommit.py --- a/hgext/uncommit.py +++ b/hgext/uncommit.py @@ -98,15 +98,13 @@ newid = repo.commitctx(new) return newid -def _uncommitdirstate(repo, oldctx, match): -"""Fix the dirstate after switching the working directory from -oldctx to a copy of oldctx not containing changed files matched by -match. +def _fixdirstate(repo, oldctx, newctx, status): +""" fix the dirstate after switching the working directory from oldctx to +newctx which can be result of either unamend or uncommit. """ -ctx = repo['.'] ds = repo.dirstate copies = dict(ds.copies()) -s = repo.status(oldctx.p1(), oldctx, match=match) +s = status for f in s.modified: if ds[f] == 'r': # modified + removed -> removed @@ -138,7 +136,7 @@ for dst, src in oldcopies.iteritems()) # Adjust the dirstate copies for dst, src in copies.iteritems(): -if (src not in ctx or dst in ctx or ds[dst] != 'a'): +if (src not in newctx or dst in newctx or ds[dst] != 'a'): src = None ds.copy(src, dst) @@ -194,54 +192,14 @@ with repo.dirstate.parentchange(): repo.dirstate.setparents(newid, node.nullid) -_uncommitdirstate(repo, old, match) +s = repo.status(old.p1(), old, match=match) +_fixdirstate(repo, old, repo[newid], s) def predecessormarkers(ctx): """yields the obsolete markers marking the given changeset as a successor""" for data in ctx.repo().obsstore.predecessors.get(ctx.node(), ()): yield obsutil.marker(ctx.repo(), data) -def _unamenddirstate(repo, predctx, curctx): -"" - -s = repo.status(predctx, curctx) -ds = repo.dirstate -copies = dict(ds.copies()) -for f in s.modified: -if ds[f] == 'r': -# modified + removed -> removed -continue -ds.normallookup(f) - -for f in s.added: -if ds[f] == 'r': -# added + removed -> unknown -ds.drop(f) -elif ds[f] != 'a': -ds.add(f) - -for f in s.removed: -if ds[f] == 'a': -# removed + added -> normal -ds.normallookup(f) -elif ds[f] != 'r': -ds.remove(f) - -# Merge old parent and old working dir copies -oldcopies = {} -for f in (s.modified + s.added): -src = curctx[f].renamed() -if src: -oldcopies[f] = src[0] -oldcopies.update(copies) -copies = dict((dst, oldcopies.get(src, src)) - for dst, src in oldcopies.iteritems()) -# Adjust the dirstate copies -for dst, src in copies.iteritems(): -if (src not in predctx or dst in predctx or ds[dst] != 'a'): -src = None -ds.copy(src, dst) - @command('^unamend', []) def unamend(ui, repo, **opts): """undo the amend operation on a current changeset @@ -309,7 +267,8 @@ with dirstate.parentchange(): dirstate.setparents(newprednode, node.nullid) -_unamenddirstate(repo, newpredctx, curctx) +s = repo.status(predctx, curctx) +_fixdirstate(repo, curctx, newpredctx, s) mapping = {curctx.node(): (newprednode,)} scmutil.cleanupnodes(repo, mapping, 'unamend') To: pulkit, #hg-reviewers, mbthomas Cc: mercurial-devel ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
D821: unamend: move fb extension unamend to core
pulkit updated this revision to Diff 3421. REPOSITORY rHG Mercurial CHANGES SINCE LAST UPDATE https://phab.mercurial-scm.org/D821?vs=2493&id=3421 REVISION DETAIL https://phab.mercurial-scm.org/D821 AFFECTED FILES hgext/uncommit.py tests/test-unamend.t CHANGE DETAILS diff --git a/tests/test-unamend.t b/tests/test-unamend.t new file mode 100644 --- /dev/null +++ b/tests/test-unamend.t @@ -0,0 +1,362 @@ +Test for command `hg unamend` which lives in uncommit extension +=== + + $ cat >> $HGRCPATH << EOF + > [alias] + > glog = log -G -T '{rev}:{node|short} {desc}' + > [experimental] + > evolution = createmarkers, allowunstable + > [extensions] + > rebase = + > amend = + > uncommit = + > EOF + +Repo Setup +- + + $ hg init repo + $ cd repo + $ for ch in {a..h}; do touch $ch; echo "foo" >> $ch; hg ci -Aqm "Added "$ch; done + + $ hg glog + @ 7:ec2426147f0e Added h + | + o 6:87d6d6676308 Added g + | + o 5:825660c69f0c Added f + | + o 4:aa98ab95a928 Added e + | + o 3:62615734edd5 Added d + | + o 2:28ad74487de9 Added c + | + o 1:29becc82797a Added b + | + o 0:18d04c59bb5d Added a + + +Trying to unamend when there was no amend done +-- + + $ hg unamend + abort: changeset must have one predecessor, found 0 predecessors + [255] + +Unamend on clean wdir and tip +-- + + $ echo "bar" >> h + $ hg amend + + $ hg exp + # HG changeset patch + # User test + # Date 0 0 + # Thu Jan 01 00:00:00 1970 + + # Node ID c9fa1a715c1b7661c0fafb362a9f30bd75878d7d + # Parent 87d6d66763085b629e6d7ed56778c79827273022 + Added h + + diff -r 87d6d6676308 -r c9fa1a715c1b h + --- /dev/nullThu Jan 01 00:00:00 1970 + + +++ b/h Thu Jan 01 00:00:00 1970 + + @@ -0,0 +1,2 @@ + +foo + +bar + + $ hg glog --hidden + @ 8:c9fa1a715c1b Added h + | + | x 7:ec2426147f0e Added h + |/ + o 6:87d6d6676308 Added g + | + o 5:825660c69f0c Added f + | + o 4:aa98ab95a928 Added e + | + o 3:62615734edd5 Added d + | + o 2:28ad74487de9 Added c + | + o 1:29becc82797a Added b + | + o 0:18d04c59bb5d Added a + + $ hg unamend + $ hg glog --hidden + @ 9:8da14a1fd653 Added h + | + | x 8:c9fa1a715c1b Added h + |/ + | x 7:ec2426147f0e Added h + |/ + o 6:87d6d6676308 Added g + | + o 5:825660c69f0c Added f + | + o 4:aa98ab95a928 Added e + | + o 3:62615734edd5 Added d + | + o 2:28ad74487de9 Added c + | + o 1:29becc82797a Added b + | + o 0:18d04c59bb5d Added a + + $ hg diff + diff -r 8da14a1fd653 h + --- a/h Thu Jan 01 00:00:00 1970 + + +++ b/h Thu Jan 01 00:00:00 1970 + + @@ -1,1 +1,2 @@ + foo + +bar + + $ hg exp + # HG changeset patch + # User test + # Date 0 0 + # Thu Jan 01 00:00:00 1970 + + # Node ID 8da14a1fd653c3f07fdad5760511c9e12652a306 + # Parent 87d6d66763085b629e6d7ed56778c79827273022 + Added h + + diff -r 87d6d6676308 -r 8da14a1fd653 h + --- /dev/nullThu Jan 01 00:00:00 1970 + + +++ b/h Thu Jan 01 00:00:00 1970 + + @@ -0,0 +1,1 @@ + +foo + + $ hg status + M h + + $ hg log -r . -T '{extras % "{extra}\n"}' --config alias.log=log + branch=default + unamend_source=\xc9\xfa\x1aq\\\x1bva\xc0\xfa\xfb6*\x9f0\xbdu\x87\x8d} + +Unamend on a dirty working directory + + + $ hg ci -m "Added bar to h" + $ echo "bar" >> a + $ hg amend + $ echo "foobar" >> a + $ echo "bar" >> b + $ hg status + M a + M b + + $ hg unamend + + $ hg status + M a + M b + + $ hg diff + diff -r 49f03646f7a0 a + --- a/a Thu Jan 01 00:00:00 1970 + + +++ b/a Thu Jan 01 00:00:00 1970 + + @@ -1,1 +1,3 @@ + foo + +bar + +foobar + diff -r 49f03646f7a0 b + --- a/b Thu Jan 01 00:00:00 1970 + + +++ b/b Thu Jan 01 00:00:00 1970 + + @@ -1,1 +1,2 @@ + foo + +bar + +Unamending an added file + + + $ hg ci -m "Added things to a and b" + $ echo foo > bar + $ hg add bar + $ hg amend + + $ hg unamend + $ hg status + A bar + + $ hg revert --all + forgetting bar + +Unamending a removed file +- + + $ hg remove a + $ hg amend + + $ hg unamend + $ hg status + R a + ? bar + + $ hg revert --all + undeleting a + +Unamending an added file with dirty wdir status +--- + + $ hg add bar + $ hg amend + $ echo bar >> bar + $ hg status + M bar + + $ hg unamend + $ hg status + A bar + $ hg diff + diff -r 738d71740456 bar + --- /dev/nullThu Jan 01 00:00:00 1970 + + +++ b/barThu Jan 01 00:00:00 1970 + + @@ -0,0 +1,2 @@ + +foo + +bar + + $ hg revert --all + forgetting bar + +Unamending in middle of a stack +--- + + $ hg glog + @ 19:738d71740456 Added things to a and b + | +
D1348: histedit: add support to output nodechanges using formatter
pulkit updated this revision to Diff 3420. REPOSITORY rHG Mercurial CHANGES SINCE LAST UPDATE https://phab.mercurial-scm.org/D1348?vs=3349&id=3420 REVISION DETAIL https://phab.mercurial-scm.org/D1348 AFFECTED FILES hgext/histedit.py tests/test-histedit-templates.t CHANGE DETAILS diff --git a/tests/test-histedit-templates.t b/tests/test-histedit-templates.t new file mode 100644 --- /dev/null +++ b/tests/test-histedit-templates.t @@ -0,0 +1,54 @@ +Testing templating for histedit command + +Setup + + $ cat >> $HGRCPATH < [extensions] + > histedit= + > [experimental] + > evolution=createmarkers + > EOF + + $ hg init repo + $ cd repo + $ for ch in a b c d; do echo foo > $ch; hg commit -Aqm "Added "$ch; done + + $ hg log -G -T "{rev}:{node|short} {desc}" + @ 3:62615734edd5 Added d + | + o 2:28ad74487de9 Added c + | + o 1:29becc82797a Added b + | + o 0:18d04c59bb5d Added a + +Getting the JSON output for nodechanges + + $ hg histedit -Tjson --commands - 2>&1 < pick 28ad74487de9 Added c + > pick 62615734edd5 Added d + > pick 18d04c59bb5d Added a + > pick 29becc82797a Added b + > EOF + [ + { +"nodechanges": {"18d04c59bb5d2d4090ad9a5b59bd6274adb63add": ["109f8ec895447f81b380ba8d4d8b66539ccdcb94"], "28ad74487de9599d00d81085be739c61fc340652": ["bff9e07c1807942b161dab768aa793b48e9a7f9d"], "29becc82797a4bc11ec8880b58eaecd2ab3e7760": ["f5dcf3b4db23f31f1aacf46c33d1393de303d26f"], "62615734edd52f06b6fb9c2beb429e4fe30d57b8": ["201423b441c84d9e6858daed653e0d22485c1cfa"]} + } + ] + + $ hg log -G -T "{rev}:{node|short} {desc}" + @ 7:f5dcf3b4db23 Added b + | + o 6:109f8ec89544 Added a + | + o 5:201423b441c8 Added d + | + o 4:bff9e07c1807 Added c + + $ hg histedit -T "{nodechanges|json}" --commands - 2>&1 < pick bff9e07c1807 Added c + > pick 201423b441c8 Added d + > pick 109f8ec89544 Added a + > roll f5dcf3b4db23 Added b + > EOF + {"109f8ec895447f81b380ba8d4d8b66539ccdcb94": ["8d01470bfeab64d3de13c49adb79d88790d38396"], "f3ec56a374bdbdf1953cacca505161442c6f3a3e": [], "f5dcf3b4db23f31f1aacf46c33d1393de303d26f": ["8d01470bfeab64d3de13c49adb79d88790d38396"]} (no-eol) diff --git a/hgext/histedit.py b/hgext/histedit.py --- a/hgext/histedit.py +++ b/hgext/histedit.py @@ -917,7 +917,8 @@ ('o', 'outgoing', False, _('changesets not found in destination')), ('f', 'force', False, _('force outgoing even for unrelated repositories')), - ('r', 'rev', [], _('first revision to be edited'), _('REV'))], + ('r', 'rev', [], _('first revision to be edited'), _('REV'))] + + cmdutil.formatteropts, _("[OPTIONS] ([ANCESTOR] | --outgoing [URL])")) def histedit(ui, repo, *freeargs, **opts): """interactively edit changeset history @@ -1095,6 +1096,8 @@ def _histedit(ui, repo, state, *freeargs, **opts): opts = pycompat.byteskwargs(opts) +fm = ui.formatter('histedit', opts) +fm.startitem() goal = _getgoal(opts) revs = opts.get('rev', []) rules = opts.get('commands', '') @@ -1117,7 +1120,8 @@ _newhistedit(ui, repo, state, revs, freeargs, opts) _continuehistedit(ui, repo, state) -_finishhistedit(ui, repo, state) +_finishhistedit(ui, repo, state, fm) +fm.end() def _continuehistedit(ui, repo, state): """This function runs after either: @@ -1164,7 +1168,7 @@ state.write() ui.progress(_("editing"), None) -def _finishhistedit(ui, repo, state): +def _finishhistedit(ui, repo, state, fm): """This action runs when histedit is finishing its session""" repo.ui.pushbuffer() hg.update(repo, state.parentctxnode, quietempty=True) @@ -1198,6 +1202,12 @@ mapping = {k: v for k, v in mapping.items() if k in nodemap and all(n in nodemap for n in v)} scmutil.cleanupnodes(repo, mapping, 'histedit') +hf = fm.hexfunc +fl = fm.formatlist +fd = fm.formatdict +nodechanges = fd({hf(oldn): fl([hf(n) for n in newn], 'succ') + for oldn, newn in mapping.iteritems()}) +fm.data(nodechanges=nodechanges) state.clear() if os.path.exists(repo.sjoin('undo')): To: pulkit, durin42, #hg-reviewers, dlax Cc: dlax, mercurial-devel ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
D1341: dirstate: move management of nonnormal sets into dirstate map
mbthomas added inline comments. INLINE COMMENTS > mbolin wrote in dirstate.py:1247 > I would prefer to see all mutations to `self._map` go through a common code > path so that we can override this behavior easier in Eden. > > As it stands, when this logic is conflated, it makes it much harder for us to > safely subclass `dirstatemap` in Eden. For reference, here's what we're doing > today: > > https://github.com/facebookexperimental/eden-hg/blob/master/eden/hg/eden/eden_dirstate_map.py I think what you want is a common tuple constructor hook point - eden_dirstate_map does build a different tuple, but it just sets it as a property of the map in the same way. I think we want to avoid another layer of indirection if we can. Arguably `dirstatetuple` is already one of these, as it can be either a native tuple type, or the fast C-based one from parses.c, but maybe that's the wrong place for eden to hook as it's global to the module. Instead, we can do it by setting `dirstatemap._tuplecls` to `dirstatetuple` in the constructor, so the code here becomes more like: self._map[f] = self._tuplecls(state, mode, size, mtime) In eden you can make your own function and assign that to `self._tuplecls` in `eden_dirstate_map.__init__`. REPOSITORY rHG Mercurial REVISION DETAIL https://phab.mercurial-scm.org/D1341 To: mbthomas, #hg-reviewers Cc: durin42, mbolin, mercurial-devel ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
D1340: dirstate: add explicit methods for modifying dirstate
mbthomas added inline comments. INLINE COMMENTS > mbolin wrote in dirstate.py:1275 > To avoid doing two lookups in `self._map`: > > try: > self._map.pop(f) > return True > except KeyError: > return False Good idea. I think `return self._map.pop(f, None) is not None` would avoid two lookups and also the exception. This function's going to be getting more complex in later diffs, so I'd like to avoid an exception handler if possible. REPOSITORY rHG Mercurial REVISION DETAIL https://phab.mercurial-scm.org/D1340 To: mbthomas, #hg-reviewers, durin42 Cc: durin42, mbolin, mercurial-devel ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
D1340: dirstate: add explicit methods for modifying dirstate
mbthomas added inline comments. INLINE COMMENTS > durin42 wrote in dirstate.py:1196 > Per my comment above, let's insert a patch before this one that documents in > more detail the API that dirstatemap is supposed to be providing, probably in > a docstring on this class. Sound reasonable? > > (Then the above docstring I complained about could point to this docstring.) Agreed. I removed the docstring above because it became a lie (we no longer implement `__setitem__` or `__delitem__`, so it's not really a dict any more). I will add a docstring here on Monday. REPOSITORY rHG Mercurial REVISION DETAIL https://phab.mercurial-scm.org/D1340 To: mbthomas, #hg-reviewers, durin42 Cc: durin42, mbolin, mercurial-devel ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
[PATCH 2 of 3 hglib] util: make cmdbuilder() robust for faulty parsing of early options
# HG changeset patch # User Yuya Nishihara # Date 1510397568 -32400 # Sat Nov 11 19:52:48 2017 +0900 # Node ID cd73c3ee469e22216fbb9116701eed7059c1833c # Parent 519dfa937de37d1441e2a39da76d700c7099b0c7 util: make cmdbuilder() robust for faulty parsing of early options Also fixed handling of positional arguments. diff --git a/hglib/util.py b/hglib/util.py --- a/hglib/util.py +++ b/hglib/util.py @@ -94,43 +94,50 @@ def cmdbuilder(name, *args, **kwargs): True >>> cmdbuilder(b('cmd'), long=True) == [b('cmd'), b('--long')] True ->>> cmdbuilder(b('cmd'), str=b('s')) == [b('cmd'), b('--str'), b('s')] +>>> cmdbuilder(b('cmd'), s=b('hort')) == [b('cmd'), b('-short')] +True +>>> cmdbuilder(b('cmd'), str=b('s')) == [b('cmd'), b('--str=s')] True >>> cmdbuilder(b('cmd'), d_ash=True) == [b('cmd'), b('--d-ash')] True >>> cmdbuilder(b('cmd'), _=True) == [b('cmd'), b('-')] True ->>> expect = [b('cmd'), b('--list'), b('1'), b('--list'), b('2')] +>>> cmdbuilder(b('cmd'), l=[1, 2]) == [b('cmd'), b('-l1'), b('-l2')] +True +>>> expect = [b('cmd'), b('--list=1'), b('--list=2')] >>> cmdbuilder(b('cmd'), list=[1, 2]) == expect True >>> cmdbuilder(b('cmd'), None) == [b('cmd')] True +>>> cmdbuilder(b('cmd'), b('-a')) == [b('cmd'), b('--'), b('-a')] +True """ cmd = [name] for arg, val in kwargs.items(): if val is None: continue -arg = arg.encode('latin-1').replace(b('_'), b('-')) +arg = pfx = arg.encode('latin-1').replace(b('_'), b('-')) if arg != b('-'): if len(arg) == 1: -arg = b('-') + arg +arg = pfx = b('-') + arg else: arg = b('--') + arg +pfx = arg + b('=') if isinstance(val, bool): if val: cmd.append(arg) elif isinstance(val, list): for v in val: -cmd.append(arg) -cmd.append(_cmdval(v)) +cmd.append(pfx + _cmdval(v)) else: -cmd.append(arg) -cmd.append(_cmdval(val)) +cmd.append(pfx + _cmdval(val)) +args = [a for a in args if a is not None] +if args: +cmd.append(b('--')) for a in args: -if a is not None: -cmd.append(a) +cmd.append(a) return cmd diff --git a/tests/test-log.py b/tests/test-log.py --- a/tests/test-log.py +++ b/tests/test-log.py @@ -20,6 +20,13 @@ class test_log(common.basetest): self.assertEquals(self.client.log(), self.client.log(hidden=True)) +def test_dash_in_filename(self): +self.append('-a', '-a') +self.client.commit(b('first'), addremove=True) +revs = self.client.log(files=[b('-a')]) +self.assertTrue(len(revs) == 1) +self.assertEquals(revs[0].rev, b('0')) + # def test_errors(self): # self.assertRaisesRegexp(CommandError, 'abort: unknown revision', # self.client.log, 'foo') ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
[PATCH 3 of 3 hglib] client: make it robust for weird repository path
# HG changeset patch # User Yuya Nishihara # Date 1510400155 -32400 # Sat Nov 11 20:35:55 2017 +0900 # Node ID 56b442f108be3ef960a60805e10ccda003e96bfb # Parent cd73c3ee469e22216fbb9116701eed7059c1833c client: make it robust for weird repository path diff --git a/hglib/client.py b/hglib/client.py --- a/hglib/client.py +++ b/hglib/client.py @@ -46,8 +46,16 @@ class hgclient(object): self._args = [hglib.HGPATH, 'serve', '--cmdserver', 'pipe', '--config', 'ui.interactive=True'] if path: -self._args += ['-R', path] +# perhaps path shouldn't be a unicode string, but accepted for +# backward compatibility. +if isinstance(path, str): +# py2: bytes + bytes, py3: unicode + unicode +self._args += ['-R' + path] +else: +# py2: (ascii) bytes + unicode, py3: bytes + bytes +self._args += [b('-R') + path] if configs: +# don't use "--config=" form for hg 1.9 compatibility for config in configs: self._args += ['--config', config] self._env = {'HGPLAIN': '1'} ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
[PATCH 1 of 3 hglib] client: do not append an option to a list of arguments
# HG changeset patch # User Yuya Nishihara # Date 1510399286 -32400 # Sat Nov 11 20:21:26 2017 +0900 # Node ID 519dfa937de37d1441e2a39da76d700c7099b0c7 # Parent 5f3e6f1a7e68298e21f893683c5b5d3f634c2c30 client: do not append an option to a list of arguments It wouldn't work if args are terminated with "--". diff --git a/hglib/client.py b/hglib/client.py --- a/hglib/client.py +++ b/hglib/client.py @@ -845,9 +845,8 @@ class hgclient(object): args = cmdbuilder(b('grep'), all=all, a=text, f=follow, i=ignorecase, l=fileswithmatches, n=line, u=user, d=date, - I=include, X=exclude, hidden=self.hidden, + I=include, X=exclude, hidden=self.hidden, print0=True, *[pattern] + files) -args.append(b('-0')) def eh(ret, out, err): if ret != 1: @@ -1129,13 +1128,14 @@ class hgclient(object): """ # we can't really use --preview since merge doesn't support --template -args = cmdbuilder(b('merge'), r=rev, f=force, t=tool) +args = cmdbuilder(b('merge'), r=rev, f=force, t=tool, + y=(cb is merge.handlers.noninteractive)) prompt = None if cb is merge.handlers.abort: prompt = cb elif cb is merge.handlers.noninteractive: -args.append(b('-y')) +pass else: prompt = lambda size, output: cb(output) + b('\n') @@ -1466,9 +1466,7 @@ class hgclient(object): args = cmdbuilder(b('status'), rev=rev, change=change, A=all, m=modified, a=added, r=removed, d=deleted, c=clean, u=unknown, i=ignored, C=copies, S=subrepos, I=include, - X=exclude, hidden=self.hidden) - -args.append(b('-0')) + X=exclude, hidden=self.hidden, print0=True) out = self.rawcommand(args) l = [] ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
Re: [PATCH 2 of 2] tests: use jshint when available to check .js files
LGTM. Anton Shestakov a écrit : # HG changeset patch # User Anton Shestakov # Date 1510384041 -28800 # Sat Nov 11 15:07:21 2017 +0800 # Node ID 42809ebcbc783e0d27385c6ea1e1731df44a4f4e # Parent 36e26161d81233a8ef18e40b4198d86b23113159 tests: use jshint when available to check .js files diff --git a/tests/hghave.py b/tests/hghave.py --- a/tests/hghave.py +++ b/tests/hghave.py @@ -444,6 +444,10 @@ def has_clang_format(): return matchoutput("clang-format --help", br"^OVERVIEW: A tool to format C/C\+\+[^ ]+ code.") +@check("jshint", "JSHint static code analysis tool") +def has_jshint(): +return matchoutput("jshint --version 2>&1", br"jshint v") + @check("pygments", "Pygments source highlighting library") def has_pygments(): try: diff --git a/tests/test-check-jshint.t b/tests/test-check-jshint.t new file mode 100644 --- /dev/null +++ b/tests/test-check-jshint.t @@ -0,0 +1,12 @@ +#require test-repo jshint hg10 + + $ . "$TESTDIR/helpers-testrepo.sh" + +run jshint on all tracked files ending in .js except vendored dependencies + + $ cd "`dirname "$TESTDIR"`" + + $ testrepohg locate 'set:**.js' \ + > -X mercurial/templates/static/excanvas.js \ + > 2>/dev/null \ + > | xargs jshint ___ 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