Re: [PATCH 2 of 2 V2] revset: skip old style lookup if external whitespace are detected
On 11/04/2018 17:16, Yuya Nishihara wrote: On Wed, 11 Apr 2018 11:36:05 +0200, Feld Boris wrote: The proposal here is to define a prefix for which we break backward compatibility. If we do so, people with a "" label will have to use: "":whatever to get a similar effect. IIRC x:y was the most important syntax that needed a strong BC guarantee, so this proposal doesn't sound good. Indeed, the `x:y` is important and we don't want to break the BC guarantee of it. The proposal is less impacting, only people using 'set' as labels and using it at the beginning of a revsetwould be impacted. This prefix has the advantage of being concise and coherent with whatfilesetuse. Doesn't '-r set:foo' look like a range? I don't like an idea of introducing another ambiguous syntax to resolve ambiguity, but furthermore "set:foo" seems confusing to humans. IIUC, we have "set:" for filesets only because that's the syntax to specify file patterns. If we really want to add something to force revset evaluation, I think it has to be compatible with the current syntax, such as "(EXPR)" or "revset(EXPR)". `(EXPR)` seemtoo likely to introduce a BC breakage, as people are more likely to have a tag that looks like `(xxx)` than a 'set' tag IMHO. In a previous discussion, you pointed out that `revset(EXPR)` would be painful because we would have to escape everything within EXPR. What makes you consider it again? Do you mean that if a revset has this form `revset((.*))`; we just evaluate the contents inside parenthesis? Agreed that `set:foo` looks like a range, maybe we need to use a less ambiguous operator? `=foo+bar` `#foo+bar` `#revset# foo+bar` (Nothing really stands out as pretty, but trying to extend our search area here.) Since "foo(bar)" needs quotes in revset query (except for x and x:y), it would makes some sense to add an option to disable the compatibility hack at all. We cannot see a way to make the config option both easily discoverable and constrained. There is lot of labels that includes `-`, `+` and other symbols that will be impacted. sigh. ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
Re: [PATCH 01 of 10] py3: get rid of character access from pure.diffhelpers
On Wed, 11 Apr 2018 22:38:06 +0530, Pulkit Goyal wrote: > On Wed, Apr 11, 2018 at 9:03 PM, Yuya Nishihara wrote: > > > # HG changeset patch > > # User Yuya Nishihara > > # Date 1523274281 -32400 > > # Mon Apr 09 20:44:41 2018 +0900 > > # Node ID da53a21e2b96040ca2005d627b6c69a91e83f938 > > # Parent 8475c9bf096d5f67b3a82de73b27a61ef53018f1 > > py3: get rid of character access from pure.diffhelpers > > > > 's' is a result of readline(), so 'c == "\n"' means 's == "\n"'. > > > > diff --git a/mercurial/pure/diffhelpers.py b/mercurial/pure/diffhelpers.py > > --- a/mercurial/pure/diffhelpers.py > > +++ b/mercurial/pure/diffhelpers.py > > @@ -16,18 +16,17 @@ def addlines(fp, hunk, lena, lenb, a, b) > > break > > for i in xrange(num): > > s = fp.readline() > > -c = s[0] > > if s == "\\ No newline at end of file\n": > > fix_newline(hunk, a, b) > > continue > > -if c == "\n": > > +if s == "\n": > > > > Shouldn't this be `s.startswith("\n")`? No. Here we're testing if s is an empty line. ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
Re: [PATCH 2 of 2 V2] revset: skip old style lookup if external whitespace are detected
On Thu, 12 Apr 2018 11:32:23 +0200, Feld Boris wrote: > On 11/04/2018 17:16, Yuya Nishihara wrote: > > On Wed, 11 Apr 2018 11:36:05 +0200, Feld Boris wrote: > The proposal here is to define a prefix for which we break backward > compatibility. If we do so, people with a "" label will have to use: > > "":whatever > > to get a similar effect. > >>> IIRC x:y was the most important syntax that needed a strong BC guarantee, > >>> so > >>> this proposal doesn't sound good. > >> Indeed, the `x:y` is important and we don't want to break the BC > >> guarantee of it. > >> > >> The proposal is less impacting, only people using 'set' as labels and > >> using it at the beginning of a revsetwould be impacted. This prefix has > >> the advantage of being concise and coherent with whatfilesetuse. > > Doesn't '-r set:foo' look like a range? > > > > I don't like an idea of introducing another ambiguous syntax to resolve > > ambiguity, but furthermore "set:foo" seems confusing to humans. > > > > IIUC, we have "set:" for filesets only because that's the syntax to specify > > file patterns. If we really want to add something to force revset > > evaluation, > > I think it has to be compatible with the current syntax, such as "(EXPR)" or > > "revset(EXPR)". > > `(EXPR)` seemtoo likely to introduce a BC breakage, as people are more > likely to have a tag that looks like `(xxx)` than a 'set' tag IMHO. Ugh, I never assumed that would actually happen, but since you face to more real users having various backgrounds than me, I might be wrong. > In a previous discussion, you pointed out that `revset(EXPR)` would be > painful because we would have to escape everything within EXPR. What > makes you consider it again? Do you mean that if a revset has this form > `revset((.*))`; we just evaluate the contents inside parenthesis? My proposal is 'revset(EXPR)', not 'revset("EXPR")'. It's an identity function similar to present(), but also disables the legacy lookup. I don't wanna add such magic, but 'revset(EXPR)' seems less bad than 'set:EXPR' or ' EXPR'. > Agreed that `set:foo` looks like a range, maybe we need to use a less > ambiguous operator? > > `=foo+bar` > `#foo+bar` > `#revset# foo+bar` > > (Nothing really stands out as pretty, but trying to extend our search > area here.) Yeah, they look weird. FWIW, I prefer not reviewing this sort of patches just before the freeze. The patch itself is simple, but we have to carefully think about UX and syntactic consistency. ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
Re: [PATCH 1 of 4 V3] lfs: special case the null:// usercache instead of treating it as a url
On Wed, 11 Apr 2018 19:31:42 -0400, Matt Harbison wrote: > # HG changeset patch > # User Matt Harbison > # Date 1523482195 14400 > # Wed Apr 11 17:29:55 2018 -0400 > # Node ID 11de91e25707a7acb2052fe87fe7aacde88b65ca > # Parent 8478b198af9cb96463582be895f0b9a06747a13c > lfs: special case the null:// usercache instead of treating it as a url Queued, thanks. ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
D3212: patch: implement a new worddiff algorithm
yuja added a comment. > Note the color configs are not entirely equivalent to the old code. I know. It would be roughly equivalent to the old code of `sim >= 0.0`. > Therefore I still think it's reasonable to avoid using "bold" in this patch to avoid noisy outputs. I agree on that, but the default output has to be somewhat distinguishable even if "dim" isn't supported. REPOSITORY rHG Mercurial REVISION DETAIL https://phab.mercurial-scm.org/D3212 To: quark, #hg-reviewers, durin42, yuja Cc: indygreg, dhduvall, yuja, spectral, mercurial-devel ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
D3210: patch: move yielding "\n" to the end of loop
yuja added a comment. `rawline` can be removed after the rewrite of +/- lines handling. -for rawline in mdiff.splitnewlines(chunk): -line = rawline.rstrip('\n') +for line in mdiff.splitnewlines(chunk): if head: if line.startswith('@'): head = False else: -if line and not line.startswith((' ', '+', '-', '@', '\\')): +if not line.startswith((' ', '+', '-', '@', '\\', '\n')): head = True @@ -2525,13 +2523,15 @@ def difflabel(func, *args, **kw): if head: prefixes = headprefixes for prefix, label in prefixes: -if stripline.startswith(prefix): -yield (stripline, label) +if line.startswith(prefix): +if line.endswith('\n'): +yield (line[:-1], label) +yield ('\n', '') +else: +yield (line, label) break else: yield (line, '') -if rawline != line: -yield (rawline[len(line):], '') REPOSITORY rHG Mercurial REVISION DETAIL https://phab.mercurial-scm.org/D3210 To: quark, #hg-reviewers Cc: yuja, mercurial-devel ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
D3274: py3: make sure we open file in bytes mode
pulkit 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/D3274 AFFECTED FILES mercurial/sparse.py CHANGE DETAILS diff --git a/mercurial/sparse.py b/mercurial/sparse.py --- a/mercurial/sparse.py +++ b/mercurial/sparse.py @@ -579,7 +579,7 @@ # part of the active rules. changed = False for p in paths: -with util.posixfile(util.expandpath(p)) as fh: +with util.posixfile(util.expandpath(p), mode='rb') as fh: raw = fh.read() iincludes, iexcludes, iprofiles = parseconfig(repo.ui, raw) 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
D3275: py3: use pycompat.{strkwargs|byteskwargs} in infinitepush
pulkit 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/D3275 AFFECTED FILES hgext/infinitepush/__init__.py CHANGE DETAILS diff --git a/hgext/infinitepush/__init__.py b/hgext/infinitepush/__init__.py --- a/hgext/infinitepush/__init__.py +++ b/hgext/infinitepush/__init__.py @@ -123,6 +123,7 @@ peer, phases, pushkey, +pycompat, registrar, util, wireproto, @@ -579,6 +580,7 @@ return _lookup def _pull(orig, ui, repo, source="default", **opts): +opts = pycompat.byteskwargs(opts) # Copy paste from `pull` command source, branches = hg.parseurl(ui.expandpath(source), opts.get('branch')) @@ -620,7 +622,7 @@ # Remote scratch bookmarks will be deleted because remotenames doesn't # know about them. Let's save it before pull and restore after remotescratchbookmarks = _readscratchremotebookmarks(ui, repo, source) -result = orig(ui, repo, source, **opts) +result = orig(ui, repo, source, **pycompat.strkwargs(opts)) # TODO(stash): race condition is possible # if scratch bookmarks was updated right after orig. # But that's unlikely and shouldn't be harmful. 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
D3277: py3: use '%d' for integers instead of '%s'
pulkit 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/D3277 AFFECTED FILES hgext/convert/git.py hgext/convert/hg.py hgext/infinitepush/__init__.py mercurial/hg.py CHANGE DETAILS diff --git a/mercurial/hg.py b/mercurial/hg.py --- a/mercurial/hg.py +++ b/mercurial/hg.py @@ -1021,7 +1021,7 @@ ret = (ctx.sub(subpath, allowcreate=False).verify() or ret) except error.RepoError as e: -repo.ui.warn(('%s: %s\n') % (rev, e)) +repo.ui.warn(('%d: %s\n') % (rev, e)) except Exception: repo.ui.warn(_('.hgsubstate is corrupt in revision %s\n') % node.short(ctx.node())) diff --git a/hgext/infinitepush/__init__.py b/hgext/infinitepush/__init__.py --- a/hgext/infinitepush/__init__.py +++ b/hgext/infinitepush/__init__.py @@ -1042,7 +1042,7 @@ # Notify the user of what is being pushed plural = 's' if len(revs) > 1 else '' -op.repo.ui.warn(_("pushing %s commit%s:\n") % (len(revs), plural)) +op.repo.ui.warn(_("pushing %d commit%s:\n") % (len(revs), plural)) maxoutput = 10 for i in range(0, min(len(revs), maxoutput)): firstline = bundle[revs[i]].description().split('\n')[0][:50] diff --git a/hgext/convert/hg.py b/hgext/convert/hg.py --- a/hgext/convert/hg.py +++ b/hgext/convert/hg.py @@ -401,7 +401,7 @@ return context.memfilectx(repo, memctx, f, data, False, False, None) self.ui.status(_("updating tags\n")) -date = "%s 0" % int(time.mktime(time.gmtime())) +date = "%d 0" % int(time.mktime(time.gmtime())) extra = {'branch': self.tagsbranch} ctx = context.memctx(self.repo, (tagparent, None), "update tags", [".hgtags"], getfilectx, "convert-repo", date, diff --git a/hgext/convert/git.py b/hgext/convert/git.py --- a/hgext/convert/git.py +++ b/hgext/convert/git.py @@ -435,7 +435,7 @@ else: output, status = self.gitrunlines('diff-tree', '--name-only', '--root', '-r', version, - '%s^%s' % (version, i + 1), '--') + '%s^%d' % (version, i + 1), '--') if status: raise error.Abort(_('cannot read changes in %s') % version) changes = [f.rstrip('\n') for f in output] 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
D3276: py3: prevent transformer from adding b'' by adding r'' prefix
pulkit created this revision. Herald added a subscriber: mercurial-devel. Herald added a reviewer: hg-reviewers. REVISION SUMMARY These are cases where we need to use str, therefore we add r'' prefix. 1. skip-blame because just r'' prefixes REPOSITORY rHG Mercurial REVISION DETAIL https://phab.mercurial-scm.org/D3276 AFFECTED FILES hgext/infinitepush/__init__.py mercurial/subrepo.py CHANGE DETAILS diff --git a/mercurial/subrepo.py b/mercurial/subrepo.py --- a/mercurial/subrepo.py +++ b/mercurial/subrepo.py @@ -1637,7 +1637,7 @@ # This should be much faster than manually traversing the trees # and objects with many subprocess calls. tarstream = self._gitcommand(['archive', revision], stream=True) -tar = tarfile.open(fileobj=tarstream, mode='r|') +tar = tarfile.open(fileobj=tarstream, mode=r'r|') relpath = subrelpath(self) self.ui.progress(_('archiving (%s)') % relpath, 0, unit=_('files')) for i, info in enumerate(tar): diff --git a/hgext/infinitepush/__init__.py b/hgext/infinitepush/__init__.py --- a/hgext/infinitepush/__init__.py +++ b/hgext/infinitepush/__init__.py @@ -697,7 +697,7 @@ def _push(orig, ui, repo, dest=None, *args, **opts): -bookmark = opts.get('bookmark') +bookmark = opts.get(r'bookmark') # we only support pushing one infinitepush bookmark at once if len(bookmark) == 1: bookmark = bookmark[0] @@ -718,7 +718,7 @@ if scratchpush: # this is an infinitepush, we don't want the bookmark to be applied # rather that should be stored in the bundlestore -opts['bookmark'] = [] +opts[r'bookmark'] = [] ui.setconfig(experimental, configscratchpush, True) oldphasemove = extensions.wrapfunction(exchange, '_localphasemove', @@ -914,7 +914,7 @@ fd, bundlefile = tempfile.mkstemp() try: try: -fp = os.fdopen(fd, 'wb') +fp = os.fdopen(fd, r'wb') fp.write(buf.read()) finally: fp.close() @@ -1000,7 +1000,7 @@ fd, bundlefile = tempfile.mkstemp() try: try: -fp = os.fdopen(fd, 'wb') +fp = os.fdopen(fd, r'wb') fp.write(buf.read()) finally: fp.close() @@ -1112,7 +1112,7 @@ fd, bundlefile = tempfile.mkstemp() try: try: -fp = os.fdopen(fd, 'wb') +fp = os.fdopen(fd, r'wb') fp.write(buf.read()) finally: fp.close() 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
D3278: py3: use print as a function in test-convert-git.t
pulkit 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/D3278 AFFECTED FILES tests/test-convert-git.t CHANGE DETAILS diff --git a/tests/test-convert-git.t b/tests/test-convert-git.t --- a/tests/test-convert-git.t +++ b/tests/test-convert-git.t @@ -437,7 +437,7 @@ $ cd git-repo3-hg $ hg up -C 1 files updated, 0 files merged, 0 files removed, 0 files unresolved - $ $PYTHON -c 'print len(open("b", "rb").read())' + $ $PYTHON -c 'from __future__ import print_function; print(len(open("b", "rb").read()))' 4096 $ cd .. 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
D3279: py3: make sure decode() first argument is str
pulkit created this revision. Herald added a subscriber: mercurial-devel. Herald added a reviewer: hg-reviewers. REVISION SUMMARY Uses pycompat.sysstr() to make sure we uses bytes on Python 2 and unicodes on Python 3. REPOSITORY rHG Mercurial REVISION DETAIL https://phab.mercurial-scm.org/D3279 AFFECTED FILES hgext/convert/common.py CHANGE DETAILS diff --git a/hgext/convert/common.py b/hgext/convert/common.py --- a/hgext/convert/common.py +++ b/hgext/convert/common.py @@ -217,12 +217,13 @@ if isinstance(s, unicode): return s.encode("utf-8") try: -return s.decode(encoding).encode("utf-8") +return s.decode(pycompat.sysstr(encoding)).encode("utf-8") except UnicodeError: try: return s.decode("latin-1").encode("utf-8") except UnicodeError: -return s.decode(encoding, "replace").encode("utf-8") +return s.decode(pycompat.sysstr(encoding), +"replace").encode("utf-8") def getchangedfiles(self, rev, i): """Return the files changed by rev compared to parent[i]. 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
D3281: py3: add b'' prefix to make the regex bytes
pulkit created this revision. Herald added a subscriber: mercurial-devel. Herald added a reviewer: hg-reviewers. REVISION SUMMARY 1. skip-blame because just b'' prefix REPOSITORY rHG Mercurial REVISION DETAIL https://phab.mercurial-scm.org/D3281 AFFECTED FILES hgext/convert/common.py CHANGE DETAILS diff --git a/hgext/convert/common.py b/hgext/convert/common.py --- a/hgext/convert/common.py +++ b/hgext/convert/common.py @@ -144,7 +144,7 @@ """ fails if revstr is not a 40 byte hex. mercurial and git both uses such format for their revision numbering """ -if not re.match(r'[0-9a-fA-F]{40,40}$', revstr): +if not re.match(br'[0-9a-fA-F]{40,40}$', revstr): raise error.Abort(_('%s entry %s is not a valid revision' ' identifier') % (mapname, revstr)) 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
D3282: py3: add b'' prefixes in tests/test-linerange.py
pulkit created this revision. Herald added a subscriber: mercurial-devel. Herald added a reviewer: hg-reviewers. REVISION SUMMARY This makes the test pass on Python 3. 1. skip-blame because just b'' prefixes REPOSITORY rHG Mercurial REVISION DETAIL https://phab.mercurial-scm.org/D3282 AFFECTED FILES tests/test-linerange.py CHANGE DETAILS diff --git a/tests/test-linerange.py b/tests/test-linerange.py --- a/tests/test-linerange.py +++ b/tests/test-linerange.py @@ -4,7 +4,7 @@ from mercurial import error, mdiff # for readability, line numbers are 0-origin -text1 = ''' +text1 = b''' 00 at OLD 01 at OLD 02 at OLD @@ -19,7 +19,7 @@ 11 at OLD '''[1:] # strip initial LF -text2 = ''' +text2 = b''' 00 at NEW 01 at NEW 02 at NEW, 03 at OLD @@ -47,10 +47,10 @@ def setUp(self): self.blocks = list(mdiff.allblocks(text1, text2)) assert self.blocks == [ -([0, 3, 0, 2], '!'), -((3, 7, 2, 6), '='), -([7, 12, 6, 12], '!'), -((12, 12, 12, 12), '='), +([0, 3, 0, 2], b'!'), +((3, 7, 2, 6), b'='), +([7, 12, 6, 12], b'!'), +((12, 12, 12, 12), b'='), ], self.blocks def testWithinEqual(self): 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
D3283: py3: suppress the return value of open() in tests/test-subrepo-missing.t
pulkit created this revision. Herald added a subscriber: mercurial-devel. Herald added a reviewer: hg-reviewers. REVISION SUMMARY open() on Python 3 returns a value whereas does not return anything on Python 2. So we need to supress the value. REPOSITORY rHG Mercurial REVISION DETAIL https://phab.mercurial-scm.org/D3283 AFFECTED FILES tests/test-subrepo-missing.t CHANGE DETAILS diff --git a/tests/test-subrepo-missing.t b/tests/test-subrepo-missing.t --- a/tests/test-subrepo-missing.t +++ b/tests/test-subrepo-missing.t @@ -14,15 +14,15 @@ ignore blanklines in .hgsubstate - >>> open('.hgsubstate', 'wb').write(b'\n\n \t \n \n') + >>> open('.hgsubstate', 'wb').write(b'\n\n \t \n \n') and None $ hg st --subrepos M .hgsubstate $ hg revert -qC .hgsubstate abort more gracefully on .hgsubstate parsing error $ cp .hgsubstate .hgsubstate.old - >>> open('.hgsubstate', 'wb').write(b'\ninvalid') + >>> open('.hgsubstate', 'wb').write(b'\ninvalid') and None $ hg st --subrepos --cwd $TESTTMP -R $TESTTMP/repo abort: invalid subrepository revision specifier in 'repo/.hgsubstate' line 2 [255] 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
D3280: py3: use b'%d' to convert int to bytes instead of str()
pulkit 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/D3280 AFFECTED FILES hgext/convert/git.py CHANGE DETAILS diff --git a/hgext/convert/git.py b/hgext/convert/git.py --- a/hgext/convert/git.py +++ b/hgext/convert/git.py @@ -372,7 +372,7 @@ tzs, tzh, tzm = tz[-5:-4] + "1", tz[-4:-2], tz[-2:] tz = -int(tzs) * (int(tzh) * 3600 + int(tzm)) -date = tm + " " + str(tz) +date = tm + " " + (b"%d" % tz) saverev = self.ui.configbool('convert', 'git.saverev') c = common.commit(parents=parents, date=date, author=author, 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
D3284: py3: use stringutil.forcebytestr() to convert error messages to bytes
pulkit 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/D3284 AFFECTED FILES mercurial/subrepoutil.py CHANGE DETAILS diff --git a/mercurial/subrepoutil.py b/mercurial/subrepoutil.py --- a/mercurial/subrepoutil.py +++ b/mercurial/subrepoutil.py @@ -86,7 +86,8 @@ src = re.sub(pattern, repl, src, 1) except re.error as e: raise error.Abort(_("bad subrepository pattern in %s: %s") - % (p.source('subpaths', pattern), e)) + % (p.source('subpaths', pattern), +stringutil.forcebytestr(e))) return src state = {} 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
D3285: py3: use bytes() instead of str() on util.url()
pulkit created this revision. Herald added a subscriber: mercurial-devel. Herald added a reviewer: hg-reviewers. REVISION SUMMARY We internally deal with bytes and anything as string breaks things. REPOSITORY rHG Mercurial REVISION DETAIL https://phab.mercurial-scm.org/D3285 AFFECTED FILES mercurial/subrepoutil.py CHANGE DETAILS diff --git a/mercurial/subrepoutil.py b/mercurial/subrepoutil.py --- a/mercurial/subrepoutil.py +++ b/mercurial/subrepoutil.py @@ -106,7 +106,7 @@ parent = util.url(parent) parent.path = posixpath.join(parent.path or '', src) parent.path = posixpath.normpath(parent.path) -joined = str(parent) +joined = bytes(parent) # Remap the full joined path and use it if it changes, # else remap the original source. remapped = remap(joined) 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
D3212: patch: implement a new worddiff algorithm
dhduvall added inline comments. INLINE COMMENTS > quark wrote in color.py:94 > There are not many choices - dim, 16/256 colors, or bold. We ended up with > 16/256 colors internally for wider support (ex. tmux). But I'd like to > express my (strong) options that: > > - diff.inserted.changed and diff.inserted are same > - diff.inserted is not bold > > in this patch. Because color.py has no 16/256 support yet (and if it does > detection conservatively, most terminals will only report 8 color support). > And the only remaining choice is "dim". For weird terminals like tmux, I > think it's their bugs to fix, not this patch. > > That said, I'm fine with changing the defaults to whatever. So feel free to > send follow-ups changing it. I'm not sure what testing I did to claim "most", but I did make that comment in 2011, and xterm didn't start supporting dim until 2014 (it had long supported invisible), so that certainly helped inform that comment. Given @spectral's survey, I'd probably rewrite the comment simply to say that we're using `ui.debug()` to not be noisy in the wide world of different terminals. Given support by xterm, iTerm2, and Terminal.app (and I just verified gnome-terminal supports it, too), I'd lean towards just using dim whenever it made sense now, though it'd be nice to know that at least one major Windows terminal app supported it, too. I don't know how widespread rxvt-unicode is in the Linux world, or other terminal emulators that might not support it. I won't comment on the dim-the-unchanged vs bright-the-changed bits, or how this interacts with the ANSI color mode, other than to say that the default colors aren't an interface, and can be tweaked later without worries about backwards compatibility. Obviously you don't want to change them radically without good reason once people get used to them, but tweaking dim/bold/normal/background/whatever once people have had a chance to experiment more widely might be a reasonable thing to do. REPOSITORY rHG Mercurial REVISION DETAIL https://phab.mercurial-scm.org/D3212 To: quark, #hg-reviewers, durin42, yuja Cc: indygreg, dhduvall, yuja, spectral, mercurial-devel ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
Re: [PATCH 01 of 10] py3: get rid of character access from pure.diffhelpers
On Wed, Apr 11, 2018 at 9:03 PM, Yuya Nishihara wrote: > # HG changeset patch > # User Yuya Nishihara > # Date 1523274281 -32400 > # Mon Apr 09 20:44:41 2018 +0900 > # Node ID da53a21e2b96040ca2005d627b6c69a91e83f938 > # Parent 8475c9bf096d5f67b3a82de73b27a61ef53018f1 > py3: get rid of character access from pure.diffhelpers > > 's' is a result of readline(), so 'c == "\n"' means 's == "\n"'. > Queued the series, many thanks! ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
[Bug 5838] New: Interrupted rebase recovery instructions are wrong
https://bz.mercurial-scm.org/show_bug.cgi?id=5838 Bug ID: 5838 Summary: Interrupted rebase recovery instructions are wrong Product: Mercurial Version: 4.5.2 Hardware: All OS: All Status: UNCONFIRMED Severity: bug Priority: wish Component: rebase Assignee: bugzi...@mercurial-scm.org Reporter: matt_harbi...@yahoo.com CC: mercurial-devel@mercurial-scm.org I hit this on Windows a few weeks ago in the hg repo, when rebase aborted because a file was open. The transcript below is from Linux with a rebase that aborted because a subrepo wasn't available. # The parent repo is fully present, but the subrepo revision used in tip is not. # For whatever reason, the *.local style hostnames aren't working on this system # now, and that's what is in paths.default. $ hg rebase -b . -d tip rebasing 19929:ff68cd4fe339 "..." abort: error: Name or service not known # Oops. Override the path and try again. $ hg rebase -b . -d tip --config paths.default=http://matt7h-pc:8000 abort: last update was interrupted (use 'hg update' to get a consistent checkout) # No flavor of update does anything useful. $ hg up . abort: rebase in progress (use 'hg rebase --continue' or 'hg rebase --abort') $ hg up -C . abort: rebase in progress (use 'hg rebase --continue' or 'hg rebase --abort') $ hg version Mercurial Distributed SCM (version 4.5.2+2-9639c433be54) (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
D3175: commands: implement `export --format=X` with support for CBOR
yuja requested changes to this revision. yuja added a comment. This revision now requires changes to proceed. OK, `hg export -Tjson` appears mostly working. Perhaps we can add cborfromatter for `-Tcbor`. REPOSITORY rHG Mercurial REVISION DETAIL https://phab.mercurial-scm.org/D3175 To: indygreg, #hg-reviewers, yuja Cc: yuja, durin42, mercurial-devel ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
D3247: tests: load showstack in test-pull-http.t so network hangs are easier to find
mharbison72 added a comment. It doesn't load on Windows: $ ../hg id --config extensions.showstack=../contrib/showstack.py --config extensions.evolve=! Traceback (most recent call last): File "e:\Projects\hg\mercurial\extensions.py", line 215, in _runextsetup extsetup(ui) File "../contrib/showstack.py", line 18, in extsetup signal.signal(signal.SIGQUIT, sigshow) AttributeError: 'module' object has no attribute 'SIGQUIT' *** failed to set up extension showstack: 'module' object has no attribute 'SIGQUIT' REPOSITORY rHG Mercurial REVISION DETAIL https://phab.mercurial-scm.org/D3247 To: durin42, #hg-reviewers Cc: mharbison72, mercurial-devel ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
D3247: tests: load showstack in test-pull-http.t so network hangs are easier to find
durin42 updated this revision to Diff 8053. durin42 edited the summary of this revision. REPOSITORY rHG Mercurial CHANGES SINCE LAST UPDATE https://phab.mercurial-scm.org/D3247?vs=8011&id=8053 REVISION DETAIL https://phab.mercurial-scm.org/D3247 AFFECTED FILES tests/test-pull-http.t CHANGE DETAILS diff --git a/tests/test-pull-http.t b/tests/test-pull-http.t --- a/tests/test-pull-http.t +++ b/tests/test-pull-http.t @@ -1,5 +1,16 @@ #require killdaemons +#if no-windows +For debugging: this is a pretty simple test that is a good candidate +for tracking down network-related bugs. Sometimes a command in this +hangs, so having showstack pre-loaded is sometimes helpful. This also +gives us a test that at least proves showstack can be loaded. + $ cat >> $HGRCPATH < [extensions] + > showstack = $TESTDIR/../contrib/showstack.py + > EOF +#endif + $ hg init test $ cd test $ echo a > a To: durin42, #hg-reviewers Cc: mharbison72, mercurial-devel ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
D3247: tests: load showstack in test-pull-http.t so network hangs are easier to find
durin42 added a comment. In https://phab.mercurial-scm.org/D3247#52450, @mharbison72 wrote: > It doesn't load on Windows: > > $ ../hg id --config extensions.showstack=../contrib/showstack.py --config extensions.evolve=! > Traceback (most recent call last): > File "e:\Projects\hg\mercurial\extensions.py", line 215, in _runextsetup > extsetup(ui) > File "../contrib/showstack.py", line 18, in extsetup > signal.signal(signal.SIGQUIT, sigshow) > AttributeError: 'module' object has no attribute 'SIGQUIT' > *** failed to set up extension showstack: 'module' object has no attribute 'SIGQUIT' > I should have known. Now guarded by a no-windows. REPOSITORY rHG Mercurial REVISION DETAIL https://phab.mercurial-scm.org/D3247 To: durin42, #hg-reviewers Cc: mharbison72, mercurial-devel ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
D3276: py3: prevent transformer from adding b'' by adding r'' prefix
This revision was automatically updated to reflect the committed changes. Closed by commit rHG56df2ca5c032: py3: prevent transformer from adding b'' by adding r'' prefix (authored by pulkit, committed by ). REPOSITORY rHG Mercurial CHANGES SINCE LAST UPDATE https://phab.mercurial-scm.org/D3276?vs=8043&id=8056 REVISION DETAIL https://phab.mercurial-scm.org/D3276 AFFECTED FILES hgext/infinitepush/__init__.py mercurial/subrepo.py CHANGE DETAILS diff --git a/mercurial/subrepo.py b/mercurial/subrepo.py --- a/mercurial/subrepo.py +++ b/mercurial/subrepo.py @@ -1637,7 +1637,7 @@ # This should be much faster than manually traversing the trees # and objects with many subprocess calls. tarstream = self._gitcommand(['archive', revision], stream=True) -tar = tarfile.open(fileobj=tarstream, mode='r|') +tar = tarfile.open(fileobj=tarstream, mode=r'r|') relpath = subrelpath(self) self.ui.progress(_('archiving (%s)') % relpath, 0, unit=_('files')) for i, info in enumerate(tar): diff --git a/hgext/infinitepush/__init__.py b/hgext/infinitepush/__init__.py --- a/hgext/infinitepush/__init__.py +++ b/hgext/infinitepush/__init__.py @@ -697,7 +697,7 @@ def _push(orig, ui, repo, dest=None, *args, **opts): -bookmark = opts.get('bookmark') +bookmark = opts.get(r'bookmark') # we only support pushing one infinitepush bookmark at once if len(bookmark) == 1: bookmark = bookmark[0] @@ -718,7 +718,7 @@ if scratchpush: # this is an infinitepush, we don't want the bookmark to be applied # rather that should be stored in the bundlestore -opts['bookmark'] = [] +opts[r'bookmark'] = [] ui.setconfig(experimental, configscratchpush, True) oldphasemove = extensions.wrapfunction(exchange, '_localphasemove', @@ -914,7 +914,7 @@ fd, bundlefile = tempfile.mkstemp() try: try: -fp = os.fdopen(fd, 'wb') +fp = os.fdopen(fd, r'wb') fp.write(buf.read()) finally: fp.close() @@ -1000,7 +1000,7 @@ fd, bundlefile = tempfile.mkstemp() try: try: -fp = os.fdopen(fd, 'wb') +fp = os.fdopen(fd, r'wb') fp.write(buf.read()) finally: fp.close() @@ -1112,7 +1112,7 @@ fd, bundlefile = tempfile.mkstemp() try: try: -fp = os.fdopen(fd, 'wb') +fp = os.fdopen(fd, r'wb') fp.write(buf.read()) finally: fp.close() To: pulkit, #hg-reviewers, indygreg Cc: mercurial-devel ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
D3278: py3: use print as a function in test-convert-git.t
This revision was automatically updated to reflect the committed changes. Closed by commit rHG1c3c9211a40e: py3: use print as a function in test-convert-git.t (authored by pulkit, committed by ). REPOSITORY rHG Mercurial CHANGES SINCE LAST UPDATE https://phab.mercurial-scm.org/D3278?vs=8045&id=8057 REVISION DETAIL https://phab.mercurial-scm.org/D3278 AFFECTED FILES tests/test-convert-git.t CHANGE DETAILS diff --git a/tests/test-convert-git.t b/tests/test-convert-git.t --- a/tests/test-convert-git.t +++ b/tests/test-convert-git.t @@ -437,7 +437,7 @@ $ cd git-repo3-hg $ hg up -C 1 files updated, 0 files merged, 0 files removed, 0 files unresolved - $ $PYTHON -c 'print len(open("b", "rb").read())' + $ $PYTHON -c 'from __future__ import print_function; print(len(open("b", "rb").read()))' 4096 $ cd .. To: pulkit, #hg-reviewers, indygreg Cc: mercurial-devel ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
D3274: py3: make sure we open file in bytes mode
This revision was automatically updated to reflect the committed changes. Closed by commit rHG6ef94f24aa82: py3: make sure we open file in bytes mode (authored by pulkit, committed by ). REPOSITORY rHG Mercurial CHANGES SINCE LAST UPDATE https://phab.mercurial-scm.org/D3274?vs=8041&id=8054 REVISION DETAIL https://phab.mercurial-scm.org/D3274 AFFECTED FILES mercurial/sparse.py CHANGE DETAILS diff --git a/mercurial/sparse.py b/mercurial/sparse.py --- a/mercurial/sparse.py +++ b/mercurial/sparse.py @@ -579,7 +579,7 @@ # part of the active rules. changed = False for p in paths: -with util.posixfile(util.expandpath(p)) as fh: +with util.posixfile(util.expandpath(p), mode='rb') as fh: raw = fh.read() iincludes, iexcludes, iprofiles = parseconfig(repo.ui, raw) To: pulkit, #hg-reviewers, indygreg Cc: mercurial-devel ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
D3275: py3: use pycompat.{strkwargs|byteskwargs} in infinitepush
This revision was automatically updated to reflect the committed changes. Closed by commit rHGe7eea8582afa: py3: use pycompat.{strkwargs|byteskwargs} in infinitepush (authored by pulkit, committed by ). REPOSITORY rHG Mercurial CHANGES SINCE LAST UPDATE https://phab.mercurial-scm.org/D3275?vs=8042&id=8055 REVISION DETAIL https://phab.mercurial-scm.org/D3275 AFFECTED FILES hgext/infinitepush/__init__.py CHANGE DETAILS diff --git a/hgext/infinitepush/__init__.py b/hgext/infinitepush/__init__.py --- a/hgext/infinitepush/__init__.py +++ b/hgext/infinitepush/__init__.py @@ -123,6 +123,7 @@ peer, phases, pushkey, +pycompat, registrar, util, wireproto, @@ -579,6 +580,7 @@ return _lookup def _pull(orig, ui, repo, source="default", **opts): +opts = pycompat.byteskwargs(opts) # Copy paste from `pull` command source, branches = hg.parseurl(ui.expandpath(source), opts.get('branch')) @@ -620,7 +622,7 @@ # Remote scratch bookmarks will be deleted because remotenames doesn't # know about them. Let's save it before pull and restore after remotescratchbookmarks = _readscratchremotebookmarks(ui, repo, source) -result = orig(ui, repo, source, **opts) +result = orig(ui, repo, source, **pycompat.strkwargs(opts)) # TODO(stash): race condition is possible # if scratch bookmarks was updated right after orig. # But that's unlikely and shouldn't be harmful. To: pulkit, #hg-reviewers, indygreg Cc: mercurial-devel ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
D3277: py3: use '%d' for integers instead of '%s'
This revision was automatically updated to reflect the committed changes. Closed by commit rHGce566e0f73d0: py3: use '%d' for integers instead of '%s' (authored by pulkit, committed by ). REPOSITORY rHG Mercurial CHANGES SINCE LAST UPDATE https://phab.mercurial-scm.org/D3277?vs=8044&id=8058 REVISION DETAIL https://phab.mercurial-scm.org/D3277 AFFECTED FILES hgext/convert/git.py hgext/convert/hg.py hgext/infinitepush/__init__.py mercurial/hg.py CHANGE DETAILS diff --git a/mercurial/hg.py b/mercurial/hg.py --- a/mercurial/hg.py +++ b/mercurial/hg.py @@ -1021,7 +1021,7 @@ ret = (ctx.sub(subpath, allowcreate=False).verify() or ret) except error.RepoError as e: -repo.ui.warn(('%s: %s\n') % (rev, e)) +repo.ui.warn(('%d: %s\n') % (rev, e)) except Exception: repo.ui.warn(_('.hgsubstate is corrupt in revision %s\n') % node.short(ctx.node())) diff --git a/hgext/infinitepush/__init__.py b/hgext/infinitepush/__init__.py --- a/hgext/infinitepush/__init__.py +++ b/hgext/infinitepush/__init__.py @@ -1042,7 +1042,7 @@ # Notify the user of what is being pushed plural = 's' if len(revs) > 1 else '' -op.repo.ui.warn(_("pushing %s commit%s:\n") % (len(revs), plural)) +op.repo.ui.warn(_("pushing %d commit%s:\n") % (len(revs), plural)) maxoutput = 10 for i in range(0, min(len(revs), maxoutput)): firstline = bundle[revs[i]].description().split('\n')[0][:50] diff --git a/hgext/convert/hg.py b/hgext/convert/hg.py --- a/hgext/convert/hg.py +++ b/hgext/convert/hg.py @@ -401,7 +401,7 @@ return context.memfilectx(repo, memctx, f, data, False, False, None) self.ui.status(_("updating tags\n")) -date = "%s 0" % int(time.mktime(time.gmtime())) +date = "%d 0" % int(time.mktime(time.gmtime())) extra = {'branch': self.tagsbranch} ctx = context.memctx(self.repo, (tagparent, None), "update tags", [".hgtags"], getfilectx, "convert-repo", date, diff --git a/hgext/convert/git.py b/hgext/convert/git.py --- a/hgext/convert/git.py +++ b/hgext/convert/git.py @@ -435,7 +435,7 @@ else: output, status = self.gitrunlines('diff-tree', '--name-only', '--root', '-r', version, - '%s^%s' % (version, i + 1), '--') + '%s^%d' % (version, i + 1), '--') if status: raise error.Abort(_('cannot read changes in %s') % version) changes = [f.rstrip('\n') for f in output] To: pulkit, #hg-reviewers, indygreg Cc: mercurial-devel ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
D3283: py3: suppress the return value of open() in tests/test-subrepo-missing.t
indygreg accepted this revision. indygreg added a comment. This revision is now accepted and ready to land. Nit: (I've seen a few commit messages with this mistake.) The thing whose return is being suppressed is `.write()` not `open()`. REPOSITORY rHG Mercurial REVISION DETAIL https://phab.mercurial-scm.org/D3283 To: pulkit, #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
D3281: py3: add b'' prefix to make the regex bytes
This revision was automatically updated to reflect the committed changes. Closed by commit rHG39ced3ef586d: py3: add b'' prefix to make the regex bytes (authored by pulkit, committed by ). REPOSITORY rHG Mercurial CHANGES SINCE LAST UPDATE https://phab.mercurial-scm.org/D3281?vs=8048&id=8060 REVISION DETAIL https://phab.mercurial-scm.org/D3281 AFFECTED FILES hgext/convert/common.py CHANGE DETAILS diff --git a/hgext/convert/common.py b/hgext/convert/common.py --- a/hgext/convert/common.py +++ b/hgext/convert/common.py @@ -144,7 +144,7 @@ """ fails if revstr is not a 40 byte hex. mercurial and git both uses such format for their revision numbering """ -if not re.match(r'[0-9a-fA-F]{40,40}$', revstr): +if not re.match(br'[0-9a-fA-F]{40,40}$', revstr): raise error.Abort(_('%s entry %s is not a valid revision' ' identifier') % (mapname, revstr)) 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
D3280: py3: use b'%d' to convert int to bytes instead of str()
This revision was automatically updated to reflect the committed changes. Closed by commit rHG5b836a4c9a1f: py3: use b'%d' to convert int to bytes instead of str() (authored by pulkit, committed by ). REPOSITORY rHG Mercurial CHANGES SINCE LAST UPDATE https://phab.mercurial-scm.org/D3280?vs=8047&id=8059 REVISION DETAIL https://phab.mercurial-scm.org/D3280 AFFECTED FILES hgext/convert/git.py CHANGE DETAILS diff --git a/hgext/convert/git.py b/hgext/convert/git.py --- a/hgext/convert/git.py +++ b/hgext/convert/git.py @@ -372,7 +372,7 @@ tzs, tzh, tzm = tz[-5:-4] + "1", tz[-4:-2], tz[-2:] tz = -int(tzs) * (int(tzh) * 3600 + int(tzm)) -date = tm + " " + str(tz) +date = tm + " " + (b"%d" % tz) saverev = self.ui.configbool('convert', 'git.saverev') c = common.commit(parents=parents, date=date, author=author, To: pulkit, #hg-reviewers, indygreg Cc: mercurial-devel ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
D3282: py3: add b'' prefixes in tests/test-linerange.py
This revision was automatically updated to reflect the committed changes. Closed by commit rHG6939b6ac960a: py3: add b'' prefixes in tests/test-linerange.py (authored by pulkit, committed by ). REPOSITORY rHG Mercurial CHANGES SINCE LAST UPDATE https://phab.mercurial-scm.org/D3282?vs=8049&id=8061 REVISION DETAIL https://phab.mercurial-scm.org/D3282 AFFECTED FILES tests/test-linerange.py CHANGE DETAILS diff --git a/tests/test-linerange.py b/tests/test-linerange.py --- a/tests/test-linerange.py +++ b/tests/test-linerange.py @@ -4,7 +4,7 @@ from mercurial import error, mdiff # for readability, line numbers are 0-origin -text1 = ''' +text1 = b''' 00 at OLD 01 at OLD 02 at OLD @@ -19,7 +19,7 @@ 11 at OLD '''[1:] # strip initial LF -text2 = ''' +text2 = b''' 00 at NEW 01 at NEW 02 at NEW, 03 at OLD @@ -47,10 +47,10 @@ def setUp(self): self.blocks = list(mdiff.allblocks(text1, text2)) assert self.blocks == [ -([0, 3, 0, 2], '!'), -((3, 7, 2, 6), '='), -([7, 12, 6, 12], '!'), -((12, 12, 12, 12), '='), +([0, 3, 0, 2], b'!'), +((3, 7, 2, 6), b'='), +([7, 12, 6, 12], b'!'), +((12, 12, 12, 12), b'='), ], self.blocks def testWithinEqual(self): To: pulkit, #hg-reviewers, indygreg Cc: mercurial-devel ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
D3284: py3: use stringutil.forcebytestr() to convert error messages to bytes
This revision was automatically updated to reflect the committed changes. Closed by commit rHGdf4fd29c0854: py3: use stringutil.forcebytestr() to convert error messages to bytes (authored by pulkit, committed by ). REPOSITORY rHG Mercurial CHANGES SINCE LAST UPDATE https://phab.mercurial-scm.org/D3284?vs=8051&id=8063 REVISION DETAIL https://phab.mercurial-scm.org/D3284 AFFECTED FILES mercurial/subrepoutil.py CHANGE DETAILS diff --git a/mercurial/subrepoutil.py b/mercurial/subrepoutil.py --- a/mercurial/subrepoutil.py +++ b/mercurial/subrepoutil.py @@ -86,7 +86,8 @@ src = re.sub(pattern, repl, src, 1) except re.error as e: raise error.Abort(_("bad subrepository pattern in %s: %s") - % (p.source('subpaths', pattern), e)) + % (p.source('subpaths', pattern), +stringutil.forcebytestr(e))) return src state = {} To: pulkit, #hg-reviewers, indygreg Cc: mercurial-devel ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
D3283: py3: suppress the return value of open() in tests/test-subrepo-missing.t
This revision was automatically updated to reflect the committed changes. Closed by commit rHGfd0e6678ba0f: py3: suppress the return value of write() in tests/test-subrepo-missing.t (authored by pulkit, committed by ). REPOSITORY rHG Mercurial CHANGES SINCE LAST UPDATE https://phab.mercurial-scm.org/D3283?vs=8050&id=8062 REVISION DETAIL https://phab.mercurial-scm.org/D3283 AFFECTED FILES tests/test-subrepo-missing.t CHANGE DETAILS diff --git a/tests/test-subrepo-missing.t b/tests/test-subrepo-missing.t --- a/tests/test-subrepo-missing.t +++ b/tests/test-subrepo-missing.t @@ -14,15 +14,15 @@ ignore blanklines in .hgsubstate - >>> open('.hgsubstate', 'wb').write(b'\n\n \t \n \n') + >>> open('.hgsubstate', 'wb').write(b'\n\n \t \n \n') and None $ hg st --subrepos M .hgsubstate $ hg revert -qC .hgsubstate abort more gracefully on .hgsubstate parsing error $ cp .hgsubstate .hgsubstate.old - >>> open('.hgsubstate', 'wb').write(b'\ninvalid') + >>> open('.hgsubstate', 'wb').write(b'\ninvalid') and None $ hg st --subrepos --cwd $TESTTMP -R $TESTTMP/repo abort: invalid subrepository revision specifier in 'repo/.hgsubstate' line 2 [255] To: pulkit, #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
D3285: py3: use bytes() instead of str() on util.url()
This revision was automatically updated to reflect the committed changes. Closed by commit rHGb94fecf4cd8c: py3: use bytes() instead of str() on util.url() (authored by pulkit, committed by ). REPOSITORY rHG Mercurial CHANGES SINCE LAST UPDATE https://phab.mercurial-scm.org/D3285?vs=8052&id=8064 REVISION DETAIL https://phab.mercurial-scm.org/D3285 AFFECTED FILES mercurial/subrepoutil.py CHANGE DETAILS diff --git a/mercurial/subrepoutil.py b/mercurial/subrepoutil.py --- a/mercurial/subrepoutil.py +++ b/mercurial/subrepoutil.py @@ -106,7 +106,7 @@ parent = util.url(parent) parent.path = posixpath.join(parent.path or '', src) parent.path = posixpath.normpath(parent.path) -joined = str(parent) +joined = bytes(parent) # Remap the full joined path and use it if it changes, # else remap the original source. remapped = remap(joined) 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
D3283: py3: suppress the return value of open() in tests/test-subrepo-missing.t
pulkit added a comment. In https://phab.mercurial-scm.org/D3283#52480, @indygreg wrote: > Nit: (I've seen a few commit messages with this mistake.) The thing whose return is being suppressed is `.write()` not `open()`. If you can fix the commit message on flight, please do. I will take care of this next time. REPOSITORY rHG Mercurial REVISION DETAIL https://phab.mercurial-scm.org/D3283 To: pulkit, #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
D3246: keepalive: rewrite readinto() to not use read()
indygreg accepted this revision. indygreg added a comment. This revision is now accepted and ready to land. This is horrible. But this is the world we live in. Everything about the HTTP code terrifies me. That includes both our code and CPython's. REPOSITORY rHG Mercurial REVISION DETAIL https://phab.mercurial-scm.org/D3246 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
D3248: hgweb: put response headers back into str for Python 3
indygreg accepted this revision. indygreg added a comment. This revision is now accepted and ready to land. A low-level WSGI API that literally puts data on the wire uses Unicode. Because Python 3. Sadness. REPOSITORY rHG Mercurial REVISION DETAIL https://phab.mercurial-scm.org/D3248 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
D3251: tests: glob away fqdn wherever we print it
indygreg accepted this revision. indygreg added a comment. This revision is now accepted and ready to land. I think `$LOCALIP$` is the proper place for this fix. But it sounds like there were issues implementing that. Perfect is the enemy of done. REPOSITORY rHG Mercurial REVISION DETAIL https://phab.mercurial-scm.org/D3251 To: durin42, #hg-reviewers, indygreg Cc: indygreg, mharbison72, mercurial-devel ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
D2854: hgweb: use our forked wsgiheaders module instead of stdlib one
indygreg requested changes to this revision. indygreg added a comment. This revision now requires changes to proceed. This one caused an import cycle: `Import cycle: mercurial.hgweb.__init__ -> mercurial.hgweb.hgweb_mod -> mercurial.hgweb.request -> mercurial.hgweb.__init__` REPOSITORY rHG Mercurial REVISION DETAIL https://phab.mercurial-scm.org/D2854 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
D3246: keepalive: rewrite readinto() to not use read()
This revision was automatically updated to reflect the committed changes. Closed by commit rHG192b7ad06932: keepalive: rewrite readinto() to not use read() (authored by durin42, committed by ). REPOSITORY rHG Mercurial CHANGES SINCE LAST UPDATE https://phab.mercurial-scm.org/D3246?vs=8015&id=8065 REVISION DETAIL https://phab.mercurial-scm.org/D3246 AFFECTED FILES mercurial/keepalive.py CHANGE DETAILS diff --git a/mercurial/keepalive.py b/mercurial/keepalive.py --- a/mercurial/keepalive.py +++ b/mercurial/keepalive.py @@ -384,6 +384,7 @@ self._connection = None # (same) _raw_read = httplib.HTTPResponse.read +_raw_readinto = getattr(httplib.HTTPResponse, 'readinto', None) def close(self): if self.fp: @@ -523,12 +524,24 @@ return list def readinto(self, dest): -res = self.read(len(dest)) -if not res: -return 0 - -dest[0:len(res)] = res -return len(res) +if self._raw_readinto is None: +res = self.read(len(dest)) +if not res: +return 0 +dest[0:len(res)] = res +return len(res) +total = len(dest) +have = len(self._rbuf) +if have >= total: +dest[0:total] = self._rbuf[:total] +self._rbuf = self._rbuf[total:] +return total +mv = memoryview(dest) +got = self._raw_readinto(mv[have:total]) +dest[0:have] = self._rbuf +got += len(self._rbuf) +self._rbuf = '' +return got def safesend(self, str): """Send `str' to the server. 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
D3248: hgweb: put response headers back into str for Python 3
This revision was automatically updated to reflect the committed changes. Closed by commit rHGe320d9405bba: hgweb: put response headers back into str for Python 3 (authored by durin42, committed by ). REPOSITORY rHG Mercurial CHANGES SINCE LAST UPDATE https://phab.mercurial-scm.org/D3248?vs=8012&id=8067 REVISION DETAIL https://phab.mercurial-scm.org/D3248 AFFECTED FILES mercurial/hgweb/request.py CHANGE DETAILS diff --git a/mercurial/hgweb/request.py b/mercurial/hgweb/request.py --- a/mercurial/hgweb/request.py +++ b/mercurial/hgweb/request.py @@ -518,8 +518,10 @@ if not chunk: break +strheaders = [(pycompat.strurl(k), pycompat.strurl(v)) for + k, v in self.headers.items()] write = self._startresponse(pycompat.sysstr(self.status), -self.headers.items()) +strheaders) if self._bodybytes: yield self._bodybytes 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
D3250: hgweb: use native strings when interfacing with stdlib headers
This revision was automatically updated to reflect the committed changes. Closed by commit rHGb5ca5d34fe8d: hgweb: use native strings when interfacing with stdlib headers (authored by durin42, committed by ). REPOSITORY rHG Mercurial CHANGES SINCE LAST UPDATE https://phab.mercurial-scm.org/D3250?vs=8016&id=8069 REVISION DETAIL https://phab.mercurial-scm.org/D3250 AFFECTED FILES mercurial/hgweb/server.py CHANGE DETAILS diff --git a/mercurial/hgweb/server.py b/mercurial/hgweb/server.py --- a/mercurial/hgweb/server.py +++ b/mercurial/hgweb/server.py @@ -139,17 +139,17 @@ env[r'CONTENT_TYPE'] = self.headers.get_default_type() else: env[r'CONTENT_TYPE'] = self.headers.get_content_type() -length = self.headers.get('content-length') +length = self.headers.get(r'content-length') else: if self.headers.typeheader is None: env[r'CONTENT_TYPE'] = self.headers.type else: env[r'CONTENT_TYPE'] = self.headers.typeheader -length = self.headers.getheader('content-length') +length = self.headers.getheader(r'content-length') if length: env[r'CONTENT_LENGTH'] = length for header in [h for h in self.headers.keys() - if h not in ('content-type', 'content-length')]: + if h not in (r'content-type', r'content-length')]: hkey = r'HTTP_' + header.replace(r'-', r'_').upper() hval = self.headers.get(header) hval = hval.replace(r'\n', r'').strip() To: durin42, #hg-reviewers, indygreg Cc: mercurial-devel ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
D3251: tests: glob away fqdn wherever we print it
This revision was automatically updated to reflect the committed changes. Closed by commit rHGfb91757471b5: tests: glob away fqdn wherever we print it (authored by durin42, committed by ). REPOSITORY rHG Mercurial CHANGES SINCE LAST UPDATE https://phab.mercurial-scm.org/D3251?vs=8017&id=8070 REVISION DETAIL https://phab.mercurial-scm.org/D3251 AFFECTED FILES tests/test-pull-bundle.t tests/test-push-http.t CHANGE DETAILS diff --git a/tests/test-push-http.t b/tests/test-push-http.t --- a/tests/test-push-http.t +++ b/tests/test-push-http.t @@ -79,7 +79,7 @@ > txnclose-phase.test = sh $TESTTMP/hook.sh > EOF $ req "--debug --config extensions.blackbox=" - listening at http://localhost:$HGPORT/ (bound to $LOCALIP:$HGPORT) (?) + listening at http://*:$HGPORT/ (bound to $LOCALIP:$HGPORT) (glob) (?) pushing to http://localhost:$HGPORT/ searching for changes remote: redirecting incoming bundle to */hg-unbundle-* (glob) @@ -100,7 +100,7 @@ $ hg rollback repository tip rolled back to revision 0 (undo serve) $ req "--debug --config server.streamunbundle=True --config extensions.blackbox=" - listening at http://localhost:$HGPORT/ (bound to $LOCALIP:$HGPORT) (?) + listening at http://*:$HGPORT/ (bound to $LOCALIP:$HGPORT) (glob) (?) pushing to http://localhost:$HGPORT/ searching for changes remote: adding changesets diff --git a/tests/test-pull-bundle.t b/tests/test-pull-bundle.t --- a/tests/test-pull-bundle.t +++ b/tests/test-pull-bundle.t @@ -49,7 +49,7 @@ > 0.hg heads=bbd179dfa0a71671c253b3ae0aa1513b60d199fa > EOF $ hg --config blackbox.track=debug --debug serve -p $HGPORT2 -d --pid-file=../repo.pid - listening at http://localhost:$HGPORT2/ (bound to $LOCALIP:$HGPORT2) (?) + listening at http://*:$HGPORT2/ (bound to $LOCALIP:$HGPORT2) (glob) (?) $ cat ../repo.pid >> $DAEMON_PIDS $ cd .. $ hg clone -r 0 http://localhost:$HGPORT2/ repo.pullbundle @@ -91,7 +91,7 @@ $ cd repo $ hg --config blackbox.track=debug --debug serve -p $HGPORT2 -d --pid-file=../repo.pid - listening at http://localhost:$HGPORT2/ (bound to $LOCALIP:$HGPORT2) (?) + listening at http://*:$HGPORT2/ (bound to $LOCALIP:$HGPORT2) (glob) (?) $ cat ../repo.pid >> $DAEMON_PIDS $ cd .. $ hg clone http://localhost:$HGPORT2/ repo.pullbundle2 @@ -126,7 +126,7 @@ > 0.hg heads=bbd179dfa0a71671c253b3ae0aa1513b60d199fa > EOF $ hg --config blackbox.track=debug --debug serve -p $HGPORT2 -d --pid-file=../repo.pid - listening at http://localhost:$HGPORT2/ (bound to $LOCALIP:$HGPORT2) (?) + listening at http://*:$HGPORT2/ (bound to $LOCALIP:$HGPORT2) (glob) (?) $ cat ../repo.pid >> $DAEMON_PIDS $ cd .. $ hg clone -r 0 http://localhost:$HGPORT2/ repo.pullbundle3 To: durin42, #hg-reviewers, indygreg Cc: indygreg, mharbison72, mercurial-devel ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
D3247: tests: load showstack in test-pull-http.t so network hangs are easier to find
This revision was automatically updated to reflect the committed changes. Closed by commit rHG165a77f7ec13: tests: load showstack in test-pull-http.t so network hangs are easier to find (authored by durin42, committed by ). REPOSITORY rHG Mercurial CHANGES SINCE LAST UPDATE https://phab.mercurial-scm.org/D3247?vs=8053&id=8066 REVISION DETAIL https://phab.mercurial-scm.org/D3247 AFFECTED FILES tests/test-pull-http.t CHANGE DETAILS diff --git a/tests/test-pull-http.t b/tests/test-pull-http.t --- a/tests/test-pull-http.t +++ b/tests/test-pull-http.t @@ -1,5 +1,16 @@ #require killdaemons +#if no-windows +For debugging: this is a pretty simple test that is a good candidate +for tracking down network-related bugs. Sometimes a command in this +hangs, so having showstack pre-loaded is sometimes helpful. This also +gives us a test that at least proves showstack can be loaded. + $ cat >> $HGRCPATH < [extensions] + > showstack = $TESTDIR/../contrib/showstack.py + > EOF +#endif + $ hg init test $ cd test $ echo a > a To: durin42, #hg-reviewers, indygreg Cc: mharbison72, mercurial-devel ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
D3249: wireprotoserver: headers are bytes for us internally, use bytes
This revision was automatically updated to reflect the committed changes. Closed by commit rHG9170df9106a8: wireprotoserver: headers are bytes for us internally, use bytes (authored by durin42, committed by ). REPOSITORY rHG Mercurial CHANGES SINCE LAST UPDATE https://phab.mercurial-scm.org/D3249?vs=8013&id=8068 REVISION DETAIL https://phab.mercurial-scm.org/D3249 AFFECTED FILES mercurial/wireprotoserver.py CHANGE DETAILS diff --git a/mercurial/wireprotoserver.py b/mercurial/wireprotoserver.py --- a/mercurial/wireprotoserver.py +++ b/mercurial/wireprotoserver.py @@ -103,7 +103,7 @@ def getprotocaps(self): if self._protocaps is None: -value = decodevaluefromheaders(self._req, r'X-HgProto') +value = decodevaluefromheaders(self._req, b'X-HgProto') self._protocaps = set(value.split(' ')) return self._protocaps To: durin42, #hg-reviewers, indygreg Cc: mercurial-devel ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
D3245: wsgiheaders: import a bytes-ified fork of wsgiref.headers from cpython@46f5072
indygreg requested changes to this revision. indygreg added a comment. This revision now requires changes to proceed. Could you please separate the vendoring from the changes so we have a record of the patch that was made. Also, do we want a license annotation? REPOSITORY rHG Mercurial REVISION DETAIL https://phab.mercurial-scm.org/D3245 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
D3252: tests: use `f --newer` instead of `stat -c` in test-fix.t
This revision was automatically updated to reflect the committed changes. Closed by commit rHG314f39e5fa86: tests: use `f --newer` instead of `stat -c` in test-fix.t (authored by durin42, committed by ). REPOSITORY rHG Mercurial CHANGES SINCE LAST UPDATE https://phab.mercurial-scm.org/D3252?vs=8018&id=8071 REVISION DETAIL https://phab.mercurial-scm.org/D3252 AFFECTED FILES tests/test-fix.t CHANGE DETAILS diff --git a/tests/test-fix.t b/tests/test-fix.t --- a/tests/test-fix.t +++ b/tests/test-fix.t @@ -492,11 +492,11 @@ $ printf "NO FIX NEEDED\n" > foo.whole $ hg add adding foo.whole - $ OLD_MTIME=`stat -c %Y foo.whole` - $ sleep 1 # mtime has a resolution of one second. + $ cp foo.whole foo.whole.orig + $ sleep 2 # mtime has a resolution of one or two seconds. $ hg fix --working-dir - $ NEW_MTIME=`stat -c %Y foo.whole` - $ test $OLD_MTIME = $NEW_MTIME + $ f foo.whole --newer foo.whole.orig + foo.whole: older than foo.whole.orig $ cd .. To: durin42, #hg-reviewers, indygreg Cc: mercurial-devel ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
D2939: fsmonitor: layer on another hack in bser.c for os.stat() compat (issue5811)
indygreg accepted this revision. indygreg added a comment. This revision is now accepted and ready to land. This is super hacky. That's par for the course for this file, sadly. Also, I'm kinda surprised we're fully realizing the Python tuple to represent stat results. If we made tuple attribute access lazy, that would probably make `hg status` a bit faster, since we never access every field of that tuple. These kinds of things never show up in Python profilers though. And it is difficult to pin performance problems on Python object creation. But we know it is a very real thing. Obviously work for another day. REPOSITORY rHG Mercurial REVISION DETAIL https://phab.mercurial-scm.org/D2939 To: durin42, #hg-reviewers, indygreg Cc: spectral, indygreg, mercurial-devel ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
D2939: fsmonitor: layer on another hack in bser.c for os.stat() compat (issue5811)
This revision was automatically updated to reflect the committed changes. Closed by commit rHGb1f62cd39b5c: fsmonitor: layer on another hack in bser.c for os.stat() compat (issue5811) (authored by durin42, committed by ). REPOSITORY rHG Mercurial CHANGES SINCE LAST UPDATE https://phab.mercurial-scm.org/D2939?vs=7915&id=8072 REVISION DETAIL https://phab.mercurial-scm.org/D2939 AFFECTED FILES hgext/fsmonitor/pywatchman/bser.c CHANGE DETAILS diff --git a/hgext/fsmonitor/pywatchman/bser.c b/hgext/fsmonitor/pywatchman/bser.c --- a/hgext/fsmonitor/pywatchman/bser.c +++ b/hgext/fsmonitor/pywatchman/bser.c @@ -128,27 +128,38 @@ Py_ssize_t i, n; PyObject* name_bytes = NULL; PyObject* ret = NULL; - const char* namestr; + const char* namestr = NULL; if (PyIndex_Check(name)) { i = PyNumber_AsSsize_t(name, PyExc_IndexError); if (i == -1 && PyErr_Occurred()) { goto bail; } -ret = PySequence_GetItem(obj->values, i); -goto bail; - } - // We can be passed in Unicode objects here -- we don't support anything other - // than UTF-8 for keys. - if (PyUnicode_Check(name)) { -name_bytes = PyUnicode_AsUTF8String(name); -if (name_bytes == NULL) { +if (i == 8 && PySequence_Size(obj->values) < 9) { + // Hack alert: Python 3 removed support for os.stat().st_mtime + // being an integer.Instead, if you need an integer, you have to + // use os.stat()[stat.ST_MTIME] instead. stat.ST_MTIME is 8, and + // our stat tuples are shorter than that, so we can detect + // requests for index 8 on tuples shorter than that and return + // st_mtime instead. + namestr = "st_mtime"; +} else { + ret = PySequence_GetItem(obj->values, i); goto bail; } -namestr = PyBytes_AsString(name_bytes); } else { -namestr = PyBytes_AsString(name); +// We can be passed in Unicode objects here -- we don't support anything other +// than UTF-8 for keys. +if (PyUnicode_Check(name)) { + name_bytes = PyUnicode_AsUTF8String(name); + if (name_bytes == NULL) { +goto bail; + } + namestr = PyBytes_AsString(name_bytes); +} else { + namestr = PyBytes_AsString(name); +} } if (namestr == NULL) { To: durin42, #hg-reviewers, indygreg Cc: spectral, indygreg, mercurial-devel ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
D3213: fix: add --all flag to fix non-public non-obsolete revisions
indygreg accepted this revision. indygreg added a comment. This revision is now accepted and ready to land. Nice feature! INLINE COMMENTS > test-fix-topology.t:264-290 > + $ printf "one\n" > foo.whole > + $ hg commit -Aqm "first" > + $ hg phase --public > + $ hg tag --local root > + $ printf "two\n" > foo.whole > + $ hg commit -m "second" > + $ printf "three\n" > foo.whole Next time, please consider using the `drawdag` extension for building a repo. It can't create obsolete changesets. But if the test is doing a bunch of regular `hg commit`, it will be faster to use `drawdag` to create the repo, as it avoids a ton of overhead from `hg` processes. (I'm still guilty of not using `drawdag`, as the tool is relatively new.) REPOSITORY rHG Mercurial REVISION DETAIL https://phab.mercurial-scm.org/D3213 To: hooper, #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
D3213: fix: add --all flag to fix non-public non-obsolete revisions
This revision was automatically updated to reflect the committed changes. Closed by commit rHGe2506748b47f: fix: add --all flag to fix non-public non-obsolete revisions (authored by hooper, committed by ). REPOSITORY rHG Mercurial CHANGES SINCE LAST UPDATE https://phab.mercurial-scm.org/D3213?vs=7925&id=8073 REVISION DETAIL https://phab.mercurial-scm.org/D3213 AFFECTED FILES hgext/fix.py tests/test-fix-topology.t tests/test-fix.t CHANGE DETAILS diff --git a/tests/test-fix.t b/tests/test-fix.t --- a/tests/test-fix.t +++ b/tests/test-fix.t @@ -104,6 +104,7 @@ options ([+] can be repeated): + --all fix all non-public non-obsolete revisions --base REV [+] revisions to diff against (overrides automatic selection, and applies to every revision being fixed) -r --rev REV [+] revisions to fix diff --git a/tests/test-fix-topology.t b/tests/test-fix-topology.t --- a/tests/test-fix-topology.t +++ b/tests/test-fix-topology.t @@ -266,3 +266,152 @@ $ cd .. +The --all flag should fix anything that wouldn't cause a problem if you fixed +it, including the working copy. Obsolete revisions are not fixed because that +could cause divergence. Public revisions would cause an abort because they are +immutable. We can fix orphans because their successors are still just orphans +of the original obsolete parent. When obsolesence is off, we're just fixing and +replacing anything that isn't public. + + $ hg init fixall + $ cd fixall + +#if obsstore-on + $ printf "one\n" > foo.whole + $ hg commit -Aqm "first" + $ hg phase --public + $ hg tag --local root + $ printf "two\n" > foo.whole + $ hg commit -m "second" + $ printf "three\n" > foo.whole + $ hg commit -m "third" --secret + $ hg tag --local secret + $ hg checkout root + 1 files updated, 0 files merged, 0 files removed, 0 files unresolved + $ printf "four\n" > foo.whole + $ hg commit -m "fourth" + created new head + $ printf "five\n" > foo.whole + $ hg commit -m "fifth" + $ hg tag --local replaced + $ printf "six\n" > foo.whole + $ hg commit -m "sixth" + $ hg checkout replaced + 1 files updated, 0 files merged, 0 files removed, 0 files unresolved + $ printf "seven\n" > foo.whole + $ hg commit --amend + 1 new orphan changesets + $ hg checkout secret + 1 files updated, 0 files merged, 0 files removed, 0 files unresolved + $ printf "uncommitted\n" > foo.whole + + $ hg log --graph --template '{rev} {desc} {phase}\n' + o 6 fifth draft + | + | * 5 sixth draft + | | + | x 4 fifth draft + |/ + o 3 fourth draft + | + | @ 2 third secret + | | + | o 1 second draft + |/ + o 0 first public + + + $ hg fix --all + 1 new orphan changesets + + $ hg log --graph --template '{rev} {desc}\n' -r 'sort(all(), topo)' --hidden + o 11 fifth + | + o 9 fourth + | + | @ 8 third + | | + | o 7 second + |/ + | * 10 sixth + | | + | | x 5 sixth + | |/ + | x 4 fifth + | | + | | x 6 fifth + | |/ + | x 3 fourth + |/ + | x 2 third + | | + | x 1 second + |/ + o 0 first + + + $ hg cat -r 7 foo.whole + TWO + $ hg cat -r 8 foo.whole + THREE + $ hg cat -r 9 foo.whole + FOUR + $ hg cat -r 10 foo.whole + SIX + $ hg cat -r 11 foo.whole + SEVEN + $ cat foo.whole + UNCOMMITTED +#else + $ printf "one\n" > foo.whole + $ hg commit -Aqm "first" + $ hg phase --public + $ hg tag --local root + $ printf "two\n" > foo.whole + $ hg commit -m "second" + $ printf "three\n" > foo.whole + $ hg commit -m "third" --secret + $ hg tag --local secret + $ hg checkout root + 1 files updated, 0 files merged, 0 files removed, 0 files unresolved + $ printf "four\n" > foo.whole + $ hg commit -m "fourth" + created new head + $ printf "uncommitted\n" > foo.whole + + $ hg log --graph --template '{rev} {desc} {phase}\n' + @ 3 fourth draft + | + | o 2 third secret + | | + | o 1 second draft + |/ + o 0 first public + + + $ hg fix --all + saved backup bundle to * (glob) + + $ hg log --graph --template '{rev} {desc} {phase}\n' + @ 3 fourth draft + | + | o 2 third secret + | | + | o 1 second draft + |/ + o 0 first public + + $ hg cat -r 0 foo.whole + one + $ hg cat -r 1 foo.whole + TWO + $ hg cat -r 2 foo.whole + THREE + $ hg cat -r 3 foo.whole + FOUR + $ cat foo.whole + UNCOMMITTED +#endif + + $ cd .. + diff --git a/hgext/fix.py b/hgext/fix.py --- a/hgext/fix.py +++ b/hgext/fix.py @@ -95,7 +95,8 @@ configitem('fix', 'maxfilesize', default='2MB') @command('fix', -[('', 'base', [], _('revisions to diff against (overrides automatic ' +[('', 'all', False, _('fix all non-public non-obsolete revisions')), + ('', 'base', [], _('revisions to diff against (overrides automatic ' 'selection, and applies to every revision being ' 'fixed)'), _('REV')), ('r', 'rev', [], _('revisions to fix'), _('REV')), @@ -125,6 +126,11 @@ revisions are not forgotten in late
D3117: tests: make test-convert-git.t more deterministic
indygreg abandoned this revision. indygreg added a comment. This isn't worth my time to close the loop on. REPOSITORY rHG Mercurial REVISION DETAIL https://phab.mercurial-scm.org/D3117 To: indygreg, #hg-reviewers, durin42 Cc: mercurial-devel ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
D2880: bundle: add the possibility to bundle bookmarks (issue5792)
indygreg requested changes to this revision. indygreg added a comment. This revision now requires changes to proceed. What's the status of this patch? Is it still reviewable? If so, let's get a rebased version submitted, just in case things have changed. REPOSITORY rHG Mercurial REVISION DETAIL https://phab.mercurial-scm.org/D2880 To: lothiraldan, #hg-reviewers, indygreg Cc: martinvonz, indygreg, pulkit, mercurial-devel ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
[PATCH 3 of 9] export: do not start pager if output will be written to file
# HG changeset patch # User Yuya Nishihara # Date 1523536427 -32400 # Thu Apr 12 21:33:47 2018 +0900 # Node ID 18bead1ff6b9b9d0df3e6b0a7aea2fd358ce1244 # Parent aa00793f5b3567c6768e8f7be43c3043ea29f536 export: do not start pager if output will be written to file A copy of 3b569745af6c. diff --git a/mercurial/commands.py b/mercurial/commands.py --- a/mercurial/commands.py +++ b/mercurial/commands.py @@ -1971,8 +1971,14 @@ def export(ui, repo, *changesets, **opts ui.note(_('exporting patches:\n')) else: ui.note(_('exporting patch:\n')) -ui.pager('export') -cmdutil.export(repo, revs, fntemplate=opts.get('output'), + +fntemplate = opts.get('output') +if cmdutil.isstdiofilename(fntemplate): +fntemplate = '' + +if not fntemplate: +ui.pager('export') +cmdutil.export(repo, revs, fntemplate=fntemplate, switch_parent=opts.get('switch_parent'), opts=patch.diffallopts(ui, opts)) diff --git a/tests/test-pager.t b/tests/test-pager.t --- a/tests/test-pager.t +++ b/tests/test-pager.t @@ -322,6 +322,37 @@ A command with --output option: $ hg cat -r0 a --output=- paged! 'a\n' $ hg cat -r0 a --output=out + + $ hg export -r0 + paged! '# HG changeset patch\n' + paged! '# User test\n' + paged! '# Date 0 0\n' + paged! '# Thu Jan 01 00:00:00 1970 +\n' + paged! '# Node ID 1f0dee641bb7258c56bd60e93edfa2405381c41e\n' + paged! '# Parent \n' + paged! 'add a\n' + paged! '\n' + paged! '\x1b[0;1mdiff -r -r 1f0dee641bb7 a\x1b[0m\n' + paged! '\x1b[0;31;1m--- /dev/null\tThu Jan 01 00:00:00 1970 +\x1b[0m\n' + paged! '\x1b[0;32;1m+++ b/a\tThu Jan 01 00:00:00 1970 +\x1b[0m\n' + paged! '\x1b[0;35m@@ -0,0 +1,1 @@\x1b[0m\n' + paged! '\x1b[0;32m+a\x1b[0m\n' + $ hg export -r0 -o - + paged! '# HG changeset patch\n' + paged! '# User test\n' + paged! '# Date 0 0\n' + paged! '# Thu Jan 01 00:00:00 1970 +\n' + paged! '# Node ID 1f0dee641bb7258c56bd60e93edfa2405381c41e\n' + paged! '# Parent \n' + paged! 'add a\n' + paged! '\n' + paged! '\x1b[0;1mdiff -r -r 1f0dee641bb7 a\x1b[0m\n' + paged! '\x1b[0;31;1m--- /dev/null\tThu Jan 01 00:00:00 1970 +\x1b[0m\n' + paged! '\x1b[0;32;1m+++ b/a\tThu Jan 01 00:00:00 1970 +\x1b[0m\n' + paged! '\x1b[0;35m@@ -0,0 +1,1 @@\x1b[0m\n' + paged! '\x1b[0;32m+a\x1b[0m\n' + $ hg export -r0 -o out + $ rm out Put annotate in the ignore list for pager: ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
[PATCH 1 of 9] formatter: remove unused private attributes from baseformatter
# HG changeset patch # User Yuya Nishihara # Date 1523543073 -32400 # Thu Apr 12 23:24:33 2018 +0900 # Node ID e6609e390f284931c10f06f3c8258769fad9bbc5 # Parent 9c7a25ef5b49f3ce2fe698b58246b622ca9fd382 formatter: remove unused private attributes from baseformatter No idea what they were for. diff --git a/mercurial/formatter.py b/mercurial/formatter.py --- a/mercurial/formatter.py +++ b/mercurial/formatter.py @@ -160,8 +160,6 @@ class baseformatter(object): def __init__(self, ui, topic, opts, converter): self._ui = ui self._topic = topic -self._style = opts.get("style") -self._template = opts.get("template") self._converter = converter self._item = None # function to convert node to string suitable for this output ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
[PATCH 4 of 9] export: remove unused argument 'rev' from _exportsingle()
# HG changeset patch # User Yuya Nishihara # Date 1523537237 -32400 # Thu Apr 12 21:47:17 2018 +0900 # Node ID 905b4afbfed88a336287cc79e7f3258fd05380cd # Parent 18bead1ff6b9b9d0df3e6b0a7aea2fd358ce1244 export: remove unused argument 'rev' from _exportsingle() diff --git a/mercurial/cmdutil.py b/mercurial/cmdutil.py --- a/mercurial/cmdutil.py +++ b/mercurial/cmdutil.py @@ -1526,7 +1526,7 @@ extraexport = [] # it is given two arguments (sequencenumber, changectx) extraexportmap = {} -def _exportsingle(repo, ctx, match, switch_parent, rev, seqno, write, diffopts): +def _exportsingle(repo, ctx, match, switch_parent, seqno, write, diffopts): node = scmutil.binnode(ctx) parents = [p.node() for p in ctx.parents() if p] branch = ctx.branch() @@ -1611,7 +1611,7 @@ def export(repo, revs, fntemplate='hg-%h if not dest.startswith('<'): repo.ui.note("%s\n" % dest) _exportsingle( -repo, ctx, match, switch_parent, rev, seqno, write, opts) +repo, ctx, match, switch_parent, seqno, write, opts) if fo is not None: fo.close() ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
[PATCH 2 of 9] formatter: carry opts to file-based formatters by basefm
# HG changeset patch # User Yuya Nishihara # Date 1523543158 -32400 # Thu Apr 12 23:25:58 2018 +0900 # Node ID aa00793f5b3567c6768e8f7be43c3043ea29f536 # Parent e6609e390f284931c10f06f3c8258769fad9bbc5 formatter: carry opts to file-based formatters by basefm This makes it slightly easier to port "hg export" to formatter. diff --git a/mercurial/cmdutil.py b/mercurial/cmdutil.py --- a/mercurial/cmdutil.py +++ b/mercurial/cmdutil.py @@ -2231,7 +2231,7 @@ def cat(ui, repo, ctx, matcher, basefm, os.makedirs(os.path.dirname(filename)) except OSError: pass -with formatter.maybereopen(basefm, filename, opts) as fm: +with formatter.maybereopen(basefm, filename) as fm: _updatecatformatter(fm, ctx, matcher, path, opts.get('decode')) # Automation often uses hg cat on single files, so special case it diff --git a/mercurial/commands.py b/mercurial/commands.py --- a/mercurial/commands.py +++ b/mercurial/commands.py @@ -1318,7 +1318,7 @@ def cat(ui, repo, file1, *pats, **opts): fntemplate = '' if fntemplate: -fm = formatter.nullformatter(ui, 'cat') +fm = formatter.nullformatter(ui, 'cat', opts) else: ui.pager('cat') fm = ui.formatter('cat', opts) diff --git a/mercurial/formatter.py b/mercurial/formatter.py --- a/mercurial/formatter.py +++ b/mercurial/formatter.py @@ -160,6 +160,7 @@ class baseformatter(object): def __init__(self, ui, topic, opts, converter): self._ui = ui self._topic = topic +self._opts = opts self._converter = converter self._item = None # function to convert node to string suitable for this output @@ -222,9 +223,9 @@ class baseformatter(object): if self._item is not None: self._showitem() -def nullformatter(ui, topic): +def nullformatter(ui, topic, opts): '''formatter that prints nothing''' -return baseformatter(ui, topic, opts={}, converter=_nullconverter) +return baseformatter(ui, topic, opts, converter=_nullconverter) class _nestedformatter(baseformatter): '''build sub items and store them in the parent formatter''' @@ -595,7 +596,7 @@ def openformatter(ui, filename, topic, o def _neverending(fm): yield fm -def maybereopen(fm, filename, opts): +def maybereopen(fm, filename): """Create a formatter backed by file if filename specified, else return the given formatter @@ -603,6 +604,6 @@ def maybereopen(fm, filename, opts): of the given formatter. """ if filename: -return openformatter(fm._ui, filename, fm._topic, opts) +return openformatter(fm._ui, filename, fm._topic, fm._opts) else: return _neverending(fm) ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
[PATCH 5 of 9] export: split cmdutil.export() to single-file and maybe-multiple-files cases
# HG changeset patch # User Yuya Nishihara # Date 1523537762 -32400 # Thu Apr 12 21:56:02 2018 +0900 # Node ID 97ed426f12977158a72a81e64514aa69a735766b # Parent 905b4afbfed88a336287cc79e7f3258fd05380cd export: split cmdutil.export() to single-file and maybe-multiple-files cases Porting "hg export" to formatter is a bit hard because cmdutil.export() may append to files if the fntemplate is specified. This patch splits the hard part from the trivial case. diff --git a/mercurial/cmdutil.py b/mercurial/cmdutil.py --- a/mercurial/cmdutil.py +++ b/mercurial/cmdutil.py @@ -1559,6 +1559,39 @@ def _exportsingle(repo, ctx, match, swit for chunk, label in patch.diffui(repo, prev, node, match, opts=diffopts): write(chunk, label=label) +def _exportfile(repo, revs, fp, switch_parent, diffopts, match): +"""Export changesets to stdout or a single file""" +dest = '' +if fp: +dest = getattr(fp, 'name', dest) +def write(s, **kw): +fp.write(s) +else: +write = repo.ui.write + +for seqno, rev in enumerate(revs, 1): +ctx = repo[rev] +if not dest.startswith('<'): +repo.ui.note("%s\n" % dest) +_exportsingle(repo, ctx, match, switch_parent, seqno, write, diffopts) + +def _exportfntemplate(repo, revs, fntemplate, switch_parent, diffopts, match): +"""Export changesets to possibly multiple files""" +total = len(revs) +revwidth = max(len(str(rev)) for rev in revs) +filemode = {} + +for seqno, rev in enumerate(revs, 1): +ctx = repo[rev] +fo = makefileobj(ctx, fntemplate, mode='wb', modemap=filemode, + total=total, seqno=seqno, revwidth=revwidth) +dest = fo.name +def write(s, **kw): +fo.write(s) +repo.ui.note("%s\n" % dest) +_exportsingle(repo, ctx, match, switch_parent, seqno, write, diffopts) +fo.close() + def export(repo, revs, fntemplate='hg-%h.patch', fp=None, switch_parent=False, opts=None, match=None): '''export changesets as hg patches @@ -1585,35 +1618,10 @@ def export(repo, revs, fntemplate='hg-%h the given template. Neither fp nor template specified: All revs written to repo.ui.write() ''' - -total = len(revs) -revwidth = max(len(str(rev)) for rev in revs) -filemode = {} - -write = None -dest = '' -if fp: -dest = getattr(fp, 'name', dest) -def write(s, **kw): -fp.write(s) -elif not fntemplate: -write = repo.ui.write - -for seqno, rev in enumerate(revs, 1): -ctx = repo[rev] -fo = None -if not fp and fntemplate: -fo = makefileobj(ctx, fntemplate, mode='wb', modemap=filemode, - total=total, seqno=seqno, revwidth=revwidth) -dest = fo.name -def write(s, **kw): -fo.write(s) -if not dest.startswith('<'): -repo.ui.note("%s\n" % dest) -_exportsingle( -repo, ctx, match, switch_parent, seqno, write, opts) -if fo is not None: -fo.close() +if fp or not fntemplate: +_exportfile(repo, revs, fp, switch_parent, opts, match) +else: +_exportfntemplate(repo, revs, fntemplate, switch_parent, opts, match) def showmarker(fm, marker, index=None): """utility function to display obsolescence marker in a readable way ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
[PATCH 8 of 9] export: extract function to write patch to file object (API)
# HG changeset patch # User Yuya Nishihara # Date 1523541589 -32400 # Thu Apr 12 22:59:49 2018 +0900 # Node ID 499cfc83b0cba948eec6b1e30998862b7e7fc051 # Parent 6041c9cdcee8f25328016f1727055d1bc1677054 export: extract function to write patch to file object (API) This is common use case of cmdutil.export(), and we wouldn't want to handle formatter thingy everywhere. .. api:: The ``fp`` argument is removed from ``cmdutil.export()``. Use ``cmdutil.exportfile()`` instead. diff --git a/hgext/mq.py b/hgext/mq.py --- a/hgext/mq.py +++ b/hgext/mq.py @@ -2182,9 +2182,8 @@ class queue(object): self.checkpatchname(patchname, force) self.fullseries.insert(0, patchname) -patchf = self.opener(patchname, "w") -cmdutil.export(repo, [n], fp=patchf, opts=diffopts) -patchf.close() +with self.opener(patchname, "w") as fp: +cmdutil.exportfile(repo, [n], fp, opts=diffopts) se = statusentry(n, patchname) self.applied.insert(0, se) diff --git a/hgext/patchbomb.py b/hgext/patchbomb.py --- a/hgext/patchbomb.py +++ b/hgext/patchbomb.py @@ -306,8 +306,8 @@ def _getpatches(repo, revs, **opts): ui.warn(_('warning: working directory has ' 'uncommitted changes\n')) output = stringio() -cmdutil.export(repo, [r], fp=output, - opts=patch.difffeatureopts(ui, opts, git=True)) +cmdutil.exportfile(repo, [r], output, + opts=patch.difffeatureopts(ui, opts, git=True)) yield output.getvalue().split('\n') def _getbundle(repo, dest, **opts): """return a bundle containing changesets missing in "dest" diff --git a/hgext/shelve.py b/hgext/shelve.py --- a/hgext/shelve.py +++ b/hgext/shelve.py @@ -413,9 +413,8 @@ def _nothingtoshelvemessaging(ui, repo, def _shelvecreatedcommit(repo, node, name): bases = list(mutableancestors(repo[node])) shelvedfile(repo, name, 'hg').writebundle(bases, node) -cmdutil.export(repo, [node], - fp=shelvedfile(repo, name, patchextension).opener('wb'), - opts=mdiff.diffopts(git=True)) +with shelvedfile(repo, name, patchextension).opener('wb') as fp: +cmdutil.exportfile(repo, [node], fp, opts=mdiff.diffopts(git=True)) def _includeunknownfiles(repo, pats, opts, extra): s = repo.status(match=scmutil.match(repo[None], pats, opts), diff --git a/mercurial/cmdutil.py b/mercurial/cmdutil.py --- a/mercurial/cmdutil.py +++ b/mercurial/cmdutil.py @@ -1603,7 +1603,7 @@ def _exportfntemplate(repo, revs, fntemp _exportsingle(repo, ctx, fm, match, switch_parent, seqno, diffopts) -def export(repo, revs, fntemplate='hg-%h.patch', fp=None, switch_parent=False, +def export(repo, revs, fntemplate='hg-%h.patch', switch_parent=False, opts=None, match=None): '''export changesets as hg patches @@ -1611,7 +1611,6 @@ def export(repo, revs, fntemplate='hg-%h repo: The repository from which we're exporting revisions. revs: A list of revisions to export as revision numbers. fntemplate: An optional string to use for generating patch file names. - fp: An optional file-like object to which patches should be written. switch_parent: If True, show diffs against second parent when not nullid. Default is false, which always shows diff against p1. opts: diff options to use for generating the patch. @@ -1623,17 +1622,19 @@ def export(repo, revs, fntemplate='hg-%h Side Effect: "HG Changeset Patch" data is emitted to one of the following destinations: -fp is specified: All revs are written to the specified - file-like object. fntemplate specified: Each rev is written to a unique file named using the given template. -Neither fp nor template specified: All revs written to repo.ui.write() +Otherwise: All revs written to repo.ui.write() ''' -if fp or not fntemplate: -_exportfile(repo, revs, fp, switch_parent, opts, match) +if not fntemplate: +_exportfile(repo, revs, None, switch_parent, opts, match) else: _exportfntemplate(repo, revs, fntemplate, switch_parent, opts, match) +def exportfile(repo, revs, fp, switch_parent=False, opts=None, match=None): +"""Export changesets to the given file stream""" +_exportfile(repo, revs, fp, switch_parent, opts, match) + def showmarker(fm, marker, index=None): """utility function to display obsolescence marker in a readable way ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
[PATCH 6 of 9] export: serialize revisions to be exported per destination file
# HG changeset patch # User Yuya Nishihara # Date 1523538535 -32400 # Thu Apr 12 22:08:55 2018 +0900 # Node ID 724b281e9d9b9ebd91d5ab12482f93a25efb1259 # Parent 97ed426f12977158a72a81e64514aa69a735766b export: serialize revisions to be exported per destination file Prepares for porting to the formatter API, where we can't simply append to existing files because JSON can't be streamed for example. The modemap hack is removed since cmdutil.export() was the only user. I also made the destination filename printed only once. diff --git a/mercurial/cmdutil.py b/mercurial/cmdutil.py --- a/mercurial/cmdutil.py +++ b/mercurial/cmdutil.py @@ -1014,7 +1014,7 @@ class _unclosablefile(object): def __exit__(self, exc_type, exc_value, exc_tb): pass -def makefileobj(ctx, pat, mode='wb', modemap=None, **props): +def makefileobj(ctx, pat, mode='wb', **props): writable = mode not in ('r', 'rb') if isstdiofilename(pat): @@ -1025,10 +1025,6 @@ def makefileobj(ctx, pat, mode='wb', mod fp = repo.ui.fin return _unclosablefile(fp) fn = makefilename(ctx, pat, **props) -if modemap is not None: -mode = modemap.get(fn, mode) -if mode == 'wb': -modemap[fn] = 'ab' return open(fn, mode) def openrevlog(repo, cmd, file_, opts): @@ -1579,18 +1575,23 @@ def _exportfntemplate(repo, revs, fntemp """Export changesets to possibly multiple files""" total = len(revs) revwidth = max(len(str(rev)) for rev in revs) -filemode = {} +filemap = util.sortdict() # filename: [(seqno, rev), ...] for seqno, rev in enumerate(revs, 1): ctx = repo[rev] -fo = makefileobj(ctx, fntemplate, mode='wb', modemap=filemode, - total=total, seqno=seqno, revwidth=revwidth) -dest = fo.name -def write(s, **kw): -fo.write(s) -repo.ui.note("%s\n" % dest) -_exportsingle(repo, ctx, match, switch_parent, seqno, write, diffopts) -fo.close() +dest = makefilename(ctx, fntemplate, +total=total, seqno=seqno, revwidth=revwidth) +filemap.setdefault(dest, []).append((seqno, rev)) + +for dest in filemap: +with open(dest, 'wb') as fo: +repo.ui.note("%s\n" % dest) +def write(s, **kw): +fo.write(s) +for seqno, rev in filemap[dest]: +ctx = repo[rev] +_exportsingle(repo, ctx, match, switch_parent, seqno, write, + diffopts) def export(repo, revs, fntemplate='hg-%h.patch', fp=None, switch_parent=False, opts=None, match=None): ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
[PATCH 7 of 9] export: port _exportsingle() to formatter
# HG changeset patch # User Yuya Nishihara # Date 1523540383 -32400 # Thu Apr 12 22:39:43 2018 +0900 # Node ID 6041c9cdcee8f25328016f1727055d1bc1677054 # Parent 724b281e9d9b9ebd91d5ab12482f93a25efb1259 export: port _exportsingle() to formatter Pass 'fm' instead of 'write', and use fm.plain(), fm.write(), etc. instead. The callers will be updated later. diff --git a/mercurial/cmdutil.py b/mercurial/cmdutil.py --- a/mercurial/cmdutil.py +++ b/mercurial/cmdutil.py @@ -1522,7 +1522,7 @@ extraexport = [] # it is given two arguments (sequencenumber, changectx) extraexportmap = {} -def _exportsingle(repo, ctx, match, switch_parent, seqno, write, diffopts): +def _exportsingle(repo, ctx, fm, match, switch_parent, seqno, diffopts): node = scmutil.binnode(ctx) parents = [p.node() for p in ctx.parents() if p] branch = ctx.branch() @@ -1534,42 +1534,53 @@ def _exportsingle(repo, ctx, match, swit else: prev = nullid -write("# HG changeset patch\n") -write("# User %s\n" % ctx.user()) -write("# Date %d %d\n" % ctx.date()) -write("# %s\n" % dateutil.datestr(ctx.date())) -if branch and branch != 'default': -write("# Branch %s\n" % branch) -write("# Node ID %s\n" % hex(node)) -write("# Parent %s\n" % hex(prev)) +fm.context(ctx=ctx) +fm.plain('# HG changeset patch\n') +fm.write('user', '# User %s\n', ctx.user()) +fm.plain('# Date %d %d\n' % ctx.date()) +fm.write('date', '# %s\n', fm.formatdate(ctx.date())) +fm.condwrite(branch and branch != 'default', + 'branch', '# Branch %s\n', branch) +fm.write('node', '# Node ID %s\n', hex(node)) +fm.plain('# Parent %s\n' % hex(prev)) if len(parents) > 1: -write("# Parent %s\n" % hex(parents[1])) - +fm.plain('# Parent %s\n' % hex(parents[1])) +fm.data(parents=fm.formatlist(pycompat.maplist(hex, parents), name='node')) + +# TODO: redesign extraexportmap function to support formatter for headerid in extraexport: header = extraexportmap[headerid](seqno, ctx) if header is not None: -write('# %s\n' % header) -write(ctx.description().rstrip()) -write("\n\n") - -for chunk, label in patch.diffui(repo, prev, node, match, opts=diffopts): -write(chunk, label=label) +fm.plain('# %s\n' % header) + +fm.write('desc', '%s\n', ctx.description().rstrip()) +fm.plain('\n') + +if fm.isplain(): +chunkiter = patch.diffui(repo, prev, node, match, opts=diffopts) +for chunk, label in chunkiter: +fm.plain(chunk, label=label) +else: +chunkiter = patch.diff(repo, prev, node, match, opts=diffopts) +# TODO: make it structured? +fm.data(diff=b''.join(chunkiter)) def _exportfile(repo, revs, fp, switch_parent, diffopts, match): """Export changesets to stdout or a single file""" dest = '' if fp: dest = getattr(fp, 'name', dest) -def write(s, **kw): -fp.write(s) +fm = formatter.formatter(repo.ui, fp, 'export', {}) else: -write = repo.ui.write +fm = repo.ui.formatter('export', {}) for seqno, rev in enumerate(revs, 1): ctx = repo[rev] if not dest.startswith('<'): repo.ui.note("%s\n" % dest) -_exportsingle(repo, ctx, match, switch_parent, seqno, write, diffopts) +fm.startitem() +_exportsingle(repo, ctx, fm, match, switch_parent, seqno, diffopts) +fm.end() def _exportfntemplate(repo, revs, fntemplate, switch_parent, diffopts, match): """Export changesets to possibly multiple files""" @@ -1584,13 +1595,12 @@ def _exportfntemplate(repo, revs, fntemp filemap.setdefault(dest, []).append((seqno, rev)) for dest in filemap: -with open(dest, 'wb') as fo: +with formatter.openformatter(repo.ui, dest, 'export', {}) as fm: repo.ui.note("%s\n" % dest) -def write(s, **kw): -fo.write(s) for seqno, rev in filemap[dest]: +fm.startitem() ctx = repo[rev] -_exportsingle(repo, ctx, match, switch_parent, seqno, write, +_exportsingle(repo, ctx, fm, match, switch_parent, seqno, diffopts) def export(repo, revs, fntemplate='hg-%h.patch', fp=None, switch_parent=False, ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
[PATCH 9 of 9] export: enable formatter support (API)
# HG changeset patch # User Yuya Nishihara # Date 1523542435 -32400 # Thu Apr 12 23:13:55 2018 +0900 # Node ID 839c77960cd798119d748a6c018874c334b664a4 # Parent 499cfc83b0cba948eec6b1e30998862b7e7fc051 export: enable formatter support (API) This change is basically the same as "hg cat". A formatter object is created by caller. .. api:: ``cmdutil.export()`` takes a formatter as an argument. diff --git a/hgext/extdiff.py b/hgext/extdiff.py --- a/hgext/extdiff.py +++ b/hgext/extdiff.py @@ -82,6 +82,7 @@ from mercurial import ( cmdutil, error, filemerge, +formatter, pycompat, registrar, scmutil, @@ -267,9 +268,11 @@ def dodiff(ui, repo, cmdline, pats, opts label2 = common_file + rev2 else: template = 'hg-%h.patch' -cmdutil.export(repo, [repo[node1a].rev(), repo[node2].rev()], - fntemplate=repo.vfs.reljoin(tmproot, template), - match=matcher) +with formatter.nullformatter(ui, 'extdiff', {}) as fm: +cmdutil.export(repo, [repo[node1a].rev(), repo[node2].rev()], + fm, + fntemplate=repo.vfs.reljoin(tmproot, template), + match=matcher) label1a = cmdutil.makefilename(repo[node1a], template) label2 = cmdutil.makefilename(repo[node2], template) dir1a = repo.vfs.reljoin(tmproot, label1a) diff --git a/mercurial/cmdutil.py b/mercurial/cmdutil.py --- a/mercurial/cmdutil.py +++ b/mercurial/cmdutil.py @@ -1565,24 +1565,17 @@ def _exportsingle(repo, ctx, fm, match, # TODO: make it structured? fm.data(diff=b''.join(chunkiter)) -def _exportfile(repo, revs, fp, switch_parent, diffopts, match): +def _exportfile(repo, revs, fm, dest, switch_parent, diffopts, match): """Export changesets to stdout or a single file""" -dest = '' -if fp: -dest = getattr(fp, 'name', dest) -fm = formatter.formatter(repo.ui, fp, 'export', {}) -else: -fm = repo.ui.formatter('export', {}) - for seqno, rev in enumerate(revs, 1): ctx = repo[rev] if not dest.startswith('<'): repo.ui.note("%s\n" % dest) fm.startitem() _exportsingle(repo, ctx, fm, match, switch_parent, seqno, diffopts) -fm.end() - -def _exportfntemplate(repo, revs, fntemplate, switch_parent, diffopts, match): + +def _exportfntemplate(repo, revs, basefm, fntemplate, switch_parent, diffopts, + match): """Export changesets to possibly multiple files""" total = len(revs) revwidth = max(len(str(rev)) for rev in revs) @@ -1595,7 +1588,7 @@ def _exportfntemplate(repo, revs, fntemp filemap.setdefault(dest, []).append((seqno, rev)) for dest in filemap: -with formatter.openformatter(repo.ui, dest, 'export', {}) as fm: +with formatter.maybereopen(basefm, dest) as fm: repo.ui.note("%s\n" % dest) for seqno, rev in filemap[dest]: fm.startitem() @@ -1603,13 +1596,14 @@ def _exportfntemplate(repo, revs, fntemp _exportsingle(repo, ctx, fm, match, switch_parent, seqno, diffopts) -def export(repo, revs, fntemplate='hg-%h.patch', switch_parent=False, +def export(repo, revs, basefm, fntemplate='hg-%h.patch', switch_parent=False, opts=None, match=None): '''export changesets as hg patches Args: repo: The repository from which we're exporting revisions. revs: A list of revisions to export as revision numbers. + basefm: A formatter to which patches should be written. fntemplate: An optional string to use for generating patch file names. switch_parent: If True, show diffs against second parent when not nullid. Default is false, which always shows diff against p1. @@ -1624,16 +1618,19 @@ def export(repo, revs, fntemplate='hg-%h destinations: fntemplate specified: Each rev is written to a unique file named using the given template. -Otherwise: All revs written to repo.ui.write() +Otherwise: All revs will be written to basefm. ''' if not fntemplate: -_exportfile(repo, revs, None, switch_parent, opts, match) +_exportfile(repo, revs, basefm, '', switch_parent, opts, match) else: -_exportfntemplate(repo, revs, fntemplate, switch_parent, opts, match) +_exportfntemplate(repo, revs, basefm, fntemplate, switch_parent, opts, + match) def exportfile(repo, revs, fp, switch_parent=False, opts=None, match=None): """Export changesets to the given file stream""" -_exportfile(repo, revs, fp, switch_parent, opts, match) +dest = getattr(fp, 'name', '') +with formatter.formatter(repo.ui, fp, 'export', {}) as fm: +_exportfile(
D2854: hgweb: use our forked wsgiheaders module instead of stdlib one
durin42 updated this revision to Diff 8074. REPOSITORY rHG Mercurial CHANGES SINCE LAST UPDATE https://phab.mercurial-scm.org/D2854?vs=8009&id=8074 REVISION DETAIL https://phab.mercurial-scm.org/D2854 AFFECTED FILES mercurial/hgweb/request.py CHANGE DETAILS diff --git a/mercurial/hgweb/request.py b/mercurial/hgweb/request.py --- a/mercurial/hgweb/request.py +++ b/mercurial/hgweb/request.py @@ -8,7 +8,6 @@ from __future__ import absolute_import -import wsgiref.headers as wsgiheaders #import wsgiref.validate from ..thirdparty import ( @@ -289,6 +288,7 @@ if k.startswith('HTTP_'): headers.append((k[len('HTTP_'):].replace('_', '-'), v)) +from . import wsgiheaders # avoid cycle headers = wsgiheaders.Headers(headers) # This is kind of a lie because the HTTP header wasn't explicitly @@ -378,6 +378,7 @@ self._startresponse = startresponse self.status = None +from . import wsgiheaders # avoid cycle self.headers = wsgiheaders.Headers([]) self._bodybytes = None 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
Re: [PATCH 1 of 9] formatter: remove unused private attributes from baseformatter
On Thu, Apr 12, 2018 at 9:17 AM, Yuya Nishihara wrote: > # HG changeset patch > # User Yuya Nishihara > # Date 1523543073 -32400 > # Thu Apr 12 23:24:33 2018 +0900 > # Node ID e6609e390f284931c10f06f3c8258769fad9bbc5 > # Parent 9c7a25ef5b49f3ce2fe698b58246b622ca9fd382 > formatter: remove unused private attributes from baseformatter > Queued this series with great delight, thanks! This is infinitely better than my hacky series which was attempting to add CBOR support. Thank you for coding this up. > > No idea what they were for. > AFAICT they are as old as this class and weren't even used when the class was introduced! (3c0327ea20c0). > > diff --git a/mercurial/formatter.py b/mercurial/formatter.py > --- a/mercurial/formatter.py > +++ b/mercurial/formatter.py > @@ -160,8 +160,6 @@ class baseformatter(object): > def __init__(self, ui, topic, opts, converter): > self._ui = ui > self._topic = topic > -self._style = opts.get("style") > -self._template = opts.get("template") > self._converter = converter > self._item = None > # function to convert node to string suitable for this output > ___ > 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
Re: [PATCH 7 of 9] export: port _exportsingle() to formatter
On Thu, Apr 12, 2018 at 9:17 AM, Yuya Nishihara wrote: > # HG changeset patch > # User Yuya Nishihara > # Date 1523540383 -32400 > # Thu Apr 12 22:39:43 2018 +0900 > # Node ID 6041c9cdcee8f25328016f1727055d1bc1677054 > # Parent 724b281e9d9b9ebd91d5ab12482f93a25efb1259 > export: port _exportsingle() to formatter > > Pass 'fm' instead of 'write', and use fm.plain(), fm.write(), etc. instead. > The callers will be updated later. > > diff --git a/mercurial/cmdutil.py b/mercurial/cmdutil.py > --- a/mercurial/cmdutil.py > +++ b/mercurial/cmdutil.py > @@ -1522,7 +1522,7 @@ extraexport = [] > # it is given two arguments (sequencenumber, changectx) > extraexportmap = {} > > -def _exportsingle(repo, ctx, match, switch_parent, seqno, write, > diffopts): > +def _exportsingle(repo, ctx, fm, match, switch_parent, seqno, diffopts): > node = scmutil.binnode(ctx) > parents = [p.node() for p in ctx.parents() if p] > branch = ctx.branch() > @@ -1534,42 +1534,53 @@ def _exportsingle(repo, ctx, match, swit > else: > prev = nullid > > -write("# HG changeset patch\n") > -write("# User %s\n" % ctx.user()) > -write("# Date %d %d\n" % ctx.date()) > -write("# %s\n" % dateutil.datestr(ctx.date())) > -if branch and branch != 'default': > -write("# Branch %s\n" % branch) > -write("# Node ID %s\n" % hex(node)) > -write("# Parent %s\n" % hex(prev)) > +fm.context(ctx=ctx) > +fm.plain('# HG changeset patch\n') > +fm.write('user', '# User %s\n', ctx.user()) > +fm.plain('# Date %d %d\n' % ctx.date()) > +fm.write('date', '# %s\n', fm.formatdate(ctx.date())) > +fm.condwrite(branch and branch != 'default', > + 'branch', '# Branch %s\n', branch) > +fm.write('node', '# Node ID %s\n', hex(node)) > +fm.plain('# Parent %s\n' % hex(prev)) > if len(parents) > 1: > -write("# Parent %s\n" % hex(parents[1])) > - > +fm.plain('# Parent %s\n' % hex(parents[1])) > +fm.data(parents=fm.formatlist(pycompat.maplist(hex, parents), > name='node')) > + > +# TODO: redesign extraexportmap function to support formatter > for headerid in extraexport: > header = extraexportmap[headerid](seqno, ctx) > if header is not None: > -write('# %s\n' % header) > -write(ctx.description().rstrip()) > -write("\n\n") > - > -for chunk, label in patch.diffui(repo, prev, node, match, > opts=diffopts): > -write(chunk, label=label) > +fm.plain('# %s\n' % header) > + > +fm.write('desc', '%s\n', ctx.description().rstrip()) > +fm.plain('\n') > + > +if fm.isplain(): > +chunkiter = patch.diffui(repo, prev, node, match, opts=diffopts) > +for chunk, label in chunkiter: > +fm.plain(chunk, label=label) > +else: > +chunkiter = patch.diff(repo, prev, node, match, opts=diffopts) > +# TODO: make it structured? > +fm.data(diff=b''.join(chunkiter)) > A concern I have is that we'll want to keep the door open for writing the diff chunks in a structured manner. That would seemingly require a different key for the templater. But I think "diff" is fine as the key that means "a textual diff format recognized by most patch tools." We can introduce a "diffparts" (or similar) and make "diff" lazily evaluate as follow-ups, when needed. > > def _exportfile(repo, revs, fp, switch_parent, diffopts, match): > """Export changesets to stdout or a single file""" > dest = '' > if fp: > dest = getattr(fp, 'name', dest) > -def write(s, **kw): > -fp.write(s) > +fm = formatter.formatter(repo.ui, fp, 'export', {}) > else: > -write = repo.ui.write > +fm = repo.ui.formatter('export', {}) > > for seqno, rev in enumerate(revs, 1): > ctx = repo[rev] > if not dest.startswith('<'): > repo.ui.note("%s\n" % dest) > -_exportsingle(repo, ctx, match, switch_parent, seqno, write, > diffopts) > +fm.startitem() > +_exportsingle(repo, ctx, fm, match, switch_parent, seqno, > diffopts) > +fm.end() > > def _exportfntemplate(repo, revs, fntemplate, switch_parent, diffopts, > match): > """Export changesets to possibly multiple files""" > @@ -1584,13 +1595,12 @@ def _exportfntemplate(repo, revs, fntemp > filemap.setdefault(dest, []).append((seqno, rev)) > > for dest in filemap: > -with open(dest, 'wb') as fo: > +with formatter.openformatter(repo.ui, dest, 'export', {}) as fm: > repo.ui.note("%s\n" % dest) > -def write(s, **kw): > -fo.write(s) > for seqno, rev in filemap[dest]: > +fm.startitem() > ctx = repo[rev] > -_exportsingle(repo, ctx, match, switch_parent, seqno, > write, > +_exportsingle(repo, ctx, fm, match, switch_parent, seqno, >
D3245: wsgiheaders: import a bytes-ified fork of wsgiref.headers from cpython@46f5072
indygreg accepted this revision. indygreg added a comment. This revision is now accepted and ready to land. I missed the commit in the commit message. I diffed locally and things look reasonable. I'm adding the original license/header back in flight (preserving our modifications as well). REPOSITORY rHG Mercurial REVISION DETAIL https://phab.mercurial-scm.org/D3245 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
D3253: py3: whitelist another nine passing tests
This revision was automatically updated to reflect the committed changes. Closed by commit rHGe40c8494acfa: py3: whitelist another nine passing tests (authored by durin42, committed by ). REPOSITORY rHG Mercurial CHANGES SINCE LAST UPDATE https://phab.mercurial-scm.org/D3253?vs=8019&id=8077 REVISION DETAIL https://phab.mercurial-scm.org/D3253 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 @@ -91,9 +91,11 @@ test-diff-unified.t test-diff-upgrade.t test-diffdir.t +test-diffstat.t test-directaccess.t test-dirstate-backup.t test-dirstate-nonnormalset.t +test-dirstate.t test-doctest.py test-double-merge.t test-drawdag.t @@ -151,6 +153,7 @@ test-hgk.t test-hgweb-bundle.t test-hgweb-descend-empties.t +test-hgweb-empty.t test-hgweb-removed.t test-histedit-arguments.t test-histedit-base.t @@ -173,6 +176,7 @@ test-import-unknown.t test-import.t test-imports-checker.t +test-incoming-outgoing.t test-inherit-mode.t test-issue1089.t test-issue1102.t @@ -242,11 +246,14 @@ test-mq-git.t test-mq-header-date.t test-mq-header-from.t +test-mq-merge.t test-mq-pull-from-bundle.t +test-mq-qdelete.t test-mq-qdiff.t test-mq-qfold.t test-mq-qgoto.t test-mq-qimport-fail-cleanup.t +test-mq-qnew.t test-mq-qpush-exact.t test-mq-qqueue.t test-mq-qrefresh-interactive.t @@ -347,6 +354,7 @@ test-rebase-issue-noparam-single-rev.t test-rebase-legacy.t test-rebase-mq-skip.t +test-rebase-mq.t test-rebase-named-branches.t test-rebase-newancestor.t test-rebase-obsolete.t @@ -379,6 +387,7 @@ test-run-tests.py test-schemes.t test-serve.t +test-setdiscovery.t test-share.t test-show-stack.t test-show-work.t To: durin42, pulkit, #hg-reviewers, indygreg Cc: mercurial-devel ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
D3245: wsgiheaders: import a bytes-ified fork of wsgiref.headers from cpython@46f5072
This revision was automatically updated to reflect the committed changes. Closed by commit rHG74e1362585c0: wsgiheaders: import a bytes-ified fork of wsgiref.headers from cpython@46f5072 (authored by durin42, committed by ). CHANGED PRIOR TO COMMIT https://phab.mercurial-scm.org/D3245?vs=8014&id=8075#toc REPOSITORY rHG Mercurial CHANGES SINCE LAST UPDATE https://phab.mercurial-scm.org/D3245?vs=8014&id=8075 REVISION DETAIL https://phab.mercurial-scm.org/D3245 AFFECTED FILES mercurial/hgweb/wsgiheaders.py CHANGE DETAILS diff --git a/mercurial/hgweb/wsgiheaders.py b/mercurial/hgweb/wsgiheaders.py new file mode 100644 --- /dev/null +++ b/mercurial/hgweb/wsgiheaders.py @@ -0,0 +1,176 @@ +"""This was forked from cpython's wsgiref.headers module to work on bytes. + +Header from old file showing copyright is below. + +Much of this module is red-handedly pilfered from email.message in the stdlib, +so portions are Copyright (C) 2001,2002 Python Software Foundation, and were +written by Barry Warsaw. +""" + +# Regular expression that matches `special' characters in parameters, the +# existence of which force quoting of the parameter value. +from __future__ import absolute_import, print_function + +import re +tspecials = re.compile(br'[ \(\)<>@,;:\\"/\[\]\?=]') + +def _formatparam(param, value=None, quote=1): +"""Convenience function to format and return a key=value pair. +This will quote the value if needed or if quote is true. +""" +if value is not None and len(value) > 0: +if quote or tspecials.search(value): +value = value.replace('\\', '').replace('"', r'\"') +return '%s="%s"' % (param, value) +else: +return '%s=%s' % (param, value) +else: +return param + + +class Headers(object): +"""Manage a collection of HTTP response headers""" + +def __init__(self, headers=None): +headers = headers if headers is not None else [] +if type(headers) is not list: +raise TypeError("Headers must be a list of name/value tuples") +self._headers = headers +if __debug__: +for k, v in headers: +self._convert_string_type(k) +self._convert_string_type(v) + +def _convert_string_type(self, value): +"""Convert/check value type.""" +if type(value) is bytes: +return value +raise AssertionError(u"Header names/values must be" + u" of type bytes (got %s)" % repr(value)) + +def __len__(self): +"""Return the total number of headers, including duplicates.""" +return len(self._headers) + +def __setitem__(self, name, val): +"""Set the value of a header.""" +del self[name] +self._headers.append( +(self._convert_string_type(name), self._convert_string_type(val))) + +def __delitem__(self, name): +"""Delete all occurrences of a header, if present. +Does *not* raise an exception if the header is missing. +""" +name = self._convert_string_type(name.lower()) +self._headers[:] = [kv for kv in self._headers if kv[0].lower() != name] + +def __getitem__(self, name): +"""Get the first header value for 'name' +Return None if the header is missing instead of raising an exception. +Note that if the header appeared multiple times, the first exactly which +occurrence gets returned is undefined. Use getall() to get all +the values matching a header field name. +""" +return self.get(name) + +def __contains__(self, name): +"""Return true if the message contains the header.""" +return self.get(name) is not None + + +def get_all(self, name): +"""Return a list of all the values for the named field. +These will be sorted in the order they appeared in the original header +list or were added to this instance, and may contain duplicates. Any +fields deleted and re-inserted are always appended to the header list. +If no fields exist with the given name, returns an empty list. +""" +name = self._convert_string_type(name.lower()) +return [kv[1] for kv in self._headers if kv[0].lower()==name] + + +def get(self, name, default=None): +"""Get the first header value for 'name', or return 'default'""" +name = self._convert_string_type(name.lower()) +for k, v in self._headers: +if k.lower()==name: +return v +return default + + +def keys(self): +"""Return a list of all the header field names. +These will be sorted in the order they appeared in the original header +list, or were added to this instance, and may contain duplicates. +Any fields deleted and re-inserted are always appended to the header +list. +""" +return [k for k, v in self._headers] + +
D2854: hgweb: use our forked wsgiheaders module instead of stdlib one
This revision was automatically updated to reflect the committed changes. Closed by commit rHGda84e26d85ed: hgweb: use our forked wsgiheaders module instead of stdlib one (authored by durin42, committed by ). REPOSITORY rHG Mercurial CHANGES SINCE LAST UPDATE https://phab.mercurial-scm.org/D2854?vs=8074&id=8076 REVISION DETAIL https://phab.mercurial-scm.org/D2854 AFFECTED FILES mercurial/hgweb/request.py CHANGE DETAILS diff --git a/mercurial/hgweb/request.py b/mercurial/hgweb/request.py --- a/mercurial/hgweb/request.py +++ b/mercurial/hgweb/request.py @@ -8,7 +8,6 @@ from __future__ import absolute_import -import wsgiref.headers as wsgiheaders #import wsgiref.validate from ..thirdparty import ( @@ -289,6 +288,7 @@ if k.startswith('HTTP_'): headers.append((k[len('HTTP_'):].replace('_', '-'), v)) +from . import wsgiheaders # avoid cycle headers = wsgiheaders.Headers(headers) # This is kind of a lie because the HTTP header wasn't explicitly @@ -378,6 +378,7 @@ self._startresponse = startresponse self.status = None +from . import wsgiheaders # avoid cycle self.headers = wsgiheaders.Headers([]) self._bodybytes = None 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
D3286: py3: whitelist another six passing tests
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/D3286 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 @@ -69,6 +69,7 @@ test-convert-hg-sink.t test-convert-hg-source.t test-convert-hg-startrev.t +test-convert-splicemap.t test-copy-move-merge.t test-copy.t test-copytrace-heuristics.t @@ -137,6 +138,7 @@ test-exchange-obsmarkers-case-D3.t test-exchange-obsmarkers-case-D4.t test-execute-bit.t +test-export.t test-extdiff.t test-extra-filelog-entry.t test-filebranch.t @@ -205,6 +207,7 @@ test-largefiles-small-disk.t test-largefiles-update.t test-lfs-largefiles.t +test-linerange.py test-locate.t test-lock-badness.t test-log-linerange.t @@ -395,7 +398,9 @@ test-simple-update.t test-single-head.t test-sparse-clear.t +test-sparse-import.t test-sparse-merges.t +test-sparse-profiles.t test-sparse-requirement.t test-sparse-verbose-json.t test-ssh-clone-r.t @@ -407,6 +412,7 @@ test-strip-cross.t test-strip.t test-subrepo-deep-nested-change.t +test-subrepo-missing.t test-subrepo.t test-symlinks.t test-tag.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
[PATCH] dispatch: add a whitelist map of commands to implicitly loaded extensions
# HG changeset patch # User Matt Harbison # Date 1523332699 14400 # Mon Apr 09 23:58:19 2018 -0400 # Node ID 986b51f15e9bce19b2f67573ff76612540320d1b # Parent 2e0e61312a257708a70201427b31deba964e9b05 dispatch: add a whitelist map of commands to implicitly loaded extensions This was Augie's idea[1] (or at least my interpretation of it). The goal is to be able to load the lfs extension without user intervention where it is both harmless, and provides a user convenience. The referenced thread discusses the clone command and the cryptic error around that in some cases. But the obvious benefit is to be able transparently support cloning an lfs repository, or the sudden transition to lfs on a pull, without bothering the user. The choice to use the lfs extension in the repository has already been made in both cases at that point, and neither command can accidentally introduce the feature. The implementation is perhaps a bit more than imagined in the thread, because I think there may be room to allow extensions like 'share' to force lfs on too, in order to make the extension usage more invisible. The largefiles extension could probably be given the same treatment. For simplicity, I didn't bother allowing external extensions to be loadable like this. The mechanism used here was pilfered from acl.ensureenabled(). [1] https://www.mercurial-scm.org/pipermail/mercurial-devel/2018-January/109851.html diff --git a/mercurial/dispatch.py b/mercurial/dispatch.py --- a/mercurial/dispatch.py +++ b/mercurial/dispatch.py @@ -48,6 +48,15 @@ from .utils import ( unrecoverablewrite = registrar.command.unrecoverablewrite +# Map a command to a list of extensions that are forced on prior to running the +# command (unless it has been explicitly disabled.) The idea is to help the +# user by enabling extensions implicitly when requirements may be added by a +# remote exchange, instead of erroring out after a partial exchange. +extensionwhitelist = { +commands.clone: ['lfs'], +commands.pull: ['lfs'], +} + class request(object): def __init__(self, args, ui=None, repo=None, fin=None, fout=None, ferr=None, prereposetups=None): @@ -843,6 +852,20 @@ def _dispatch(req): fullargs = args cmd, func, args, options, cmdoptions = _parse(lui, args) +# resolve aliases back to the core function +entrypoint = func +if isinstance(entrypoint, cmdalias): +entrypoint = entrypoint.fn + +if entrypoint in extensionwhitelist: +configured = [ext for (ext, _path) in ui.configitems("extensions")] +missing = [ext for ext in extensionwhitelist[entrypoint] + if ext not in configured] +for ext in missing: +ui.setconfig('extensions', ext, '', source='internal') +if missing: +extensions.loadall(ui, missing) + if options["config"] != req.earlyoptions["config"]: raise error.Abort(_("option --config may not be abbreviated!")) if options["cwd"] != req.earlyoptions["cwd"]: diff --git a/tests/test-clonebundles.t b/tests/test-clonebundles.t --- a/tests/test-clonebundles.t +++ b/tests/test-clonebundles.t @@ -26,12 +26,13 @@ Missing manifest should not result in se adding manifests adding file changes added 2 changesets with 2 changes to 2 files + calling hook pretxnchangegroup.lfs: hgext.lfs.checkrequireslfs new changesets 53245c60e682:aaff8d2ffbbf $ cat server/access.log * - - [*] "GET /?cmd=capabilities HTTP/1.1" 200 - (glob) $LOCALIP - - [$LOGDATE$] "GET /?cmd=batch HTTP/1.1" 200 - x-hgarg-1:cmds=heads+%3Bknown+nodes%3D x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull (glob) - $LOCALIP - - [$LOGDATE$] "GET /?cmd=getbundle HTTP/1.1" 200 - x-hgarg-1:bookmarks=1&$USUAL_BUNDLE_CAPS$&cg=1&common=&heads=aaff8d2ffbbf07a46dd1f05d8ae7877e3f56e2a2&listkeys=bookmarks&phases=1 x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull (glob) + $LOCALIP - - [$LOGDATE$] "GET /?cmd=getbundle HTTP/1.1" 200 - x-hgarg-1:bookmarks=1&bundlecaps=HG20%2Cbundle2%3DHG20%250Abookmarks%250Achangegroup%253D01%252C02%252C03%250Adigests%253Dmd5%252Csha1%252Csha512%250Aerror%253Dabort%252Cunsupportedcontent%252Cpushraced%252Cpushkey%250Ahgtagsfnodes%250Alistkeys%250Aphases%253Dheads%250Apushkey%250Aremote-changegroup%253Dhttp%252Chttps%250Arev-branch-cache%250Astream%253Dv2&cg=1&common=&heads=aaff8d2ffbbf07a46dd1f05d8ae7877e3f56e2a2&listkeys=bookmarks&phases=1 x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull (glob) Empty manifest file results in retrieval (the extension only checks if the manifest file exists) @@ -44,6 +45,7 @@ Empty manifest file results in retrieval adding manifests adding file changes added 2 changesets with 2 changes to 2 files + calling hook pretxnchangegroup.lfs: hgext.lfs.checkrequireslfs
D2880: bundle: add the possibility to bundle bookmarks (issue5792)
lothiraldan added a comment. In https://phab.mercurial-scm.org/D2880#52559, @indygreg wrote: > What's the status of this patch? Is it still reviewable? If so, let's get a rebased version submitted, just in case things have changed. I need to update the patch according to @martinvoz comment. I was also waiting on your comment on https://phab.mercurial-scm.org/D2880#46263, do you think we will keep the option once the bundlespec system is revamped? If yes, we can make the config option a non-experimental one. But if it will be dropped soon, I think keeping it experimental until it's dropped is preferable. What do you think? REPOSITORY rHG Mercurial REVISION DETAIL https://phab.mercurial-scm.org/D2880 To: lothiraldan, #hg-reviewers, indygreg Cc: martinvonz, indygreg, pulkit, mercurial-devel ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
D3286: py3: whitelist another six passing tests
This revision was automatically updated to reflect the committed changes. Closed by commit rHGfa4b39bb0a07: py3: whitelist another six passing tests (authored by durin42, committed by ). REPOSITORY rHG Mercurial CHANGES SINCE LAST UPDATE https://phab.mercurial-scm.org/D3286?vs=8078&id=8079 REVISION DETAIL https://phab.mercurial-scm.org/D3286 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 @@ -69,6 +69,7 @@ test-convert-hg-sink.t test-convert-hg-source.t test-convert-hg-startrev.t +test-convert-splicemap.t test-copy-move-merge.t test-copy.t test-copytrace-heuristics.t @@ -137,6 +138,7 @@ test-exchange-obsmarkers-case-D3.t test-exchange-obsmarkers-case-D4.t test-execute-bit.t +test-export.t test-extdiff.t test-extra-filelog-entry.t test-filebranch.t @@ -205,6 +207,7 @@ test-largefiles-small-disk.t test-largefiles-update.t test-lfs-largefiles.t +test-linerange.py test-locate.t test-lock-badness.t test-log-linerange.t @@ -395,7 +398,9 @@ test-simple-update.t test-single-head.t test-sparse-clear.t +test-sparse-import.t test-sparse-merges.t +test-sparse-profiles.t test-sparse-requirement.t test-sparse-verbose-json.t test-ssh-clone-r.t @@ -407,6 +412,7 @@ test-strip-cross.t test-strip.t test-subrepo-deep-nested-change.t +test-subrepo-missing.t test-subrepo.t test-symlinks.t test-tag.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
D3288: discovery: use command executor interface
indygreg created this revision. Herald added a subscriber: mercurial-devel. Herald added a reviewer: hg-reviewers. REVISION SUMMARY We're trying to port all wire protocol code to use the new interface so we can implement wire protocol version 2 clients. REPOSITORY rHG Mercurial REVISION DETAIL https://phab.mercurial-scm.org/D3288 AFFECTED FILES mercurial/discovery.py CHANGE DETAILS diff --git a/mercurial/discovery.py b/mercurial/discovery.py --- a/mercurial/discovery.py +++ b/mercurial/discovery.py @@ -203,7 +203,11 @@ headssum = {} # A. Create set of branches involved in the push. branches = set(repo[n].branch() for n in outgoing.missing) -remotemap = remote.branchmap() + +with remote.commandexecutor() as e: +fremotemap = e.callcommand('branchmap', {}) + +remotemap = fremotemap.result() newbranches = branches - set(remotemap) branches.difference_update(newbranches) @@ -287,7 +291,13 @@ repo = pushop.repo.unfiltered() remote = pushop.remote localbookmarks = repo._bookmarks -remotebookmarks = remote.listkeys('bookmarks') + +with remote.commandexecutor() as e: +fremotebookmarks = e.callcommand('listkeys', { +'namespace': 'bookmarks', +}) + +remotebookmarks = fremotebookmarks.result() bookmarkedheads = set() # internal config: bookmarks.pushing 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
D3290: logexchange: use command executor for wire protocol commands
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/D3290 AFFECTED FILES mercurial/logexchange.py CHANGE DETAILS diff --git a/mercurial/logexchange.py b/mercurial/logexchange.py --- a/mercurial/logexchange.py +++ b/mercurial/logexchange.py @@ -127,14 +127,25 @@ remoterepo is the peer instance """ remotepath = activepath(localrepo, remoterepo) -bookmarks = remoterepo.listkeys('bookmarks') + +with remoterepo.commandexecutor() as e: +fbookmarks = e.callcommand('listkeys', { +'namespace': 'bookmarks', +}) + +bookmarks = fbookmarks.result() + # on a push, we don't want to keep obsolete heads since # they won't show up as heads on the next pull, so we # remove them here otherwise we would require the user # to issue a pull to refresh the storage bmap = {} repo = localrepo.unfiltered() -for branch, nodes in remoterepo.branchmap().iteritems(): + +with remoterepo.commandexecutor() as e: +fbranchmap = e.callcommand('branchmap', {}) + +for branch, nodes in fbranchmap.result().iteritems(): bmap[branch] = [] for node in nodes: if node in repo and not repo[node].obsolete(): 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
D3289: streamclone: use command executor for wire protocol commands
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/D3289 AFFECTED FILES mercurial/streamclone.py CHANGE DETAILS diff --git a/mercurial/streamclone.py b/mercurial/streamclone.py --- a/mercurial/streamclone.py +++ b/mercurial/streamclone.py @@ -126,11 +126,21 @@ # creation. rbranchmap = None if remote.capable('branchmap'): -rbranchmap = remote.branchmap() +with remote.commandexecutor() as e: +frbranchmap = e.callcommand('branchmap', {}) + +rbranchmap = frbranchmap.result() repo.ui.status(_('streaming all changes\n')) -fp = remote.stream_out() +with remote.commandexecutor() as e: +f = e.callcommand('stream_out', {}) + +# TODO strictly speaking, this should be inside the context manager +# because the context manager is supposed to ensure all wire state +# is flushed when exiting. But the legacy peers don't do this, so it +# doesn't matter. +fp = f.result() l = fp.readline() try: resp = int(l) 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
D3287: discovery: don't redundantly call branchmap
indygreg created this revision. Herald added a subscriber: mercurial-devel. Herald added a reviewer: hg-reviewers. REVISION SUMMARY We were calling the remote command twice without mutation the remote in between. Derp. REPOSITORY rHG Mercurial REVISION DETAIL https://phab.mercurial-scm.org/D3287 AFFECTED FILES mercurial/discovery.py tests/test-http-bundle1.t tests/test-http.t tests/test-treediscovery.t CHANGE DETAILS diff --git a/tests/test-treediscovery.t b/tests/test-treediscovery.t --- a/tests/test-treediscovery.t +++ b/tests/test-treediscovery.t @@ -537,7 +537,6 @@ "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=phases x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=bookmarks x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull "GET /?cmd=branchmap HTTP/1.1" 200 - x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull - "GET /?cmd=branchmap HTTP/1.1" 200 - x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=bookmarks x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull "POST /?cmd=unbundle HTTP/1.1" 200 - x-hgarg-1:heads=686173686564+1827a5bb63e602382eb89dd58f2ac9f3b007ad91* (glob) "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=phases x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull diff --git a/tests/test-http.t b/tests/test-http.t --- a/tests/test-http.t +++ b/tests/test-http.t @@ -296,11 +296,6 @@ devel-peer-request: Vary X-HgProto-1 devel-peer-request: X-hgproto-1 0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull devel-peer-request: finished in *. seconds (200) (glob) - sending branchmap command - devel-peer-request: GET http://localhost:$HGPORT2/?cmd=branchmap - devel-peer-request: Vary X-HgProto-1 - devel-peer-request: X-hgproto-1 0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull - devel-peer-request: finished in *. seconds (200) (glob) preparing listkeys for "bookmarks" sending listkeys command devel-peer-request: GET http://localhost:$HGPORT2/?cmd=listkeys @@ -395,7 +390,6 @@ "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=phases x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=bookmarks x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull "GET /?cmd=branchmap HTTP/1.1" 200 - x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull - "GET /?cmd=branchmap HTTP/1.1" 200 - x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=bookmarks x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull "POST /?cmd=unbundle HTTP/1.1" 200 - x-hgarg-1:heads=666f726365* (glob) "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=phases x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull @@ -405,7 +399,6 @@ "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=phases x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=bookmarks x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull "GET /?cmd=branchmap HTTP/1.1" 200 - x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull - "GET /?cmd=branchmap HTTP/1.1" 200 - x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=bookmarks x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull "POST /?cmd=unbundle HTTP/1.1" 200 - x-hgarg-1:heads=666f726365 x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=phases x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull diff --git a/tests/test-http-bundle1.t b/tests/test-http-bundle1.t --- a/tests/test-http-bundle1.t +++ b/tests/test-http-bundle1.t @@ -316,7 +316,6 @@ "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=phases x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=bookmarks x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull "GET /?cmd=branchmap HTTP/1.1" 200 - x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull - "GET /?cmd=branchmap HTTP/1.1" 200 - x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=bookmarks x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull "POST /?cmd=unbundle HTTP/1.1" 200 - x-hgarg-1:heads=686173686564+5eb5abfefeea63c80dd7553bcc3783f37e0c5524* (glob) "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=phases x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull diff --git a/mercurial/discovery.py b/mercurial/discovery.py --- a/mercurial/discovery.py +++ b/mercurial/discovery.py @@ -209,7 +209,7 @@ # A. register remote heads remotebranches = s
D3294: bundlerepo: use command executor for wire protocol commands
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/D3294 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 @@ -540,17 +540,32 @@ and peer.capable('getbundle') and peer.capable('bundle2')) if canbundle2: -kwargs = {} -kwargs[r'common'] = common -kwargs[r'heads'] = rheads -kwargs[r'bundlecaps'] = exchange.caps20to10(repo, role='client') -kwargs[r'cg'] = True -b2 = peer.getbundle('incoming', **kwargs) -fname = bundle = changegroup.writechunks(ui, b2._forwardchunks(), - bundlename) +with peer.commandexecutor() as e: +fincoming = e.callcommand('getbundle', { +'source': 'incoming', +'common': common, +'heads': rheads, +'bundlecaps': exchange.caps20to10(repo, role='client'), +'cg': True, +}) + +e.sendcommands() +b2 = fincoming.result() + +fname = bundle = changegroup.writechunks(ui, + b2._forwardchunks(), + bundlename) else: if peer.capable('getbundle'): -cg = peer.getbundle('incoming', common=common, heads=rheads) +with peer.commandexecutor() as e: +fincoming = e.callcommand('getbundle', { +'source': 'incoming', +'common': common, +'heads': rheads, +}) + +e.sendcommands() +cg = fincoming.result() elif onlyheads is None and not peer.capable('changegroupsubset'): # compat with older servers when pulling all remote heads @@ -596,7 +611,13 @@ if bundlerepo: reponodes = [ctx.node() for ctx in bundlerepo[bundlerepo.firstnewrev:]] -remotephases = peer.listkeys('phases') + +with peer.commandexecutor() as e: +flistkeys = e.callcommand('listkeys', { +'namespace': 'phases', +}) + +remotephases = flistkeys.result() pullop = exchange.pulloperation(bundlerepo, peer, heads=reponodes) pullop.trmanager = bundletransactionmanager() 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
D3291: hg: use command executor for wire protocol commands
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/D3291 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 @@ -81,7 +81,11 @@ raise error.Abort(_("remote branch lookup not supported")) revs.append(hashbranch) return revs, revs[0] -branchmap = peer.branchmap() + +with peer.commandexecutor() as e: +fbranchmap = e.callcommand('branchmap', {}) + +branchmap = fbranchmap.result() def primary(branch): if branch == '.': @@ -421,7 +425,17 @@ raise error.Abort(_("src repository does not support " "revision lookup and so doesn't " "support clone by revision")) -revs = [srcpeer.lookup(r) for r in rev] + +remoterevs = [] +for r in rev: +with srcpeer.commandexecutor() as e: +frev = e.callcommand('lookup', { +'key': r, +}) + +remoterevs.append(frev.result()) + +revs = remoterevs # Obtain a lock before checking for or cloning the pooled repo otherwise # 2 clients may race creating or populating it. @@ -567,7 +581,13 @@ # raises RepoLookupError if revision 0 is filtered or otherwise # not available. If we fail to resolve, sharing is not enabled. try: -rootnode = srcpeer.lookup('0') +with srcpeer.commandexecutor() as e: +frootnode = e.callcommand('lookup', { +'key': '0', +}) + +rootnode = frootnode.result() + if rootnode != node.nullid: sharepath = os.path.join(sharepool, node.hex(rootnode)) else: @@ -663,7 +683,17 @@ raise error.Abort(_("src repository does not support " "revision lookup and so doesn't " "support clone by revision")) -revs = [srcpeer.lookup(r) for r in revs] + +remoterevs = [] +for rev in revs: +with srcpeer.commandexecutor() as e: +frev = e.callcommand('lookup', { +'key': rev, +}) + +remoterevs.append(frev.result()) + +revs = remoterevs checkout = revs[0] else: revs = None @@ -705,7 +735,13 @@ if update: if update is not True: -checkout = srcpeer.lookup(update) +with srcpeer.commandexecutor() as e: +fcheckout = e.callcommand('lookup', { +'key': update, +}) + +checkout = fcheckout.result() + uprev = None status = None if checkout is not None: 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
D3297: httppeer: implement command executor for version 2 peer
indygreg created this revision. Herald added a subscriber: mercurial-devel. Herald added a reviewer: hg-reviewers. REVISION SUMMARY Now that we have a new API for issuing commands which is compatible with wire protocol version 2, we can start using it with wire protocol version 2. This commit replaces our hacky implementation of _call() with something a bit more robust based on the new command executor interface. We now have proper support for issuing multiple commands per HTTP request. Each HTTP request maintains its own client reactor. The implementation is similar to the one in the legacy wire protocol. We use a ThreadPoolExecutor for spinning up a thread to read the HTTP response in the background. This allows responses to resolve in any order. While not implemented on the server yet, a client could use concurrent.futures.as_completed() with a collection of futures and handle responses as they arrive from the server. The return value from issued commands is still a simple list of raw or decoded CBOR data. This is still super hacky. We will want a rich data type for representing command responses. But at least this commit gets us one step closer to a proper peer implementation. REPOSITORY rHG Mercurial REVISION DETAIL https://phab.mercurial-scm.org/D3297 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 @@ -13,7 +13,9 @@ import os import socket import struct +import sys import tempfile +import weakref from .i18n import _ from .thirdparty import ( @@ -31,7 +33,6 @@ statichttprepo, url as urlmod, util, -wireproto, wireprotoframing, wireprototypes, wireprotov1peer, @@ -517,8 +518,237 @@ def _abort(self, exception): raise exception +def sendv2request(ui, opener, requestbuilder, apiurl, permission, requests): +reactor = wireprotoframing.clientreactor(hasmultiplesend=False, + buffersends=True) + +url = '%s/%s' % (apiurl, permission) + +if len(requests) > 1: +url += '/multirequest' +else: +url += '/%s' % requests[0][0] + +# Request ID to (request, future) +requestmap = {} + +for command, args, f in requests: +request, action, meta = reactor.callcommand(command, args) +assert action == 'noop' + +requestmap[request.requestid] = (request, f) + +action, meta = reactor.flushcommands() +assert action == 'sendframes' + +# TODO stream this. +body = b''.join(map(bytes, meta['framegen'])) + +# TODO modify user-agent to reflect v2 +headers = { +r'Accept': wireprotov2server.FRAMINGTYPE, +r'Content-Type': wireprotov2server.FRAMINGTYPE, +} + +req = requestbuilder(pycompat.strurl(url), body, headers) +req.add_unredirected_header(r'Content-Length', r'%d' % len(body)) + +try: +res = opener.open(req) +except urlerr.httpeeror as e: +if e.code == 401: +raise error.Abort(_('authorization failed')) + +raise +except httplib.HTTPException as e: +ui.traceback() +raise IOError(None, e) + +return reactor, requestmap, res + +@zi.implementer(repository.ipeercommandexecutor) +class httpv2executor(object): +def __init__(self, ui, opener, requestbuilder, apiurl, descriptor): +self._ui = ui +self._opener = opener +self._requestbuilder = requestbuilder +self._apiurl = apiurl +self._descriptor = descriptor +self._sent = False +self._closed = False +self._neededpermissions = set() +self._calls = [] +self._futures = weakref.WeakSet() +self._responseexecutor = None +self._responsef = None + +def __enter__(self): +return self + +def __exit__(self, exctype, excvalue, exctb): +self.close() + +def callcommand(self, command, args): +if self._sent: +raise error.ProgrammingError('callcommand() cannot be used after ' + 'sendcommands()') + +if self._closed: +raise error.ProgrammingError('callcommand() cannot be used after ' + 'close()') + +# The service advertises which commands are available. So if we attempt +# to call an unknown command or pass an unknown argument, we can screen +# for this. +if command not in self._descriptor['commands']: +raise error.ProgrammingError( +'wire protocol command %s is not available' % command) + +cmdinfo = self._descriptor['commands'][command] +unknownargs = set(args.keys()) - set(cmdinfo.get('args', {})) + +if unknownargs: +raise error.ProgrammingError( +'wire protocol command %s does not accept argument: %s' %
D3295: wireproto: rename HTTPV2 so it less like HTTP/2
indygreg created this revision. Herald added a subscriber: mercurial-devel. Herald added a reviewer: hg-reviewers. REVISION SUMMARY Per review suggestion on https://phab.mercurial-scm.org/D3230 from Augie. REPOSITORY rHG Mercurial REVISION DETAIL https://phab.mercurial-scm.org/D3295 AFFECTED FILES mercurial/debugcommands.py mercurial/httppeer.py mercurial/wireprotoserver.py mercurial/wireprototypes.py mercurial/wireprotov2server.py CHANGE DETAILS diff --git a/mercurial/wireprotov2server.py b/mercurial/wireprotov2server.py --- a/mercurial/wireprotov2server.py +++ b/mercurial/wireprotov2server.py @@ -27,7 +27,7 @@ FRAMINGTYPE = b'application/mercurial-exp-framing-0003' -HTTPV2 = wireprototypes.HTTPV2 +HTTP_WIREPROTO_V2 = wireprototypes.HTTP_WIREPROTO_V2 def handlehttpv2request(rctx, req, res, checkperm, urlparts): from .hgweb import common as hgwebcommon @@ -332,7 +332,7 @@ @property def name(self): -return HTTPV2 +return HTTP_WIREPROTO_V2 def getargs(self, args): data = {} diff --git a/mercurial/wireprototypes.py b/mercurial/wireprototypes.py --- a/mercurial/wireprototypes.py +++ b/mercurial/wireprototypes.py @@ -18,7 +18,7 @@ # These are advertised over the wire. Increment the counters at the end # to reflect BC breakages. SSHV2 = 'exp-ssh-v2-0001' -HTTPV2 = 'exp-http-v2-0001' +HTTP_WIREPROTO_V2 = 'exp-http-v2-0001' # All available wire protocol transports. TRANSPORTS = { @@ -35,7 +35,7 @@ 'transport': 'http', 'version': 1, }, -HTTPV2: { +HTTP_WIREPROTO_V2: { 'transport': 'http', 'version': 2, } diff --git a/mercurial/wireprotoserver.py b/mercurial/wireprotoserver.py --- a/mercurial/wireprotoserver.py +++ b/mercurial/wireprotoserver.py @@ -307,7 +307,7 @@ #Callable receiving (req, repo) that is called to obtain an API #descriptor for this service. The response must be serializable to CBOR. API_HANDLERS = { -wireprotov2server.HTTPV2: { +wireprotov2server.HTTP_WIREPROTO_V2: { 'config': ('experimental', 'web.api.http-v2'), 'handler': wireprotov2server.handlehttpv2request, 'apidescriptor': wireprotov2server.httpv2apidescriptor, diff --git a/mercurial/httppeer.py b/mercurial/httppeer.py --- a/mercurial/httppeer.py +++ b/mercurial/httppeer.py @@ -672,7 +672,7 @@ #Integer priority for the service. If we could choose from multiple #services, we choose the one with the highest priority. API_PEERS = { -wireprototypes.HTTPV2: { +wireprototypes.HTTP_WIREPROTO_V2: { 'init': httpv2peer, 'priority': 50, }, diff --git a/mercurial/debugcommands.py b/mercurial/debugcommands.py --- a/mercurial/debugcommands.py +++ b/mercurial/debugcommands.py @@ -2912,7 +2912,7 @@ if opts['peer'] == 'http2': ui.write(_('creating http peer for wire protocol version 2\n')) peer = httppeer.httpv2peer( -ui, path, 'api/%s' % wireprototypes.HTTPV2, +ui, path, 'api/%s' % wireprototypes.HTTP_WIREPROTO_V2, opener, httppeer.urlreq.request, {}) elif opts['peer'] == 'raw': ui.write(_('using raw connection to peer\n')) 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
D3298: debugcommands: use command executor for invoking commands
indygreg created this revision. Herald added a subscriber: mercurial-devel. Herald added a reviewer: hg-reviewers. REVISION SUMMARY Now that all peers support the command executor interface, we can use it in place of peer._call() (which isn't part of the public API). Tests changed because we are now returning the decoded response instead of the raw bytes. The raw bytes over the wire are already logged. So we're not losing any test coverage. In fact, we're adding test coverage because we're testing decoding of those command responses as well. REPOSITORY rHG Mercurial REVISION DETAIL https://phab.mercurial-scm.org/D3298 AFFECTED FILES mercurial/debugcommands.py tests/test-http-protocol.t tests/test-ssh-proto.t CHANGE DETAILS diff --git a/tests/test-ssh-proto.t b/tests/test-ssh-proto.t --- a/tests/test-ssh-proto.t +++ b/tests/test-ssh-proto.t @@ -1367,7 +1367,7 @@ o> bookmarks\t\n o> namespaces\t\n o> phases\t - response: b'bookmarks\t\nnamespaces\t\nphases\t' + response: {b'bookmarks': b'', b'namespaces': b'', b'phases': b''} testing ssh2 creating ssh peer from handshake results @@ -1398,7 +1398,7 @@ o> bookmarks\t\n o> namespaces\t\n o> phases\t - response: b'bookmarks\t\nnamespaces\t\nphases\t' + response: {b'bookmarks': b'', b'namespaces': b'', b'phases': b''} $ cd .. @@ -1443,7 +1443,7 @@ i> flush() -> None o> bufferedreadline() -> 2: o> 0\n - response: b'' + response: {} testing ssh2 creating ssh peer from handshake results @@ -1470,7 +1470,7 @@ i> flush() -> None o> bufferedreadline() -> 2: o> 0\n - response: b'' + response: {} With a single bookmark set @@ -1505,7 +1505,7 @@ o> bufferedreadline() -> 3: o> 46\n o> bufferedread(46) -> 46: bookA\t68986213bd4485ea51533535e3fc9e78007a711f - response: b'bookA\t68986213bd4485ea51533535e3fc9e78007a711f' + response: {b'bookA': b'68986213bd4485ea51533535e3fc9e78007a711f'} testing ssh2 creating ssh peer from handshake results @@ -1533,7 +1533,7 @@ o> bufferedreadline() -> 3: o> 46\n o> bufferedread(46) -> 46: bookA\t68986213bd4485ea51533535e3fc9e78007a711f - response: b'bookA\t68986213bd4485ea51533535e3fc9e78007a711f' + response: {b'bookA': b'68986213bd4485ea51533535e3fc9e78007a711f'} With multiple bookmarks set @@ -1570,7 +1570,7 @@ o> bufferedread(93) -> 93: o> bookA\t68986213bd4485ea51533535e3fc9e78007a711f\n o> bookB\t1880f3755e2e52e3199e0ee5638128b08642f34d - response: b'bookA\t68986213bd4485ea51533535e3fc9e78007a711f\nbookB\t1880f3755e2e52e3199e0ee5638128b08642f34d' + response: {b'bookA': b'68986213bd4485ea51533535e3fc9e78007a711f', b'bookB': b'1880f3755e2e52e3199e0ee5638128b08642f34d'} testing ssh2 creating ssh peer from handshake results @@ -1600,7 +1600,7 @@ o> bufferedread(93) -> 93: o> bookA\t68986213bd4485ea51533535e3fc9e78007a711f\n o> bookB\t1880f3755e2e52e3199e0ee5638128b08642f34d - response: b'bookA\t68986213bd4485ea51533535e3fc9e78007a711f\nbookB\t1880f3755e2e52e3199e0ee5638128b08642f34d' + response: {b'bookA': b'68986213bd4485ea51533535e3fc9e78007a711f', b'bookB': b'1880f3755e2e52e3199e0ee5638128b08642f34d'} Test pushkey for bookmarks @@ -1646,7 +1646,7 @@ o> 2\n o> bufferedread(2) -> 2: o> 1\n - response: b'1\n' + response: True testing ssh2 creating ssh peer from handshake results @@ -1683,7 +1683,7 @@ o> 2\n o> bufferedread(2) -> 2: o> 1\n - response: b'1\n' + response: True $ hg bookmarks bookA 0:68986213bd44 @@ -1729,7 +1729,7 @@ o> bufferedreadline() -> 3: o> 15\n o> bufferedread(15) -> 15: publishing\tTrue - response: b'publishing\tTrue' + response: {b'publishing': b'True'} testing ssh2 creating ssh peer from handshake results @@ -1757,7 +1757,7 @@ o> bufferedreadline() -> 3: o> 15\n o> bufferedread(15) -> 15: publishing\tTrue - response: b'publishing\tTrue' + response: {b'publishing': b'True'} Create some commits @@ -1811,7 +1811,7 @@ o> 20b8a89289d80036e6c4e87c2083e3bea1586637\t1\n o> c4750011d906c18ea2f0527419cbc1a544435150\t1\n o> publishing\tTrue - response: b'20b8a89289d80036e6c4e87c2083e3bea1586637\t1\nc4750011d906c18ea2f0527419cbc1a544435150\t1\npublishing\tTrue' + response: {b'20b8a89289d80036e6c4e87c2083e3bea1586637': b'1', b'c4750011d906c18ea2f0527419cbc1a544435150': b'1', b'publishing': b'True'} testing ssh2 creating ssh peer from handshake results @@ -1842,7 +1842,7 @@ o> 20b8a89289d80036e6c4e87c2083e3bea1586637\t1\n o> c4750011d906c18ea2f0527419cbc1a544435150\t1\n o> publishing\tTrue - response: b'20b8a89289d80036e6c4e87c2083e3bea1586637\t1\nc4750011d906c18ea2f0527419cbc1a544435150\t1\npublishing\tTrue' + response: {b'20b8a89289d80036e6c4e87c2083e3bea1586637': b'1', b'c4750011d906c18ea2f0527419cbc1a5444
D3293: bundlerepo: rename "other" to "peer"
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/D3293 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 @@ -492,9 +492,9 @@ def release(self): raise NotImplementedError -def getremotechanges(ui, repo, other, onlyheads=None, bundlename=None, +def getremotechanges(ui, repo, peer, onlyheads=None, bundlename=None, force=False): -'''obtains a bundle of changes incoming from other +'''obtains a bundle of changes incoming from peer "onlyheads" restricts the returned changes to those reachable from the specified heads. @@ -507,63 +507,63 @@ "local" is a local repo from which to obtain the actual incoming changesets; it is a bundlerepo for the obtained bundle when the - original "other" is remote. + original "peer" is remote. "csets" lists the incoming changeset node ids. "cleanupfn" must be called without arguments when you're done processing - the changes; it closes both the original "other" and the one returned + the changes; it closes both the original "peer" and the one returned here. ''' -tmp = discovery.findcommonincoming(repo, other, heads=onlyheads, +tmp = discovery.findcommonincoming(repo, peer, heads=onlyheads, force=force) common, incoming, rheads = tmp if not incoming: try: if bundlename: os.unlink(bundlename) except OSError: pass -return repo, [], other.close +return repo, [], peer.close commonset = set(common) rheads = [x for x in rheads if x not in commonset] bundle = None bundlerepo = None -localrepo = other.local() +localrepo = peer.local() if bundlename or not localrepo: -# create a bundle (uncompressed if other repo is not local) +# create a bundle (uncompressed if peer repo is not local) # developer config: devel.legacy.exchange legexc = ui.configlist('devel', 'legacy.exchange') forcebundle1 = 'bundle2' not in legexc and 'bundle1' in legexc canbundle2 = (not forcebundle1 - and other.capable('getbundle') - and other.capable('bundle2')) + and peer.capable('getbundle') + and peer.capable('bundle2')) if canbundle2: kwargs = {} kwargs[r'common'] = common kwargs[r'heads'] = rheads kwargs[r'bundlecaps'] = exchange.caps20to10(repo, role='client') kwargs[r'cg'] = True -b2 = other.getbundle('incoming', **kwargs) +b2 = peer.getbundle('incoming', **kwargs) fname = bundle = changegroup.writechunks(ui, b2._forwardchunks(), bundlename) else: -if other.capable('getbundle'): -cg = other.getbundle('incoming', common=common, heads=rheads) -elif onlyheads is None and not other.capable('changegroupsubset'): +if peer.capable('getbundle'): +cg = peer.getbundle('incoming', common=common, heads=rheads) +elif onlyheads is None and not peer.capable('changegroupsubset'): # compat with older servers when pulling all remote heads -with other.commandexecutor() as e: +with peer.commandexecutor() as e: fcg = e.callcommand('changegroup', { 'nodes': incoming, 'source': 'incoming', }) cg = fcg.result() rheads = None else: -with other.commandexecutor() as e: +with peer.commandexecutor() as e: fcg = e.callcommand('changegroupsubset', { 'bases': incoming, 'heads': rheads, @@ -584,7 +584,7 @@ # use the created uncompressed bundlerepo localrepo = bundlerepo = bundlerepository(repo.baseui, repo.root, fname) -# this repo contains local and other now, so filter out local again +# this repo contains local and peer now, so filter out local again common = repo.heads() if localrepo: # Part of common may be remotely filtered @@ -596,17 +596,17 @@ if bundlerepo: reponodes = [ctx.node() for ctx in bundlerepo[bundlerepo.firstnewrev:]] -remotephases = other.listkeys('phases') +remotephases = peer.listkeys('phases') -pullop = exchange.pulloperation(
D3299: wireproto: add media type to version 2 capabilities response
indygreg created this revision. Herald added a subscriber: mercurial-devel. Herald added a reviewer: hg-reviewers. REVISION SUMMARY This is useful to advertise because servers reject unsupported media types. A client may wish to speak multiple media types and choose the one the server supports. The SSH protocol doesn't currently have the concept of media types. However, the SSH peer could use this information to see if its framing protocol implementation has a version that matches the server. There is an issue that the connection will need to be "switched" to a different framing protocol. But the SSH transport isn't currently talking the framing protocol. So we can punt on this problem. I doubt we'll ever use multiple media types or negotiation in core. But during the course of developing this protocol, I may end up making extensions that backport and forward port protocol support as needed to support Mercurial deploys in the wild. e.g. I may deploy support for an older protocol on a server so old clients can continue using it. REPOSITORY rHG Mercurial REVISION DETAIL https://phab.mercurial-scm.org/D3299 AFFECTED FILES mercurial/help/internals/wireprotocol.txt 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 CHANGE DETAILS 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 @@ -45,7 +45,7 @@ s> Content-Type: application/mercurial-cbor\r\n s> Content-Length: *\r\n (glob) s> \r\n - s> \xa3Dapis\xa1Pexp-http-v2-0001\xa2Hcommands\xa7Eheads\xa2Dargs\xa1Jpubliconly\xf4Kpermissions\x81DpullEknown\xa2Dargs\xa1Enodes\x81HdeadbeefKpermissions\x81DpullFlookup\xa2Dargs\xa1CkeyCfooKpermissions\x81DpullGpushkey\xa2Dargs\xa4CkeyCkeyCnewCnewColdColdInamespaceBnsKpermissions\x81DpushHlistkeys\xa2Dargs\xa1InamespaceBnsKpermissions\x81DpullIbranchmap\xa2Dargs\xa0Kpermissions\x81DpullLcapabilities\xa2Dargs\xa0Kpermissions\x81DpullKcompression\x82\xa1DnameDzstd\xa1DnameDzlibGapibaseDapi/Nv1capabilitiesY\x01\xcabatch branchmap $USUAL_BUNDLE2_CAPS_SERVER$ changegroupsubset compression=$BUNDLE2_COMPRESSIONS$ getbundle httpheader=1024 httpmediatype=0.1rx,0.1tx,0.2tx known lookup pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash + s> \xa3Dapis\xa1Pexp-http-v2-0001\xa3Hcommands\xa7Eheads\xa2Dargs\xa1Jpubliconly\xf4Kpermissions\x81DpullEknown\xa2Dargs\xa1Enodes\x81HdeadbeefKpermissions\x81DpullFlookup\xa2Dargs\xa1CkeyCfooKpermissions\x81DpullGpushkey\xa2Dargs\xa4CkeyCkeyCnewCnewColdColdInamespaceBnsKpermissions\x81DpushHlistkeys\xa2Dargs\xa1InamespaceBnsKpermissions\x81DpullIbranchmap\xa2Dargs\xa0Kpermissions\x81DpullLcapabilities\xa2Dargs\xa0Kpermissions\x81DpullKcompression\x82\xa1DnameDzstd\xa1DnameDzlibQframingmediatypes\x81X&application/mercurial-exp-framing-0003GapibaseDapi/Nv1capabilitiesY\x01\xcabatch branchmap $USUAL_BUNDLE2_CAPS_SERVER$ changegroupsubset compression=$BUNDLE2_COMPRESSIONS$ getbundle httpheader=1024 httpmediatype=0.1rx,0.1tx,0.2tx known lookup pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash sending pushkey command s> *\r\n (glob) s> Accept-Encoding: identity\r\n @@ -93,7 +93,7 @@ s> Content-Type: application/mercurial-cbor\r\n s> Content-Length: *\r\n (glob) s> \r\n - s> \xa3Dapis\xa1Pexp-http-v2-0001\xa2Hcommands\xa7Eheads\xa2Dargs\xa1Jpubliconly\xf4Kpermissions\x81DpullEknown\xa2Dargs\xa1Enodes\x81HdeadbeefKpermissions\x81DpullFlookup\xa2Dargs\xa1CkeyCfooKpermissions\x81DpullGpushkey\xa2Dargs\xa4CkeyCkeyCnewCnewColdColdInamespaceBnsKpermissions\x81DpushHlistkeys\xa2Dargs\xa1InamespaceBnsKpermissions\x81DpullIbranchmap\xa2Dargs\xa0Kpermissions\x81DpullLcapabilities\xa2Dargs\xa0Kpermissions\x81DpullKcompression\x82\xa1DnameDzstd\xa1DnameDzlibGapibaseDapi/Nv1capabilitiesY\x01\xcabatch branchmap $USUAL_BUNDLE2_CAPS_SERVER$ changegroupsubset compression=$BUNDLE2_COMPRESSIONS$ getbundle httpheader=1024 httpmediatype=0.1rx,0.1tx,0.2tx known lookup pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash + s> \xa3Dapis\xa1Pexp-http-v2-0001\xa3Hcommands\xa7Eheads\xa2Dargs\xa1Jpubliconly\xf4Kpermissions\x81DpullEknown\xa2Dargs\xa1Enodes\x81HdeadbeefKpermissions\x81DpullFlookup\xa2Dargs\xa1CkeyCfooKpermissions\x81DpullGpushkey\xa2Dargs\xa4CkeyCkeyCnewCnewColdColdInamespaceBnsKpermissions\x81DpushHlistkeys\xa2Dargs\xa1InamespaceBnsKpermissions\x81DpullIbranchmap\xa2Dargs\xa0Kpermissions\x81DpullLcapabilities\xa2Dargs\xa0Kper
D3296: debugcommands: perform handshake when obtaining httpv2 peer
indygreg created this revision. Herald added a subscriber: mercurial-devel. Herald added a reviewer: hg-reviewers. REVISION SUMMARY If we obtain an httpv2peer directly, the instance doesn't have an API descriptor and therefore doesn't know about the remote's commands, feature support, etc. This doesn't matter now. But when we implement the peer so it consults the API descriptor as part of sending commands, it will. So we change the logic for obtaining an http version 2 peer to go through makepeer() so the peer will perform the handshake and pass the API descriptor to the httpv2peer instance. Tests changed because we now perform a ?cmd=capabilities when obtaining version 2 peers. The Content-Length header is globbed because compression info will lack zstandard for pure builds. REPOSITORY rHG Mercurial REVISION DETAIL https://phab.mercurial-scm.org/D3296 AFFECTED FILES mercurial/debugcommands.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 CHANGE DETAILS 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 @@ -29,6 +29,23 @@ > new 426bada5c67598ca65036d57d9e4b64b0c1ce7a0 > EOF creating http peer for wire protocol version 2 + s> *\r\n (glob) + s> Accept-Encoding: identity\r\n + s> vary: X-HgProto-1,X-HgUpgrade-1\r\n + s> x-hgproto-1: cbor\r\n + s> x-hgupgrade-1: exp-http-v2-0001\r\n + s> accept: application/mercurial-0.1\r\n + s> host: $LOCALIP:$HGPORT\r\n (glob) + s> user-agent: Mercurial debugwireproto\r\n + s> \r\n + 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-cbor\r\n + s> Content-Length: *\r\n (glob) + s> \r\n + s> \xa3Dapis\xa1Pexp-http-v2-0001\xa2Hcommands\xa7Eheads\xa2Dargs\xa1Jpubliconly\xf4Kpermissions\x81DpullEknown\xa2Dargs\xa1Enodes\x81HdeadbeefKpermissions\x81DpullFlookup\xa2Dargs\xa1CkeyCfooKpermissions\x81DpullGpushkey\xa2Dargs\xa4CkeyCkeyCnewCnewColdColdInamespaceBnsKpermissions\x81DpushHlistkeys\xa2Dargs\xa1InamespaceBnsKpermissions\x81DpullIbranchmap\xa2Dargs\xa0Kpermissions\x81DpullLcapabilities\xa2Dargs\xa0Kpermissions\x81DpullKcompression\x82\xa1DnameDzstd\xa1DnameDzlibGapibaseDapi/Nv1capabilitiesY\x01\xcabatch branchmap $USUAL_BUNDLE2_CAPS_SERVER$ changegroupsubset compression=$BUNDLE2_COMPRESSIONS$ getbundle httpheader=1024 httpmediatype=0.1rx,0.1tx,0.2tx known lookup pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash sending pushkey command s> *\r\n (glob) s> Accept-Encoding: identity\r\n @@ -60,6 +77,23 @@ > namespace bookmarks > EOF creating http peer for wire protocol version 2 + s> GET /?cmd=capabilities HTTP/1.1\r\n + s> Accept-Encoding: identity\r\n + s> vary: X-HgProto-1,X-HgUpgrade-1\r\n + s> x-hgproto-1: cbor\r\n + s> x-hgupgrade-1: exp-http-v2-0001\r\n + s> accept: application/mercurial-0.1\r\n + s> host: $LOCALIP:$HGPORT\r\n (glob) + s> user-agent: Mercurial debugwireproto\r\n + s> \r\n + 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-cbor\r\n + s> Content-Length: *\r\n (glob) + s> \r\n + s> \xa3Dapis\xa1Pexp-http-v2-0001\xa2Hcommands\xa7Eheads\xa2Dargs\xa1Jpubliconly\xf4Kpermissions\x81DpullEknown\xa2Dargs\xa1Enodes\x81HdeadbeefKpermissions\x81DpullFlookup\xa2Dargs\xa1CkeyCfooKpermissions\x81DpullGpushkey\xa2Dargs\xa4CkeyCkeyCnewCnewColdColdInamespaceBnsKpermissions\x81DpushHlistkeys\xa2Dargs\xa1InamespaceBnsKpermissions\x81DpullIbranchmap\xa2Dargs\xa0Kpermissions\x81DpullLcapabilities\xa2Dargs\xa0Kpermissions\x81DpullKcompression\x82\xa1DnameDzstd\xa1DnameDzlibGapibaseDapi/Nv1capabilitiesY\x01\xcabatch branchmap $USUAL_BUNDLE2_CAPS_SERVER$ changegroupsubset compression=$BUNDLE2_COMPRESSIONS$ getbundle httpheader=1024 httpmediatype=0.1rx,0.1tx,0.2tx known lookup pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash sending listkeys command s> POST /api/exp-http-v2-0001/ro/listkeys HTTP/1.1\r\n s> Accept-Encoding: identity\r\n 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 @@ -26,6 +26,23 @@ > key 426bada5c67598ca65036d57d9e4b64b0c1ce7a0 > EOF creating http p
D3292: bookmarks: use command executor for wire protocol commands
indygreg created this revision. Herald added a subscriber: mercurial-devel. Herald added a reviewer: hg-reviewers. REVISION SUMMARY And change the name of a variable to reflect that is is a peer. REPOSITORY rHG Mercurial REVISION DETAIL https://phab.mercurial-scm.org/D3292 AFFECTED FILES mercurial/bookmarks.py CHANGE DETAILS diff --git a/mercurial/bookmarks.py b/mercurial/bookmarks.py --- a/mercurial/bookmarks.py +++ b/mercurial/bookmarks.py @@ -646,12 +646,18 @@ writer(msg) localmarks.applychanges(repo, tr, changes) -def incoming(ui, repo, other): +def incoming(ui, repo, peer): '''Show bookmarks incoming from other to repo ''' ui.status(_("searching for changed bookmarks\n")) -remotemarks = unhexlifybookmarks(other.listkeys('bookmarks')) +with peer.commandexecutor() as e: +fbookmarks = e.callcommand('listkeys', { +'namespace': 'bookmarks', +}) + +remotemarks = unhexlifybookmarks(fbookmarks.result()) + r = comparebookmarks(repo, remotemarks, repo._bookmarks) addsrc, adddst, advsrc, advdst, diverge, differ, invalid, same = r @@ -733,12 +739,18 @@ return 0 -def summary(repo, other): +def summary(repo, peer): '''Compare bookmarks between repo and other for "hg summary" output This returns "(# of incoming, # of outgoing)" tuple. ''' -remotemarks = unhexlifybookmarks(other.listkeys('bookmarks')) +with peer.commandexecutor() as e: +fbookmarks = e.callcommand('listkeys', { +'namespace': 'bookmarks', +}) + +remotemarks = unhexlifybookmarks(fbookmarks.result()) + r = comparebookmarks(repo, remotemarks, repo._bookmarks) addsrc, adddst, advsrc, advdst, diverge, differ, invalid, same = r return (len(addsrc), len(adddst)) 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
Re: [PATCH 1 of 2] hgweb: fallback to checking wsgireq.env for REPO_NAME for 3rd party hosting
Gentle ping on this. This setup is at work, so I’ll only have tomorrow and Monday to make any changes. > On Apr 6, 2018, at 6:18 PM, Matt Harbison wrote: > > # HG changeset patch > # User Matt Harbison > # Date 1522957360 14400 > # Thu Apr 05 15:42:40 2018 -0400 > # Node ID d2fd52e2e5e0ce6369c551e7e00c06d36c21658f > # Parent d3286dd2ca2f9f9e2b332e00c4b25b21729c54f5 > hgweb: fallback to checking wsgireq.env for REPO_NAME for 3rd party hosting > > Starting with d7fd203e36cc, SCM Manager began to 404 any repository access. > What's happening is that it is generating a python script that creates an > hgweb > application (not hgwebdir), and launches hgweb via wsgicgi. It must be > setting > REPO_NAME in the process environment before launching this script, which gets > picked up and put into wsgireq.env when wsgicgi launches the hgweb > application. > From there, other variables (notably 'apppath' and 'dispatchpath') are > constructed differently. > > d7fd203e36cc^ (working): > >apppath: /hg/eng/devsetup >dispatchpath: >pathinfo: /eng/devsetup >reponame: eng/devsetup > > d7fd203e36cc: > >apppath: /hg >dispatchpath: eng/devsetup >pathinfo: /eng/devsetup >reponame: None >REPO_NAME: eng/devsetup > > Rather than having an existing installation break when Mercurial is upgraded, > just resume checking the environment. I have no idea how many other hosting > solutions would break without restoring this. > > diff --git a/mercurial/hgweb/request.py b/mercurial/hgweb/request.py > --- a/mercurial/hgweb/request.py > +++ b/mercurial/hgweb/request.py > @@ -162,6 +162,12 @@ def parserequestfromenv(env, reponame=No > env = {k: v.encode('latin-1') if isinstance(v, str) else v >for k, v in env.iteritems()} > > +# Some hosting solutions are emulating hgwebdir, and dispatching directly > +# to an hgweb instance using this environment variable. This was always > +# checked prior to d7fd203e36cc; keep doing so to avoid breaking them. > +if not reponame: > +reponame = env.get('REPO_NAME') > + > if altbaseurl: > altbaseurl = util.url(altbaseurl) > ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
D3301: fix: use sysstrs for command template formatting
durin42 created this revision. Herald added a subscriber: mercurial-devel. Herald added a reviewer: hg-reviewers. REVISION SUMMARY This lets us keep using the .format() interface, which I think on the whole I'd like to keep because it makes the configuration a little nicer. REPOSITORY rHG Mercurial REVISION DETAIL https://phab.mercurial-scm.org/D3301 AFFECTED FILES hgext/fix.py CHANGE DETAILS diff --git a/hgext/fix.py b/hgext/fix.py --- a/hgext/fix.py +++ b/hgext/fix.py @@ -540,12 +540,14 @@ May return None if there is no appropriate command to run for the given parameters. """ -parts = [self._command.format(rootpath=path, - basename=os.path.basename(path))] +parts = [pycompat.sysstr(self._command).format( +rootpath=path, +basename=os.path.basename(path))] if self._linerange: if not ranges: # No line ranges to fix, so don't run the fixer. return None for first, last in ranges: -parts.append(self._linerange.format(first=first, last=last)) -return ' '.join(parts) +parts.append(pycompat.sysstr(self._linerange).format( +first=first, last=last)) +return ' '.join(pycompat.sysbytes(b) for b in parts) 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
D3300: fix: port most of the way to python 3
durin42 created this revision. Herald added a subscriber: mercurial-devel. Herald added a reviewer: hg-reviewers. REVISION SUMMARY Only most of the way because we now have to decide: if we want to keep the current .format() interface for the config in hgrc, we have to use unicodes to do formatting in Python 3, rather than bytes. I'm basically fine with that, so a follow-up patch will do so. REPOSITORY rHG Mercurial REVISION DETAIL https://phab.mercurial-scm.org/D3300 AFFECTED FILES hgext/fix.py CHANGE DETAILS diff --git a/hgext/fix.py b/hgext/fix.py --- a/hgext/fix.py +++ b/hgext/fix.py @@ -66,6 +66,7 @@ mdiff, merge, obsolete, +pycompat, registrar, scmutil, util, @@ -126,6 +127,7 @@ revisions are not forgotten in later ones. The --base flag can be used to override this default behavior, though it is not usually desirable to do so. """ +opts = pycompat.byteskwargs(opts) if opts['all']: if opts['rev']: raise error.Abort(_('cannot specify both "--rev" and "--all"')) @@ -513,7 +515,8 @@ result[name] = Fixer() attrs = ui.configsuboptions('fix', name)[1] for key in FIXER_ATTRS: -setattr(result[name], '_' + key, attrs.get(key, '')) +setattr(result[name], pycompat.sysstr('_' + key), +attrs.get(key, '')) return result def fixernames(ui): 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
D3255: repository: split capabilities methods into separate interface
This revision was automatically updated to reflect the committed changes. Closed by commit rHG98861a2298b5: repository: split capabilities methods into separate interface (authored by indygreg, committed by ). REPOSITORY rHG Mercurial CHANGES SINCE LAST UPDATE https://phab.mercurial-scm.org/D3255?vs=8021&id=8096 REVISION DETAIL https://phab.mercurial-scm.org/D3255 AFFECTED FILES mercurial/repository.py CHANGE DETAILS diff --git a/mercurial/repository.py b/mercurial/repository.py --- a/mercurial/repository.py +++ b/mercurial/repository.py @@ -61,6 +61,26 @@ associated with the peer should be cleaned up. """ +class ipeercapabilities(zi.Interface): +"""Peer sub-interface related to capabilities.""" + +def capable(name): +"""Determine support for a named capability. + +Returns ``False`` if capability not supported. + +Returns ``True`` if boolean capability is supported. Returns a string +if capability support is non-boolean. + +Capability strings may or may not map to wire protocol capabilities. +""" + +def requirecap(name, purpose): +"""Require a capability to be present. + +Raises a ``CapabilityError`` if the capability isn't present. +""" + class ipeercommands(zi.Interface): """Client-side interface for communicating over the wire protocol. @@ -176,7 +196,7 @@ def changegroupsubset(bases, heads, kind): pass -class ipeerbase(ipeerconnection, ipeercommands): +class ipeerbase(ipeerconnection, ipeercapabilities, ipeercommands): """Unified interface for peer repositories. All peer instances must conform to this interface. @@ -205,21 +225,6 @@ calls. However, they must all support this API. """ -def capable(name): -"""Determine support for a named capability. - -Returns ``False`` if capability not supported. - -Returns ``True`` if boolean capability is supported. Returns a string -if capability support is non-boolean. -""" - -def requirecap(name, purpose): -"""Require a capability to be present. - -Raises a ``CapabilityError`` if the capability isn't present. -""" - class ipeerbaselegacycommands(ipeerbase, ipeerlegacycommands): """Unified peer interface that supports legacy commands.""" To: indygreg, #hg-reviewers, durin42 Cc: mercurial-devel ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
D3254: httppeer: implement ipeerconnection
This revision was automatically updated to reflect the committed changes. Closed by commit rHG01bfe5ad0c53: httppeer: implement ipeerconnection (authored by indygreg, committed by ). REPOSITORY rHG Mercurial CHANGES SINCE LAST UPDATE https://phab.mercurial-scm.org/D3254?vs=8020&id=8095 REVISION DETAIL https://phab.mercurial-scm.org/D3254 AFFECTED FILES mercurial/httppeer.py tests/test-check-interfaces.py CHANGE DETAILS diff --git a/tests/test-check-interfaces.py b/tests/test-check-interfaces.py --- a/tests/test-check-interfaces.py +++ b/tests/test-check-interfaces.py @@ -92,6 +92,10 @@ httppeer.httppeer) checkzobject(httppeer.httppeer(None, None, None, dummyopener(), None, None)) +ziverify.verifyClass(repository.ipeerconnection, + httppeer.httpv2peer) +checkzobject(httppeer.httpv2peer(None, '', None, None, None, None)) + ziverify.verifyClass(repository.ipeerbase, localrepo.localpeer) checkzobject(localrepo.localpeer(dummyrepo())) diff --git a/mercurial/httppeer.py b/mercurial/httppeer.py --- a/mercurial/httppeer.py +++ b/mercurial/httppeer.py @@ -19,11 +19,15 @@ from .thirdparty import ( cbor, ) +from .thirdparty.zope import ( +interface as zi, +) from . import ( bundle2, error, httpconnection, pycompat, +repository, statichttprepo, url as urlmod, util, @@ -513,23 +517,41 @@ raise exception # TODO implement interface for version 2 peers +@zi.implementer(repository.ipeerconnection) class httpv2peer(object): def __init__(self, ui, repourl, apipath, opener, requestbuilder, apidescriptor): self.ui = ui if repourl.endswith('/'): repourl = repourl[:-1] -self.url = repourl +self._url = repourl self._apipath = apipath self._opener = opener self._requestbuilder = requestbuilder self._descriptor = apidescriptor +# Start of ipeerconnection. + +def url(self): +return self._url + +def local(self): +return None + +def peer(self): +return self + +def canpush(self): +# TODO change once implemented. +return False + def close(self): pass +# End of ipeerconnection. + # TODO require to be part of a batched primitive, use futures. def _call(self, name, **args): """Call a wire protocol command with arguments.""" @@ -554,7 +576,7 @@ 'pull': 'ro', }[permission] -url = '%s/%s/%s/%s' % (self.url, self._apipath, permission, name) +url = '%s/%s/%s/%s' % (self._url, self._apipath, permission, name) # TODO this should be part of a generic peer for the frame-based # protocol. To: indygreg, #hg-reviewers, durin42 Cc: mercurial-devel ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
D3256: httppeer: basic implementation of capabilities interface
This revision was automatically updated to reflect the committed changes. Closed by commit rHGae8730877371: httppeer: basic implementation of capabilities interface (authored by indygreg, committed by ). REPOSITORY rHG Mercurial CHANGES SINCE LAST UPDATE https://phab.mercurial-scm.org/D3256?vs=8022&id=8097 REVISION DETAIL https://phab.mercurial-scm.org/D3256 AFFECTED FILES mercurial/httppeer.py tests/test-check-interfaces.py CHANGE DETAILS diff --git a/tests/test-check-interfaces.py b/tests/test-check-interfaces.py --- a/tests/test-check-interfaces.py +++ b/tests/test-check-interfaces.py @@ -94,6 +94,8 @@ ziverify.verifyClass(repository.ipeerconnection, httppeer.httpv2peer) +ziverify.verifyClass(repository.ipeercapabilities, + httppeer.httpv2peer) checkzobject(httppeer.httpv2peer(None, '', None, None, None, None)) ziverify.verifyClass(repository.ipeerbase, diff --git a/mercurial/httppeer.py b/mercurial/httppeer.py --- a/mercurial/httppeer.py +++ b/mercurial/httppeer.py @@ -517,7 +517,7 @@ raise exception # TODO implement interface for version 2 peers -@zi.implementer(repository.ipeerconnection) +@zi.implementer(repository.ipeerconnection, repository.ipeercapabilities) class httpv2peer(object): def __init__(self, ui, repourl, apipath, opener, requestbuilder, apidescriptor): @@ -552,6 +552,33 @@ # End of ipeerconnection. +# Start of ipeercapabilities. + +def capable(self, name): +# The capabilities used internally historically map to capabilities +# advertised from the "capabilities" wire protocol command. However, +# version 2 of that command works differently. + +# Maps to commands that are available. +if name in ('branchmap', 'getbundle', 'known', 'lookup', 'pushkey'): +return True + +# Other concepts. +if name in ('bundle2',): +return True + +return False + +def requirecap(self, name, purpose): +if self.capable(name): +return + +raise error.CapabilityError( +_('cannot %s; client or remote repository does not support the %r ' + 'capability') % (purpose, name)) + +# End of ipeercapabilities. + # TODO require to be part of a batched primitive, use futures. def _call(self, name, **args): """Call a wire protocol command with arguments.""" To: indygreg, #hg-reviewers, durin42 Cc: mercurial-devel ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
D3258: wireproto: move gboptsmap to wireprototypes and rename (API)
This revision was automatically updated to reflect the committed changes. Closed by commit rHG96d735601ca1: wireproto: move gboptsmap to wireprototypes and rename (API) (authored by indygreg, committed by ). REPOSITORY rHG Mercurial CHANGES SINCE LAST UPDATE https://phab.mercurial-scm.org/D3258?vs=8024&id=8099 REVISION DETAIL https://phab.mercurial-scm.org/D3258 AFFECTED FILES hgext/narrow/narrowbundle2.py mercurial/wireproto.py mercurial/wireprototypes.py CHANGE DETAILS diff --git a/mercurial/wireprototypes.py b/mercurial/wireprototypes.py --- a/mercurial/wireprototypes.py +++ b/mercurial/wireprototypes.py @@ -134,6 +134,30 @@ .replace(':o', ',') .replace(':c', ':')) +# mapping of options accepted by getbundle and their types +# +# Meant to be extended by extensions. It is extensions responsibility to ensure +# such options are properly processed in exchange.getbundle. +# +# supported types are: +# +# :nodes: list of binary nodes +# :csv: list of comma-separated values +# :scsv: list of comma-separated values return as set +# :plain: string with no transformation needed. +GETBUNDLE_ARGUMENTS = { +'heads': 'nodes', +'bookmarks': 'boolean', +'common': 'nodes', +'obsmarkers': 'boolean', +'phases': 'boolean', +'bundlecaps': 'scsv', +'listkeys': 'csv', +'cg': 'boolean', +'cbattempted': 'boolean', +'stream': 'boolean', +} + class baseprotocolhandler(zi.Interface): """Abstract base class for wire protocol handlers. diff --git a/mercurial/wireproto.py b/mercurial/wireproto.py --- a/mercurial/wireproto.py +++ b/mercurial/wireproto.py @@ -145,29 +145,6 @@ return cap[5:].split(',') return ['zlib', 'none'] -# mapping of options accepted by getbundle and their types -# -# Meant to be extended by extensions. It is extensions responsibility to ensure -# such options are properly processed in exchange.getbundle. -# -# supported types are: -# -# :nodes: list of binary nodes -# :csv: list of comma-separated values -# :scsv: list of comma-separated values return as set -# :plain: string with no transformation needed. -gboptsmap = {'heads': 'nodes', - 'bookmarks': 'boolean', - 'common': 'nodes', - 'obsmarkers': 'boolean', - 'phases': 'boolean', - 'bundlecaps': 'scsv', - 'listkeys': 'csv', - 'cg': 'boolean', - 'cbattempted': 'boolean', - 'stream': 'boolean', -} - # client side class wirepeer(repository.legacypeer): @@ -275,7 +252,7 @@ for key, value in kwargs.iteritems(): if value is None: continue -keytype = gboptsmap.get(key) +keytype = wireprototypes.GETBUNDLE_ARGUMENTS.get(key) if keytype is None: raise error.ProgrammingError( 'Unexpectedly None keytype for key %s' % key) @@ -1004,9 +981,10 @@ @wireprotocommand('getbundle', '*', permission='pull', transportpolicy=POLICY_V1_ONLY) def getbundle(repo, proto, others): -opts = options('getbundle', gboptsmap.keys(), others) +opts = options('getbundle', wireprototypes.GETBUNDLE_ARGUMENTS.keys(), + others) for k, v in opts.iteritems(): -keytype = gboptsmap[k] +keytype = wireprototypes.GETBUNDLE_ARGUMENTS[k] if keytype == 'nodes': opts[k] = wireprototypes.decodelist(v) elif keytype == 'csv': diff --git a/hgext/narrow/narrowbundle2.py b/hgext/narrow/narrowbundle2.py --- a/hgext/narrow/narrowbundle2.py +++ b/hgext/narrow/narrowbundle2.py @@ -27,7 +27,7 @@ narrowspec, repair, util, -wireproto, +wireprototypes, ) from mercurial.utils import ( stringutil, @@ -461,13 +461,15 @@ """Enable narrow repo support in bundle2-related extension points.""" extensions.wrapfunction(bundle2, 'getrepocaps', getrepocaps_narrow) -wireproto.gboptsmap['narrow'] = 'boolean' -wireproto.gboptsmap['depth'] = 'plain' -wireproto.gboptsmap['oldincludepats'] = 'csv' -wireproto.gboptsmap['oldexcludepats'] = 'csv' -wireproto.gboptsmap['includepats'] = 'csv' -wireproto.gboptsmap['excludepats'] = 'csv' -wireproto.gboptsmap['known'] = 'csv' +getbundleargs = wireprototypes.GETBUNDLE_ARGUMENTS + +getbundleargs['narrow'] = 'boolean' +getbundleargs['depth'] = 'plain' +getbundleargs['oldincludepats'] = 'csv' +getbundleargs['oldexcludepats'] = 'csv' +getbundleargs['includepats'] = 'csv' +getbundleargs['excludepats'] = 'csv' +getbundleargs['known'] = 'csv' # Extend changegroup serving to handle requests from narrow clients. origcgfn = exchange.getbundle2partsmapping['changegroup'] To: indygreg, durin42, #hg-reviewers Cc: mercurial-devel ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-sc
D3259: wireproto: move version 1 peer functionality to standalone module (API)
This revision was automatically updated to reflect the committed changes. Closed by commit rHGa81d02ea65db: wireproto: move version 1 peer functionality to standalone module (API) (authored by indygreg, committed by ). REPOSITORY rHG Mercurial CHANGES SINCE LAST UPDATE https://phab.mercurial-scm.org/D3259?vs=8025&id=8100 REVISION DETAIL https://phab.mercurial-scm.org/D3259 AFFECTED FILES hgext/infinitepush/__init__.py hgext/largefiles/proto.py mercurial/httppeer.py mercurial/sshpeer.py mercurial/wireproto.py mercurial/wireprotov1peer.py tests/test-batching.py tests/test-wireproto.py CHANGE DETAILS diff --git a/tests/test-wireproto.py b/tests/test-wireproto.py --- a/tests/test-wireproto.py +++ b/tests/test-wireproto.py @@ -7,6 +7,7 @@ util, wireproto, wireprototypes, +wireprotov1peer, ) stringio = util.stringio @@ -29,7 +30,7 @@ 'version': 1, } -class clientpeer(wireproto.wirepeer): +class clientpeer(wireprotov1peer.wirepeer): def __init__(self, serverrepo, ui): self.serverrepo = serverrepo self.ui = ui @@ -65,9 +66,9 @@ def _callstream(self, cmd, **args): return stringio(self._call(cmd, **args)) -@wireproto.batchable +@wireprotov1peer.batchable def greet(self, name): -f = wireproto.future() +f = wireprotov1peer.future() yield {b'name': mangle(name)}, f yield unmangle(f.value) diff --git a/tests/test-batching.py b/tests/test-batching.py --- a/tests/test-batching.py +++ b/tests/test-batching.py @@ -11,7 +11,7 @@ error, peer, util, -wireproto, +wireprotov1peer, ) # equivalent of repo.repository @@ -177,7 +177,7 @@ yield r def batchiter(self): -return wireproto.remoteiterbatcher(self) +return wireprotov1peer.remoteiterbatcher(self) @peer.batchable def foo(self, one, two=None): diff --git a/mercurial/wireproto.py b/mercurial/wireprotov1peer.py copy from mercurial/wireproto.py copy to mercurial/wireprotov1peer.py --- a/mercurial/wireproto.py +++ b/mercurial/wireprotov1peer.py @@ -1,4 +1,4 @@ -# wireproto.py - generic wire protocol support functions +# wireprotov1peer.py - Client-side functionality for wire protocol version 1. # # Copyright 2005-2010 Matt Mackall # @@ -8,45 +8,27 @@ from __future__ import absolute_import import hashlib -import os -import tempfile from .i18n import _ from .node import ( bin, -hex, -nullid, ) from . import ( bundle2, changegroup as changegroupmod, -discovery, encoding, error, -exchange, peer, pushkey as pushkeymod, pycompat, repository, -streamclone, util, wireprototypes, ) -from .utils import ( -procutil, -stringutil, -) - -urlerr = util.urlerr urlreq = util.urlreq -bundle2requiredmain = _('incompatible Mercurial client; bundle2 required') -bundle2requiredhint = _('see https://www.mercurial-scm.org/wiki/' -'IncompatibleClient') -bundle2required = '%s\n(%s)\n' % (bundle2requiredmain, bundle2requiredhint) - class remoteiterbatcher(peer.iterbatcher): def __init__(self, remote): super(remoteiterbatcher, self).__init__() @@ -115,7 +97,6 @@ batchable = peer.batchable future = peer.future - def encodebatchcmds(req): """Return a ``cmds`` argument value for the ``batch`` command.""" escapearg = wireprototypes.escapebatcharg @@ -133,20 +114,6 @@ return ';'.join(cmds) -def clientcompressionsupport(proto): -"""Returns a list of compression methods supported by the client. - -Returns a list of the compression methods supported by the client -according to the protocol capabilities. If no such capability has -been announced, fallback to the default of zlib and uncompressed. -""" -for cap in proto.getprotocaps(): -if cap.startswith('comp='): -return cap[5:].split(',') -return ['zlib', 'none'] - -# client side - class wirepeer(repository.legacypeer): """Client-side interface for communicating with a peer repository. @@ -451,815 +418,3 @@ """clearly abort the wire protocol connection and raise the exception """ raise NotImplementedError() - -# server side - -# wire protocol command can either return a string or one of these classes. - -def getdispatchrepo(repo, proto, command): -"""Obtain the repo used for processing wire protocol commands. - -The intent of this function is to serve as a monkeypatch point for -extensions that need commands to operate on different repo views under -specialized circumstances. -""" -return repo.filtered('served') - -def dispatch(repo, proto, command): -repo = getdispatchrepo(repo, proto, command) - -transportversion = wireprototypes.TRANSPORTS[proto.name]['version'] -commandtable = commandsv2 if transportversion == 2 else commands -func, spec = commandtable[comman
D3257: wireproto: move value encoding functions to wireprototypes (API)
This revision was automatically updated to reflect the committed changes. Closed by commit rHG5e71dea79aae: wireproto: move value encoding functions to wireprototypes (API) (authored by indygreg, committed by ). REPOSITORY rHG Mercurial CHANGES SINCE LAST UPDATE https://phab.mercurial-scm.org/D3257?vs=8023&id=8098 REVISION DETAIL https://phab.mercurial-scm.org/D3257 AFFECTED FILES hgext/infinitepush/__init__.py mercurial/wireproto.py mercurial/wireprototypes.py CHANGE DETAILS diff --git a/mercurial/wireprototypes.py b/mercurial/wireprototypes.py --- a/mercurial/wireprototypes.py +++ b/mercurial/wireprototypes.py @@ -5,6 +5,10 @@ from __future__ import absolute_import +from .node import ( +bin, +hex, +) from .thirdparty.zope import ( interface as zi, ) @@ -102,6 +106,34 @@ def __init__(self, v): self.value = v +# list of nodes encoding / decoding +def decodelist(l, sep=' '): +if l: +return [bin(v) for v in l.split(sep)] +return [] + +def encodelist(l, sep=' '): +try: +return sep.join(map(hex, l)) +except TypeError: +raise + +# batched call argument encoding + +def escapebatcharg(plain): +return (plain +.replace(':', ':c') +.replace(',', ':o') +.replace(';', ':s') +.replace('=', ':e')) + +def unescapebatcharg(escaped): +return (escaped +.replace(':e', '=') +.replace(':s', ';') +.replace(':o', ',') +.replace(':c', ':')) + class baseprotocolhandler(zi.Interface): """Abstract base class for wire protocol handlers. diff --git a/mercurial/wireproto.py b/mercurial/wireproto.py --- a/mercurial/wireproto.py +++ b/mercurial/wireproto.py @@ -115,37 +115,11 @@ batchable = peer.batchable future = peer.future -# list of nodes encoding / decoding - -def decodelist(l, sep=' '): -if l: -return [bin(v) for v in l.split(sep)] -return [] - -def encodelist(l, sep=' '): -try: -return sep.join(map(hex, l)) -except TypeError: -raise - -# batched call argument encoding - -def escapearg(plain): -return (plain -.replace(':', ':c') -.replace(',', ':o') -.replace(';', ':s') -.replace('=', ':e')) - -def unescapearg(escaped): -return (escaped -.replace(':e', '=') -.replace(':s', ';') -.replace(':o', ',') -.replace(':c', ':')) def encodebatchcmds(req): """Return a ``cmds`` argument value for the ``batch`` command.""" +escapearg = wireprototypes.escapebatcharg + cmds = [] for op, argsdict in req: # Old servers didn't properly unescape argument names. So prevent @@ -227,14 +201,14 @@ yield {}, f d = f.value try: -yield decodelist(d[:-1]) +yield wireprototypes.decodelist(d[:-1]) except ValueError: self._abort(error.ResponseError(_("unexpected response:"), d)) @batchable def known(self, nodes): f = future() -yield {'nodes': encodelist(nodes)}, f +yield {'nodes': wireprototypes.encodelist(nodes)}, f d = f.value try: yield [bool(int(b)) for b in d] @@ -251,7 +225,7 @@ for branchpart in d.splitlines(): branchname, branchheads = branchpart.split(' ', 1) branchname = encoding.tolocal(urlreq.unquote(branchname)) -branchheads = decodelist(branchheads) +branchheads = wireprototypes.decodelist(branchheads) branchmap[branchname] = branchheads yield branchmap except TypeError: @@ -306,7 +280,7 @@ raise error.ProgrammingError( 'Unexpectedly None keytype for key %s' % key) elif keytype == 'nodes': -value = encodelist(value) +value = wireprototypes.encodelist(value) elif keytype == 'csv': value = ','.join(value) elif keytype == 'scsv': @@ -338,10 +312,10 @@ ''' if heads != ['force'] and self.capable('unbundlehash'): -heads = encodelist(['hashed', -hashlib.sha1(''.join(sorted(heads))).digest()]) +heads = wireprototypes.encodelist( +['hashed', hashlib.sha1(''.join(sorted(heads))).digest()]) else: -heads = encodelist(heads) +heads = wireprototypes.encodelist(heads) if util.safehasattr(cg, 'deltaheader'): # this a bundle10, do the old style call sequence @@ -368,35 +342,37 @@ # Begin of ipeerlegacycommands interface. def branches(self, nodes): -n = encodelist(nodes) +n = wireprototypes.encodelist(nodes) d = self._call("branches", nodes=n) try: -br = [tuple(decodelist(b)) for b in d.splitlines()] +
D3260: peer: scatter module to the wind (API)
This revision was automatically updated to reflect the committed changes. Closed by commit rHGf3dc8239e3a9: peer: scatter module to the wind (API) (authored by indygreg, committed by ). CHANGED PRIOR TO COMMIT https://phab.mercurial-scm.org/D3260?vs=8026&id=8101#toc REPOSITORY rHG Mercurial CHANGES SINCE LAST UPDATE https://phab.mercurial-scm.org/D3260?vs=8026&id=8101 REVISION DETAIL https://phab.mercurial-scm.org/D3260 AFFECTED FILES hgext/infinitepush/__init__.py mercurial/localrepo.py mercurial/peer.py mercurial/wireprotov1peer.py tests/test-batching.py CHANGE DETAILS diff --git a/tests/test-batching.py b/tests/test-batching.py --- a/tests/test-batching.py +++ b/tests/test-batching.py @@ -9,9 +9,10 @@ from mercurial import ( error, -peer, +localrepo, util, wireprotov1peer, + ) # equivalent of repo.repository @@ -31,7 +32,7 @@ return "Hello, %s" % name def batchiter(self): '''Support for local batching.''' -return peer.localiterbatcher(self) +return localrepo.localiterbatcher(self) # usage of "thing" interface def use(it): @@ -51,7 +52,7 @@ bar2 = batch.bar(b="Uno", a="Due") # Future shouldn't be set until we submit(). -assert isinstance(foo, peer.future) +assert isinstance(foo, wireprotov1peer.future) assert not util.safehasattr(foo, 'value') assert not util.safehasattr(bar, 'value') batch.submit() @@ -179,16 +180,16 @@ def batchiter(self): return wireprotov1peer.remoteiterbatcher(self) -@peer.batchable +@wireprotov1peer.batchable def foo(self, one, two=None): encargs = [('one', mangle(one),), ('two', mangle(two),)] -encresref = peer.future() +encresref = wireprotov1peer.future() yield encargs, encresref yield unmangle(encresref.value) -@peer.batchable +@wireprotov1peer.batchable def bar(self, b, a): -encresref = peer.future() +encresref = wireprotov1peer.future() yield [('b', mangle(b),), ('a', mangle(a),)], encresref yield unmangle(encresref.value) diff --git a/mercurial/wireprotov1peer.py b/mercurial/wireprotov1peer.py --- a/mercurial/wireprotov1peer.py +++ b/mercurial/wireprotov1peer.py @@ -19,7 +19,6 @@ changegroup as changegroupmod, encoding, error, -peer, pushkey as pushkeymod, pycompat, repository, @@ -29,7 +28,76 @@ urlreq = util.urlreq -class remoteiterbatcher(peer.iterbatcher): +def batchable(f): +'''annotation for batchable methods + +Such methods must implement a coroutine as follows: + +@batchable +def sample(self, one, two=None): +# Build list of encoded arguments suitable for your wire protocol: +encargs = [('one', encode(one),), ('two', encode(two),)] +# Create future for injection of encoded result: +encresref = future() +# Return encoded arguments and future: +yield encargs, encresref +# Assuming the future to be filled with the result from the batched +# request now. Decode it: +yield decode(encresref.value) + +The decorator returns a function which wraps this coroutine as a plain +method, but adds the original method as an attribute called "batchable", +which is used by remotebatch to split the call into separate encoding and +decoding phases. +''' +def plain(*args, **opts): +batchable = f(*args, **opts) +encargsorres, encresref = next(batchable) +if not encresref: +return encargsorres # a local result in this case +self = args[0] +cmd = pycompat.bytesurl(f.__name__) # ensure cmd is ascii bytestr +encresref.set(self._submitone(cmd, encargsorres)) +return next(batchable) +setattr(plain, 'batchable', f) +return plain + +class future(object): +'''placeholder for a value to be set later''' +def set(self, value): +if util.safehasattr(self, 'value'): +raise error.RepoError("future is already set") +self.value = value + +class batcher(object): +'''base class for batches of commands submittable in a single request + +All methods invoked on instances of this class are simply queued and +return a a future for the result. Once you call submit(), all the queued +calls are performed and the results set in their respective futures. +''' +def __init__(self): +self.calls = [] +def __getattr__(self, name): +def call(*args, **opts): +resref = future() +# Please don't invent non-ascii method names, or you will +# give core hg a very sad time. +self.calls.append((name.encode('ascii'), args, opts, resref,)) +return resref +return call +def submit(self): +raise NotImplementedError() + +class iterbatcher(batcher): + +def submit(self): +raise NotImplementedError
Re: [PATCH 1 of 2] hgweb: fallback to checking wsgireq.env for REPO_NAME for 3rd party hosting
On Fri, Apr 6, 2018 at 3:18 PM, Matt Harbison wrote: > # HG changeset patch > # User Matt Harbison > # Date 1522957360 14400 > # Thu Apr 05 15:42:40 2018 -0400 > # Node ID d2fd52e2e5e0ce6369c551e7e00c06d36c21658f > # Parent d3286dd2ca2f9f9e2b332e00c4b25b21729c54f5 > hgweb: fallback to checking wsgireq.env for REPO_NAME for 3rd party hosting > Queued this series. > > Starting with d7fd203e36cc, SCM Manager began to 404 any repository access. > What's happening is that it is generating a python script that creates an > hgweb > application (not hgwebdir), and launches hgweb via wsgicgi. It must be > setting > REPO_NAME in the process environment before launching this script, which > gets > picked up and put into wsgireq.env when wsgicgi launches the hgweb > application. > From there, other variables (notably 'apppath' and 'dispatchpath') are > constructed differently. > > d7fd203e36cc^ (working): > > apppath: /hg/eng/devsetup > dispatchpath: > pathinfo: /eng/devsetup > reponame: eng/devsetup > > d7fd203e36cc: > > apppath: /hg > dispatchpath: eng/devsetup > pathinfo: /eng/devsetup > reponame: None > REPO_NAME: eng/devsetup > > Rather than having an existing installation break when Mercurial is > upgraded, > just resume checking the environment. I have no idea how many other > hosting > solutions would break without restoring this. > I was worried about someone relying on REPO_NAME. I was hoping we could get away with that BC bustage. But I guess people in the wild are setting it. Oh well. No big deal. > > diff --git a/mercurial/hgweb/request.py b/mercurial/hgweb/request.py > --- a/mercurial/hgweb/request.py > +++ b/mercurial/hgweb/request.py > @@ -162,6 +162,12 @@ def parserequestfromenv(env, reponame=No > env = {k: v.encode('latin-1') if isinstance(v, str) else v > for k, v in env.iteritems()} > > +# Some hosting solutions are emulating hgwebdir, and dispatching > directly > +# to an hgweb instance using this environment variable. This was > always > +# checked prior to d7fd203e36cc; keep doing so to avoid breaking them. > +if not reponame: > +reponame = env.get('REPO_NAME') > + > if altbaseurl: > altbaseurl = util.url(altbaseurl) > > ___ > 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