[PATCH] lfs: drop a duplicate blob verification method
# HG changeset patch # User Matt Harbison# Date 1522468951 14400 # Sat Mar 31 00:02:31 2018 -0400 # Node ID 9837cda5fd115adecf860d3a97e5a01c07ca72fc # Parent f1f70b2610da96054c6750122092adbb24e7aea8 lfs: drop a duplicate blob verification method diff --git a/hgext/lfs/blobstore.py b/hgext/lfs/blobstore.py --- a/hgext/lfs/blobstore.py +++ b/hgext/lfs/blobstore.py @@ -316,8 +316,9 @@ class _gitlfsremote(object): request = util.urlreq.request(href) if action == 'upload': # If uploading blobs, read data from local blobstore. -with localstore.open(oid) as fp: -_verifyfile(oid, fp) +if not localstore.verify(oid): +raise error.Abort(_('detected corrupt lfs object: %s') % oid, + hint=_('run hg verify')) request.data = filewithprogress(localstore.open(oid), None) request.get_method = lambda: 'PUT' @@ -491,18 +492,6 @@ def _verify(oid, content): raise error.Abort(_('detected corrupt lfs object: %s') % oid, hint=_('run hg verify')) -def _verifyfile(oid, fp): -sha256 = hashlib.sha256() -while True: -data = fp.read(1024 * 1024) -if not data: -break -sha256.update(data) -realoid = sha256.hexdigest() -if realoid != oid: -raise error.Abort(_('detected corrupt lfs object: %s') % oid, - hint=_('run hg verify')) - def remote(repo): """remotestore factory. return a store in _storemap depending on config""" url = util.url(repo.ui.config('lfs', 'url') or '') ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
[PATCH 1 of 2] server: refactor 'daemon_postexec' instructions into a dictionary
# HG changeset patch # User Matt Harbison# Date 1522466506 14400 # Fri Mar 30 23:21:46 2018 -0400 # Node ID 6e77d0a68122a6513521c94c4b8256b7e6da6f93 # Parent 45aa79668d4ee38866b0829786da076ef59b0381 server: refactor 'daemon_postexec' instructions into a dictionary diff --git a/mercurial/server.py b/mercurial/server.py --- a/mercurial/server.py +++ b/mercurial/server.py @@ -30,26 +30,35 @@ def runservice(opts, parentfn=None, init runargs=None, appendpid=False): '''Run a command as a service.''' +postexecargs = {} + +if opts['daemon_postexec']: +for inst in opts['daemon_postexec']: +if inst.startswith('unlink:'): +postexecargs['unlink'] = inst[7:] +elif inst.startswith('chdir:'): +postexecargs['chdir'] = inst[6:] +elif inst != 'none': +raise error.Abort(_('invalid value for --daemon-postexec: %s') + % inst) + # When daemonized on Windows, redirect stdout/stderr to the lockfile (which # gets cleaned up after the child is up and running), so that the parent can # read and print the error if this child dies early. See 594dd384803c. On # other platforms, the child can write to the parent's stdio directly, until # it is redirected prior to runfn(). if pycompat.iswindows and opts['daemon_postexec']: -for inst in opts['daemon_postexec']: -if inst.startswith('unlink:'): -lockpath = inst[7:] -if os.path.exists(lockpath): -procutil.stdout.flush() -procutil.stderr.flush() +if 'unlink' in postexecargs and os.path.exists(postexecargs['unlink']): +procutil.stdout.flush() +procutil.stderr.flush() -fd = os.open(lockpath, - os.O_WRONLY | os.O_APPEND | os.O_BINARY) -try: -os.dup2(fd, 1) -os.dup2(fd, 2) -finally: -os.close(fd) +fd = os.open(postexecargs['unlink'], + os.O_WRONLY | os.O_APPEND | os.O_BINARY) +try: +os.dup2(fd, 1) +os.dup2(fd, 2) +finally: +os.close(fd) def writepid(pid): if opts['pid_file']: @@ -103,21 +112,14 @@ def runservice(opts, parentfn=None, init if not opts['daemon']: writepid(procutil.getpid()) -if opts['daemon_postexec']: +if postexecargs: try: os.setsid() except AttributeError: pass -lockpath = None -for inst in opts['daemon_postexec']: -if inst.startswith('unlink:'): -lockpath = inst[7:] -elif inst.startswith('chdir:'): -os.chdir(inst[6:]) -elif inst != 'none': -raise error.Abort(_('invalid value for --daemon-postexec: %s') - % inst) +if 'chdir' in postexecargs: +os.chdir(postexecargs['chdir']) procutil.hidewindow() procutil.stdout.flush() procutil.stderr.flush() @@ -137,8 +139,8 @@ def runservice(opts, parentfn=None, init # Only unlink after redirecting stdout/stderr, so Windows doesn't # complain about a sharing violation. -if lockpath: -os.unlink(lockpath) +if 'unlink' in postexecargs: +os.unlink(postexecargs['unlink']) if runfn: return runfn() ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
[PATCH 2 of 2] server: minor code cleanup
# HG changeset patch # User Matt Harbison# Date 1522467126 14400 # Fri Mar 30 23:32:06 2018 -0400 # Node ID f1f70b2610da96054c6750122092adbb24e7aea8 # Parent 6e77d0a68122a6513521c94c4b8256b7e6da6f93 server: minor code cleanup Suggested by Yuya after 77f9e95fe3c4, this is mostly using named values for stdio descriptors. The lockfile is also opened in binary mode when reading back content from the child. diff --git a/mercurial/server.py b/mercurial/server.py --- a/mercurial/server.py +++ b/mercurial/server.py @@ -55,8 +55,8 @@ def runservice(opts, parentfn=None, init fd = os.open(postexecargs['unlink'], os.O_WRONLY | os.O_APPEND | os.O_BINARY) try: -os.dup2(fd, 1) -os.dup2(fd, 2) +os.dup2(fd, procutil.stdout.fileno()) +os.dup2(fd, procutil.stderr.fileno()) finally: os.close(fd) @@ -94,7 +94,7 @@ def runservice(opts, parentfn=None, init # If the daemonized process managed to write out an error msg, # report it. if pycompat.iswindows and os.path.exists(lockpath): -with open(lockpath) as log: +with open(lockpath, 'rb') as log: for line in log: procutil.stderr.write(line) raise error.Abort(_('child process failed to start')) @@ -129,12 +129,14 @@ def runservice(opts, parentfn=None, init if logfile: logfilefd = os.open(logfile, os.O_RDWR | os.O_CREAT | os.O_APPEND, 0o666) -os.dup2(nullfd, 0) -os.dup2(logfilefd, 1) -os.dup2(logfilefd, 2) -if nullfd not in (0, 1, 2): +os.dup2(nullfd, procutil.stdin.fileno()) +os.dup2(logfilefd, procutil.stdout.fileno()) +os.dup2(logfilefd, procutil.stderr.fileno()) +stdio = (procutil.stdin.fileno(), procutil.stdout.fileno(), + procutil.stderr.fileno()) +if nullfd not in stdio: os.close(nullfd) -if logfile and logfilefd not in (0, 1, 2): +if logfile and logfilefd not in stdio: os.close(logfilefd) # Only unlink after redirecting stdout/stderr, so Windows doesn't ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
Re: [PATCH 2 of 2] tests: partially stabilize test-fix-* for Windows
On Fri, 30 Mar 2018 22:21:51 -0400, Yuya Nishiharawrote: On Fri, 30 Mar 2018 21:43:42 -0400, Matt Harbison wrote: # HG changeset patch # User Matt Harbison # Date 1522458729 14400 # Fri Mar 30 21:12:09 2018 -0400 # Node ID 3262e4f5d83b86754e8d4bd56ba651cf166a87d8 # Parent d0bae217b58314cd50c43e345e754f2f373b0441 tests: partially stabilize test-fix-* for Windows It looks like {rootpath} may not be getting translated on Windows. But this eliminates all of the other test spew. This will conflict with D2988. Can you take a look? https://phab.mercurial-scm.org/D2988 My patch can be dropped. ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
D2988: fix: use a portable python script instead of sed in test
mharbison72 added a comment. sys.std* need the procutil.setbinary() treatment, and globbing applied to the delta below to keep Windows happy. Also, test-fix-topology.t probably needs the same fix. --- c:/Users/Matt/projects/hg/tests/test-fix.t +++ c:/Users/Matt/projects/hg/tests/test-fix.t.err @@ -930,7 +935,7 @@ $ hg commit -Aqm "foo" $ printf "Foo\nbar\nBaz\n" > foo.changed $ hg --debug fix --working-dir - subprocess: /usr/bin/python $TESTTMP/uppercase.py 1-1 3-3 + subprocess: c:/Python27/python.exe $TESTTMP/uppercase.py 1-1 3-3 $ cd .. I'm not sure if you have any idea why, but it seems like {rootpath} is getting lost on Windows. (The changes here are because the printfs don't get run properly on Windows when run directly.) https://www.mercurial-scm.org/pipermail/mercurial-devel/2018-March/114691.html REPOSITORY rHG Mercurial REVISION DETAIL https://phab.mercurial-scm.org/D2988 To: hooper, #hg-reviewers Cc: mharbison72, mercurial-devel ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
Re: [PATCH 2 of 2] tests: partially stabilize test-fix-* for Windows
On Fri, 30 Mar 2018 21:43:42 -0400, Matt Harbison wrote: > # HG changeset patch > # User Matt Harbison> # Date 1522458729 14400 > # Fri Mar 30 21:12:09 2018 -0400 > # Node ID 3262e4f5d83b86754e8d4bd56ba651cf166a87d8 > # Parent d0bae217b58314cd50c43e345e754f2f373b0441 > tests: partially stabilize test-fix-* for Windows > > It looks like {rootpath} may not be getting translated on Windows. But this > eliminates all of the other test spew. This will conflict with D2988. Can you take a look? https://phab.mercurial-scm.org/D2988 ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
Re: [PATCH 1 of 2] tests: conditionalize test-stream-bundle-v2 for Windows
On Fri, 30 Mar 2018 21:43:41 -0400, Matt Harbison wrote: > # HG changeset patch > # User Matt Harbison> # Date 1522457616 14400 > # Fri Mar 30 20:53:36 2018 -0400 > # Node ID d0bae217b58314cd50c43e345e754f2f373b0441 > # Parent 74bbfa1b88c69471713bcaa0c8124df4ce93783c > tests: conditionalize test-stream-bundle-v2 for Windows Queued this, thanks. ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
Re: [PATCH V2] server: add an error feedback mechanism for when the daemon fails to launch
On Fri, 30 Mar 2018 21:34:02 -0400, Matt Harbison wrote: > # HG changeset patch > # User Matt Harbison> # Date 1522210269 14400 > # Wed Mar 28 00:11:09 2018 -0400 > # Node ID 74bbfa1b88c69471713bcaa0c8124df4ce93783c > # Parent b9dd8403d8ff4b36847ce405c0db127ca64491a1 > server: add an error feedback mechanism for when the daemon fails to launch Queued, thanks. > +# When daemonized on Windows, redirect stdout/stderr to the lockfile > (which > +# gets cleaned up after the child is up and running), so that the parent > can > +# read and print the error if this child dies early. See 594dd384803c. > On > +# other platforms, the child can write to the parent's stdio directly, > until > +# it is redirected prior to runfn(). > +if pycompat.iswindows and opts['daemon_postexec']: > +for inst in opts['daemon_postexec']: > +if inst.startswith('unlink:'): > +lockpath = inst[7:] > +if os.path.exists(lockpath): > +procutil.stdout.flush() > +procutil.stderr.flush() > + > +fd = os.open(lockpath, > + os.O_WRONLY | os.O_APPEND | os.O_BINARY) > +try: > +os.dup2(fd, 1) > +os.dup2(fd, 2) Nit: procutil.stdout/stderr.fileno() will look slightly nicer. > if pid < 0: > +# If the daemonized process managed to write out an error > msg, > +# report it. > +if pycompat.iswindows and os.path.exists(lockpath): > +with open(lockpath) as log: Nit: 'rb' > + > +lockpath = None > for inst in opts['daemon_postexec']: > if inst.startswith('unlink:'): > lockpath = inst[7:] > -os.unlink(lockpath) > elif inst.startswith('chdir:'): > os.chdir(inst[6:]) > elif inst != 'none': > @@ -107,6 +135,11 @@ def runservice(opts, parentfn=None, init > if logfile and logfilefd not in (0, 1, 2): > os.close(logfilefd) > > +# Only unlink after redirecting stdout/stderr, so Windows doesn't > +# complain about a sharing violation. > +if lockpath: > +os.unlink(lockpath) Perhaps we should build a dict of 'daemon_postexec' instructions instead of parsing them twice. This "lockpath" change makes them effectively unordered. ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
[PATCH 11 of 11] templater: drop global exception catcher from runfilter() (API)
# HG changeset patch # User Yuya Nishihara# Date 1521359827 -32400 # Sun Mar 18 16:57:07 2018 +0900 # Node ID 9a2646947602dd11d7f65422e3ea27fabb3ee555 # Parent bf00dda4a053a9dbf7163e993a454dd9dc03cb1f templater: drop global exception catcher from runfilter() (API) Now all built-in template filters declare input data types or handle type errors by themselves. .. api:: Template filters should declare input data type and/or catch AttributeError, ValueError, TypeError, etc. as needed. See the doc of ``registrar.templatefilters`` for details. diff --git a/mercurial/templateutil.py b/mercurial/templateutil.py --- a/mercurial/templateutil.py +++ b/mercurial/templateutil.py @@ -428,8 +428,6 @@ def runfilter(context, mapping, data): try: thing = unwrapastype(thing, getattr(filt, '_intype', None)) return filt(thing) -except (ValueError, AttributeError, TypeError): -raise error.Abort(_formatfiltererror(arg, filt)) except error.ParseError as e: raise error.ParseError(bytes(e), hint=_formatfiltererror(arg, filt)) ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
[PATCH 01 of 11] hgweb: use registrar to declare "websub" template filter
# HG changeset patch # User Yuya Nishihara# Date 1521459546 -32400 # Mon Mar 19 20:39:06 2018 +0900 # Node ID eb32cf0cbbf309242f75d5b94f27744b1a1abd5d # Parent 81951fe000108850cd19f4f1185f803e20778d1b hgweb: use registrar to declare "websub" template filter Prepares for adding 'intype' attribute. diff --git a/mercurial/hgweb/hgweb_mod.py b/mercurial/hgweb/hgweb_mod.py --- a/mercurial/hgweb/hgweb_mod.py +++ b/mercurial/hgweb/hgweb_mod.py @@ -27,6 +27,7 @@ from .. import ( hook, profiling, pycompat, +registrar, repoview, templatefilters, templater, @@ -170,6 +171,9 @@ class requestcontext(object): or req.apppath or self.repo.root) +filters = {} +templatefilter = registrar.templatefilter(filters) +@templatefilter('websub') def websubfilter(text): return templatefilters.websub(text, self.websubtable) @@ -191,7 +195,7 @@ class requestcontext(object): } tres = formatter.templateresources(self.repo.ui, self.repo) tmpl = templater.templater.frommapfile(mapfile, - filters={'websub': websubfilter}, + filters=filters, defaults=defaults, resources=tres) return tmpl ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
[PATCH 10 of 11] templatefilters: raise ProgrammingError if unencodable type passed to json()
# HG changeset patch # User Yuya Nishihara# Date 1521359588 -32400 # Sun Mar 18 16:53:08 2018 +0900 # Node ID bf00dda4a053a9dbf7163e993a454dd9dc03cb1f # Parent 68b69a593cf0865a1485d10a87c58f1c3254fb76 templatefilters: raise ProgrammingError if unencodable type passed to json() This shouldn't happen for any template data types (though I know it does because of some templater bugs.) Let's clarify it is a bug. diff --git a/mercurial/templatefilters.py b/mercurial/templatefilters.py --- a/mercurial/templatefilters.py +++ b/mercurial/templatefilters.py @@ -263,8 +263,7 @@ def json(obj, paranoid=True): elif util.safehasattr(obj, '__iter__'): out = [json(i, paranoid) for i in obj] return '[' + ', '.join(out) + ']' -else: -raise TypeError('cannot encode type %s' % obj.__class__.__name__) +raise error.ProgrammingError('cannot encode %r' % obj) @templatefilter('lower', intype=bytes) def lower(text): ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
[PATCH 05 of 11] templatefuncs: use evaldate() where seems appropriate
# HG changeset patch # User Yuya Nishihara# Date 1521356302 -32400 # Sun Mar 18 15:58:22 2018 +0900 # Node ID 5195b8b4c84633ed4529a0c5430c3b04e88f6898 # Parent 01d55beea227cca5b033cfe9dd4a0a068aad5b8c templatefuncs: use evaldate() where seems appropriate This means date("today") is allowed. Also fixes evaldate() to forcibly use the custom error message if specified. diff --git a/mercurial/templatefuncs.py b/mercurial/templatefuncs.py --- a/mercurial/templatefuncs.py +++ b/mercurial/templatefuncs.py @@ -52,18 +52,16 @@ def date(context, mapping, args): # i18n: "date" is a keyword raise error.ParseError(_("date expects one or two arguments")) -date = evalfuncarg(context, mapping, args[0]) +date = evaldate(context, mapping, args[0], +# i18n: "date" is a keyword +_("date expects a date information")) fmt = None if len(args) == 2: fmt = evalstring(context, mapping, args[1]) -try: -if fmt is None: -return dateutil.datestr(date) -else: -return dateutil.datestr(date, fmt) -except (TypeError, ValueError): -# i18n: "date" is a keyword -raise error.ParseError(_("date expects a date information")) +if fmt is None: +return dateutil.datestr(date) +else: +return dateutil.datestr(date, fmt) @templatefunc('dict([[key=]value...])', argspec='*args **kwargs') def dict_(context, mapping, args): diff --git a/mercurial/templateutil.py b/mercurial/templateutil.py --- a/mercurial/templateutil.py +++ b/mercurial/templateutil.py @@ -330,6 +330,10 @@ def unwrapdate(thing, err=None): return dateutil.parsedate(thing) except AttributeError: raise error.ParseError(err or _('not a date tuple nor a string')) +except error.ParseError: +if not err: +raise +raise error.ParseError(err) def evalinteger(context, mapping, arg, err=None): return unwrapinteger(evalrawexp(context, mapping, arg), err) ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
[PATCH 03 of 11] templatefilters: declare input type as bytes where appropriate
# HG changeset patch # User Yuya Nishihara# Date 1521355348 -32400 # Sun Mar 18 15:42:28 2018 +0900 # Node ID 5b226692c357623256819fc6ab2abead595734bc # Parent a31ddf984c1b851d78faa753b12aa694f6884ee5 templatefilters: declare input type as bytes where appropriate Some test outputs changed since input is now coerced to a byte string. I think that's okay. Maybe {date} should have some readable representation? diff --git a/mercurial/hgweb/hgweb_mod.py b/mercurial/hgweb/hgweb_mod.py --- a/mercurial/hgweb/hgweb_mod.py +++ b/mercurial/hgweb/hgweb_mod.py @@ -173,7 +173,7 @@ class requestcontext(object): filters = {} templatefilter = registrar.templatefilter(filters) -@templatefilter('websub') +@templatefilter('websub', intype=bytes) def websubfilter(text): return templatefilters.websub(text, self.websubtable) diff --git a/mercurial/templatefilters.py b/mercurial/templatefilters.py --- a/mercurial/templatefilters.py +++ b/mercurial/templatefilters.py @@ -40,7 +40,7 @@ filters = {} templatefilter = registrar.templatefilter(filters) -@templatefilter('addbreaks') +@templatefilter('addbreaks', intype=bytes) def addbreaks(text): """Any text. Add an XHTML "" tag before the end of every line except the last. @@ -90,7 +90,7 @@ def age(date, abbrev=False): return '%s from now' % fmt(t, n, a) return '%s ago' % fmt(t, n, a) -@templatefilter('basename') +@templatefilter('basename', intype=bytes) def basename(path): """Any text. Treats the text as a path, and returns the last component of the path after splitting by the path separator. @@ -103,14 +103,14 @@ def count(i): """List or text. Returns the length as an integer.""" return len(i) -@templatefilter('dirname') +@templatefilter('dirname', intype=bytes) def dirname(path): """Any text. Treats the text as a path, and strips the last component of the path after splitting by the path separator. """ return os.path.dirname(path) -@templatefilter('domain') +@templatefilter('domain', intype=bytes) def domain(author): """Any text. Finds the first string that looks like an email address, and extracts just the domain component. Example: ``User @@ -125,7 +125,7 @@ def domain(author): author = author[:f] return author -@templatefilter('email') +@templatefilter('email', intype=bytes) def email(text): """Any text. Extracts the first string that looks like an email address. Example: ``User `` becomes @@ -133,7 +133,7 @@ def email(text): """ return stringutil.email(text) -@templatefilter('escape') +@templatefilter('escape', intype=bytes) def escape(text): """Any text. Replaces the special XML/XHTML characters "&", "<" and ">" with XML entities, and filters out NUL characters. @@ -170,17 +170,17 @@ def fill(text, width, initindent='', han width, initindent, hangindent) + rest for para, rest in findparas()]) -@templatefilter('fill68') +@templatefilter('fill68', intype=bytes) def fill68(text): """Any text. Wraps the text to fit in 68 columns.""" return fill(text, 68) -@templatefilter('fill76') +@templatefilter('fill76', intype=bytes) def fill76(text): """Any text. Wraps the text to fit in 76 columns.""" return fill(text, 76) -@templatefilter('firstline') +@templatefilter('firstline', intype=bytes) def firstline(text): """Any text. Returns the first line of text.""" try: @@ -188,7 +188,7 @@ def firstline(text): except IndexError: return '' -@templatefilter('hex') +@templatefilter('hex', intype=bytes) def hexfilter(text): """Any text. Convert a binary Mercurial node identifier into its long hexadecimal representation. @@ -262,17 +262,17 @@ def json(obj, paranoid=True): else: raise TypeError('cannot encode type %s' % obj.__class__.__name__) -@templatefilter('lower') +@templatefilter('lower', intype=bytes) def lower(text): """Any text. Converts the text to lowercase.""" return encoding.lower(text) -@templatefilter('nonempty') +@templatefilter('nonempty', intype=bytes) def nonempty(text): """Any text. Returns '(none)' if the string is empty.""" return text or "(none)" -@templatefilter('obfuscate') +@templatefilter('obfuscate', intype=bytes) def obfuscate(text): """Any text. Returns the input text rendered as a sequence of XML entities. @@ -280,7 +280,7 @@ def obfuscate(text): text = unicode(text, pycompat.sysstr(encoding.encoding), r'replace') return ''.join(['
[PATCH 09 of 11] templatefilters: handle TypeError by count()
# HG changeset patch # User Yuya Nishihara# Date 1521359264 -32400 # Sun Mar 18 16:47:44 2018 +0900 # Node ID 68b69a593cf0865a1485d10a87c58f1c3254fb76 # Parent 068cf6f31d4733d74d084d0cca61a9ff04939ea5 templatefilters: handle TypeError by count() Prepares for removing the weird exception catcher from runfilter(). diff --git a/mercurial/templatefilters.py b/mercurial/templatefilters.py --- a/mercurial/templatefilters.py +++ b/mercurial/templatefilters.py @@ -11,6 +11,7 @@ import os import re import time +from .i18n import _ from . import ( encoding, error, @@ -101,7 +102,10 @@ def basename(path): @templatefilter('count') def count(i): """List or text. Returns the length as an integer.""" -return len(i) +try: +return len(i) +except TypeError: +raise error.ParseError(_('not countable')) @templatefilter('dirname', intype=bytes) def dirname(path): diff --git a/tests/test-command-template.t b/tests/test-command-template.t --- a/tests/test-command-template.t +++ b/tests/test-command-template.t @@ -2277,6 +2277,11 @@ Count filter: o 0: children: 1, tags: 0, file_adds: 1, ancestors: 1 + $ hg log -l1 -T '{termwidth|count}\n' + hg: parse error: not countable + (template filter 'count' is not compatible with keyword 'termwidth') + [255] + Upper/lower filters: $ hg log -r0 --template '{branch|upper}\n' @@ -3266,7 +3271,8 @@ Test min/max of if() result Test laziness of if() then/else clause $ hg debugtemplate '{count(0)}' - abort: incompatible use of template filter 'count' + hg: parse error: not countable + (incompatible use of template filter 'count') [255] $ hg debugtemplate '{if(true, "", count(0))}' $ hg debugtemplate '{if(false, count(0), "")}' ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
[PATCH 02 of 11] templatefilters: allow declaration of input data type
# HG changeset patch # User Yuya Nishihara# Date 1521353698 -32400 # Sun Mar 18 15:14:58 2018 +0900 # Node ID a31ddf984c1b851d78faa753b12aa694f6884ee5 # Parent eb32cf0cbbf309242f75d5b94f27744b1a1abd5d templatefilters: allow declaration of input data type Currently filters take an unwrapped value, which should have no hybrid magic but actually it does because stringify() relies on it. The 'intype' allows us to pre-process the magic by .e.g. evalstring() keeping filter functions as simple as they are now. stringify() is ported as an example. More follow. diff --git a/mercurial/registrar.py b/mercurial/registrar.py --- a/mercurial/registrar.py +++ b/mercurial/registrar.py @@ -324,7 +324,7 @@ class templatefilter(_templateregistrarb templatefilter = registrar.templatefilter() -@templatefilter('myfilter') +@templatefilter('myfilter', intype=bytes) def myfilterfunc(text): '''Explanation of this template filter ''' @@ -332,6 +332,9 @@ class templatefilter(_templateregistrarb The first string argument is used also in online help. +Optional argument 'intype' defines the type of the input argument, +which should be (bytes, int, or None for any.) + 'templatefilter' instance in example above can be used to decorate multiple functions. @@ -342,6 +345,9 @@ class templatefilter(_templateregistrarb Otherwise, explicit 'templatefilters.loadkeyword()' is needed. """ +def _extrasetup(self, name, func, intype=None): +func._intype = intype + class templatefunc(_templateregistrarbase): """Decorator to register template function diff --git a/mercurial/templatefilters.py b/mercurial/templatefilters.py --- a/mercurial/templatefilters.py +++ b/mercurial/templatefilters.py @@ -354,12 +354,12 @@ def splitlines(text): def stringescape(text): return stringutil.escapestr(text) -@templatefilter('stringify') +@templatefilter('stringify', intype=bytes) def stringify(thing): """Any type. Turns the value into text by converting values into text and concatenating them. """ -return templateutil.stringify(thing) +return thing # coerced by the intype @templatefilter('stripdir') def stripdir(text): diff --git a/mercurial/templateutil.py b/mercurial/templateutil.py --- a/mercurial/templateutil.py +++ b/mercurial/templateutil.py @@ -342,6 +342,7 @@ def evalstringliteral(context, mapping, return stringify(thing) _unwrapfuncbytype = { +None: _unwrapvalue, bytes: stringify, int: unwrapinteger, } @@ -400,8 +401,9 @@ def runtemplate(context, mapping, templa def runfilter(context, mapping, data): arg, filt = data -thing = evalfuncarg(context, mapping, arg) +thing = evalrawexp(context, mapping, arg) try: +thing = unwrapastype(thing, getattr(filt, '_intype', None)) return filt(thing) except (ValueError, AttributeError, TypeError): sym = findsymbolicname(arg) ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
[PATCH 06 of 11] templater: attach hint to input-type error of runfilter()
# HG changeset patch # User Yuya Nishihara# Date 1521554256 -32400 # Tue Mar 20 22:57:36 2018 +0900 # Node ID 044cf5cbae04306dc21919b1dbb461a1f01b3a2e # Parent 5195b8b4c84633ed4529a0c5430c3b04e88f6898 templater: attach hint to input-type error of runfilter() Tests will be added by the next patch. diff --git a/mercurial/templateutil.py b/mercurial/templateutil.py --- a/mercurial/templateutil.py +++ b/mercurial/templateutil.py @@ -423,14 +423,17 @@ def runfilter(context, mapping, data): thing = unwrapastype(thing, getattr(filt, '_intype', None)) return filt(thing) except (ValueError, AttributeError, TypeError): -sym = findsymbolicname(arg) -if sym: -msg = (_("template filter '%s' is not compatible with keyword '%s'") - % (pycompat.sysbytes(filt.__name__), sym)) -else: -msg = (_("incompatible use of template filter '%s'") - % pycompat.sysbytes(filt.__name__)) -raise error.Abort(msg) +raise error.Abort(_formatfiltererror(arg, filt)) +except error.ParseError as e: +raise error.ParseError(bytes(e), hint=_formatfiltererror(arg, filt)) + +def _formatfiltererror(arg, filt): +fn = pycompat.sysbytes(filt.__name__) +sym = findsymbolicname(arg) +if not sym: +return _("incompatible use of template filter '%s'") % fn +return (_("template filter '%s' is not compatible with keyword '%s'") +% (fn, sym)) def runmap(context, mapping, data): darg, targ = data ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
[PATCH 04 of 11] templater: factor out function that parses argument as date tuple
# HG changeset patch # User Yuya Nishihara# Date 1521356131 -32400 # Sun Mar 18 15:55:31 2018 +0900 # Node ID 01d55beea227cca5b033cfe9dd4a0a068aad5b8c # Parent 5b226692c357623256819fc6ab2abead595734bc templater: factor out function that parses argument as date tuple diff --git a/mercurial/templatefuncs.py b/mercurial/templatefuncs.py --- a/mercurial/templatefuncs.py +++ b/mercurial/templatefuncs.py @@ -34,6 +34,7 @@ from .utils import ( evalrawexp = templateutil.evalrawexp evalfuncarg = templateutil.evalfuncarg evalboolean = templateutil.evalboolean +evaldate = templateutil.evaldate evalinteger = templateutil.evalinteger evalstring = templateutil.evalstring evalstringliteral = templateutil.evalstringliteral @@ -373,12 +374,9 @@ def localdate(context, mapping, args): # i18n: "localdate" is a keyword raise error.ParseError(_("localdate expects one or two arguments")) -date = evalfuncarg(context, mapping, args[0]) -try: -date = dateutil.parsedate(date) -except AttributeError: # not str nor date tuple -# i18n: "localdate" is a keyword -raise error.ParseError(_("localdate expects a date information")) +date = evaldate(context, mapping, args[0], +# i18n: "localdate" is a keyword +_("localdate expects a date information")) if len(args) >= 2: tzoffset = None tz = evalfuncarg(context, mapping, args[1]) diff --git a/mercurial/templateutil.py b/mercurial/templateutil.py --- a/mercurial/templateutil.py +++ b/mercurial/templateutil.py @@ -16,6 +16,7 @@ from . import ( util, ) from .utils import ( +dateutil, stringutil, ) @@ -318,6 +319,18 @@ def evalboolean(context, mapping, arg): # empty dict/list should be False as they are expected to be '' return bool(stringify(thing)) +def evaldate(context, mapping, arg, err=None): +"""Evaluate given argument as a date tuple or a date string; returns +a (unixtime, offset) tuple""" +return unwrapdate(evalrawexp(context, mapping, arg), err) + +def unwrapdate(thing, err=None): +thing = _unwrapvalue(thing) +try: +return dateutil.parsedate(thing) +except AttributeError: +raise error.ParseError(err or _('not a date tuple nor a string')) + def evalinteger(context, mapping, arg, err=None): return unwrapinteger(evalrawexp(context, mapping, arg), err) ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
[PATCH 07 of 11] templatefilters: declare input type as date where appropriate
# HG changeset patch # User Yuya Nishihara# Date 1521357164 -32400 # Sun Mar 18 16:12:44 2018 +0900 # Node ID baf331e387375dd7ad56b45b59fce950c385d17b # Parent 044cf5cbae04306dc21919b1dbb461a1f01b3a2e templatefilters: declare input type as date where appropriate I'm not sure if the templateutil.date type can be a thing. Currently it's just a constant. diff --git a/mercurial/registrar.py b/mercurial/registrar.py --- a/mercurial/registrar.py +++ b/mercurial/registrar.py @@ -333,7 +333,7 @@ class templatefilter(_templateregistrarb The first string argument is used also in online help. Optional argument 'intype' defines the type of the input argument, -which should be (bytes, int, or None for any.) +which should be (bytes, int, templateutil.date, or None for any.) 'templatefilter' instance in example above can be used to decorate multiple functions. diff --git a/mercurial/templatefilters.py b/mercurial/templatefilters.py --- a/mercurial/templatefilters.py +++ b/mercurial/templatefilters.py @@ -55,7 +55,7 @@ agescales = [("year", 3600 * 24 * 365, ' ("minute", 60, 'm'), ("second", 1, 's')] -@templatefilter('age') +@templatefilter('age', intype=templateutil.date) def age(date, abbrev=False): """Date. Returns a human-readable date/time difference between the given date/time and the current date/time. @@ -195,21 +195,21 @@ def hexfilter(text): """ return node.hex(text) -@templatefilter('hgdate') +@templatefilter('hgdate', intype=templateutil.date) def hgdate(text): """Date. Returns the date as a pair of numbers: "1157407993 25200" (Unix timestamp, timezone offset). """ return "%d %d" % text -@templatefilter('isodate') +@templatefilter('isodate', intype=templateutil.date) def isodate(text): """Date. Returns the date in ISO 8601 format: "2009-08-18 13:00 +0200". """ return dateutil.datestr(text, '%Y-%m-%d %H:%M %1%2') -@templatefilter('isodatesec') +@templatefilter('isodatesec', intype=templateutil.date) def isodatesec(text): """Date. Returns the date in ISO 8601 format, including seconds: "2009-08-18 13:00:13 +0200". See also the rfc3339date @@ -303,14 +303,14 @@ def revescape(text): """ return urlreq.quote(text, safe='/@').replace('/', '%252F') -@templatefilter('rfc3339date') +@templatefilter('rfc3339date', intype=templateutil.date) def rfc3339date(text): """Date. Returns a date using the Internet date format specified in RFC 3339: "2009-08-18T13:00:13+02:00". """ return dateutil.datestr(text, "%Y-%m-%dT%H:%M:%S%1:%2") -@templatefilter('rfc822date') +@templatefilter('rfc822date', intype=templateutil.date) def rfc822date(text): """Date. Returns a date using the same format used in email headers: "Tue, 18 Aug 2009 13:00:13 +0200". @@ -335,7 +335,7 @@ def shortbisect(label): return label[0:1].upper() return ' ' -@templatefilter('shortdate') +@templatefilter('shortdate', intype=templateutil.date) def shortdate(text): """Date. Returns a date like "2006-09-18".""" return dateutil.shortdate(text) diff --git a/mercurial/templateutil.py b/mercurial/templateutil.py --- a/mercurial/templateutil.py +++ b/mercurial/templateutil.py @@ -26,6 +26,11 @@ class ResourceUnavailable(error.Abort): class TemplateNotFound(error.Abort): pass +# stub for representing a date type; may be a real date type that can +# provide a readable string value +class date(object): +pass + class hybrid(object): """Wrapper for list or dict to support legacy template @@ -361,6 +366,7 @@ def evalstringliteral(context, mapping, _unwrapfuncbytype = { None: _unwrapvalue, bytes: stringify, +date: unwrapdate, int: unwrapinteger, } diff --git a/tests/test-command-template.t b/tests/test-command-template.t --- a/tests/test-command-template.t +++ b/tests/test-command-template.t @@ -2806,7 +2806,8 @@ Behind the scenes, this would throw Type Behind the scenes, this will throw a ValueError $ hg log -l 3 --template 'line: {desc|shortdate}\n' - abort: template filter 'shortdate' is not compatible with keyword 'desc' + hg: parse error: invalid date: 'Modify, add, remove, rename' + (template filter 'shortdate' is not compatible with keyword 'desc') [255] Behind the scenes, this would throw AttributeError without intype=bytes @@ -2827,11 +2828,13 @@ Behind the scenes, this will throw Value [255] $ hg tip -T '{author|email|shortdate}\n' - abort: template filter 'shortdate' is not compatible with keyword 'author' + hg: parse error: invalid date: 'test' + (template filter 'shortdate' is not compatible with keyword 'author') [255] $ hg tip -T '{get(extras, "branch")|shortdate}\n' - abort: incompatible use of template filter 'shortdate' + hg: parse error: invalid date: 'default' + (incompatible use of template filter 'shortdate') [255] Error in nested
[PATCH 08 of 11] keyword: declare input type of date filters as date
# HG changeset patch # User Yuya Nishihara# Date 1521360159 -32400 # Sun Mar 18 17:02:39 2018 +0900 # Node ID 068cf6f31d4733d74d084d0cca61a9ff04939ea5 # Parent baf331e387375dd7ad56b45b59fce950c385d17b keyword: declare input type of date filters as date Dropped redundant dateutil.parsedate(), which is now handled by the templater. diff --git a/hgext/keyword.py b/hgext/keyword.py --- a/hgext/keyword.py +++ b/hgext/keyword.py @@ -109,6 +109,7 @@ from mercurial import ( registrar, scmutil, templatefilters, +templateutil, util, ) from mercurial.utils import ( @@ -156,27 +157,27 @@ configitem('keywordset', 'svn', default=False, ) # date like in cvs' $Date -@templatefilter('utcdate') -def utcdate(text): +@templatefilter('utcdate', intype=templateutil.date) +def utcdate(date): '''Date. Returns a UTC-date in this format: "2009/08/18 11:00:13". ''' dateformat = '%Y/%m/%d %H:%M:%S' -return dateutil.datestr((dateutil.parsedate(text)[0], 0), dateformat) +return dateutil.datestr((date[0], 0), dateformat) # date like in svn's $Date -@templatefilter('svnisodate') -def svnisodate(text): +@templatefilter('svnisodate', intype=templateutil.date) +def svnisodate(date): '''Date. Returns a date in this format: "2009-08-18 13:00:13 +0200 (Tue, 18 Aug 2009)". ''' -return dateutil.datestr(text, '%Y-%m-%d %H:%M:%S %1%2 (%a, %d %b %Y)') +return dateutil.datestr(date, '%Y-%m-%d %H:%M:%S %1%2 (%a, %d %b %Y)') # date like in svn's $Id -@templatefilter('svnutcdate') -def svnutcdate(text): +@templatefilter('svnutcdate', intype=templateutil.date) +def svnutcdate(date): '''Date. Returns a UTC-date in this format: "2009-08-18 11:00:13Z". ''' dateformat = '%Y-%m-%d %H:%M:%SZ' -return dateutil.datestr((dateutil.parsedate(text)[0], 0), dateformat) +return dateutil.datestr((date[0], 0), dateformat) # make keyword tools accessible kwtools = {'hgcmd': ''} ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
[PATCH 1 of 2 RESEND] procutil: unroll uin/uout loop in protectstdio()
# HG changeset patch # User Yuya Nishihara# Date 1521947238 -32400 # Sun Mar 25 12:07:18 2018 +0900 # Node ID 6fdab0e7824cd95ea5edd4511d5063823ba423d5 # Parent 40be6a8728a046b3673a517af2a3e15574457728 procutil: unroll uin/uout loop in protectstdio() I'll change uout to be redirected to stderr. diff --git a/mercurial/utils/procutil.py b/mercurial/utils/procutil.py --- a/mercurial/utils/procutil.py +++ b/mercurial/utils/procutil.py @@ -221,17 +221,18 @@ def protectstdio(uin, uout): "owned" in that print(), exec(), etc. never reach to them. """ uout.flush() -newfiles = [] nullfd = os.open(os.devnull, os.O_RDWR) -for f, sysf, mode in [(uin, stdin, r'rb'), - (uout, stdout, r'wb')]: -if f is sysf: -newfd = os.dup(f.fileno()) -os.dup2(nullfd, f.fileno()) -f = os.fdopen(newfd, mode) -newfiles.append(f) +fin, fout = uin, uout +if uin is stdin: +newfd = os.dup(uin.fileno()) +os.dup2(nullfd, uin.fileno()) +fin = os.fdopen(newfd, r'rb') +if uout is stdout: +newfd = os.dup(uout.fileno()) +os.dup2(nullfd, uout.fileno()) +fout = os.fdopen(newfd, r'wb') os.close(nullfd) -return tuple(newfiles) +return fin, fout def restorestdio(uin, uout, fin, fout): """Restore (uin, uout) streams from possibly duplicated (fin, fout)""" ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
[PATCH 2 of 2 RESEND] procutil: redirect ui.fout to stderr while stdio is protected
# HG changeset patch # User Yuya Nishihara# Date 1521947733 -32400 # Sun Mar 25 12:15:33 2018 +0900 # Node ID 81951fe000108850cd19f4f1185f803e20778d1b # Parent 6fdab0e7824cd95ea5edd4511d5063823ba423d5 procutil: redirect ui.fout to stderr while stdio is protected The new behavior seems slightly nicer as we can at least read the output. And this is similar to what the sshserver is doing, so we can probably reuse protectstdio() instead of the weird hook.redirect(True) hack. diff --git a/mercurial/utils/procutil.py b/mercurial/utils/procutil.py --- a/mercurial/utils/procutil.py +++ b/mercurial/utils/procutil.py @@ -213,25 +213,27 @@ def isstdout(f): return _testfileno(f, sys.__stdout__) def protectstdio(uin, uout): -"""Duplicate streams and redirect original to null if (uin, uout) are -stdio +"""Duplicate streams and redirect original if (uin, uout) are stdio + +If uin is stdin, it's redirected to /dev/null. If uout is stdout, it's +redirected to stderr so the output is still readable. Returns (fin, fout) which point to the original (uin, uout) fds, but may be copy of (uin, uout). The returned streams can be considered "owned" in that print(), exec(), etc. never reach to them. """ uout.flush() -nullfd = os.open(os.devnull, os.O_RDWR) fin, fout = uin, uout if uin is stdin: newfd = os.dup(uin.fileno()) +nullfd = os.open(os.devnull, os.O_RDONLY) os.dup2(nullfd, uin.fileno()) +os.close(nullfd) fin = os.fdopen(newfd, r'rb') if uout is stdout: newfd = os.dup(uout.fileno()) -os.dup2(nullfd, uout.fileno()) +os.dup2(stderr.fileno(), uout.fileno()) fout = os.fdopen(newfd, r'wb') -os.close(nullfd) return fin, fout def restorestdio(uin, uout, fin, fout): diff --git a/tests/test-commandserver.t b/tests/test-commandserver.t --- a/tests/test-commandserver.t +++ b/tests/test-commandserver.t @@ -249,6 +249,8 @@ check that local configs for the cached ...input=stringio('some input')) *** runcommand --config hooks.pre-identify=python:hook.hook id eff892de26ec tip + hook talking + now try to read something: '' Clean hook cached version $ rm hook.py* @@ -619,7 +621,7 @@ changelog and manifest would have invali > @command(b"debugwritestdout", norepo=True) > def debugwritestdout(ui): > os.write(1, "low-level stdout fd and\n") - > sys.stdout.write("stdout should be redirected to /dev/null\n") + > sys.stdout.write("stdout should be redirected to stderr\n") > sys.stdout.flush() > EOF $ cat <> .hg/hgrc @@ -657,6 +659,8 @@ changelog and manifest would have invali *** runcommand debugreadstdin read: '' *** runcommand debugwritestdout + low-level stdout fd and + stdout should be redirected to stderr run commandserver in commandserver, which is silly but should work: ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
[PATCH] py3: fix fix doctests to be bytes-safe
# HG changeset patch # User Yuya Nishihara# Date 1522459698 -32400 # Sat Mar 31 10:28:18 2018 +0900 # Node ID 40be6a8728a046b3673a517af2a3e15574457728 # Parent 2a2ce93e12f4a70fa4aa2efae74658e43cc0e989 py3: fix fix doctests to be bytes-safe diff --git a/hgext/fix.py b/hgext/fix.py --- a/hgext/fix.py +++ b/hgext/fix.py @@ -303,33 +303,34 @@ def difflineranges(content1, content2): present in content1. Relies on mdiff's idea of where the line endings are in the string. ->>> lines = lambda s: '\\n'.join([c for c in s]) +>>> from mercurial import pycompat +>>> lines = lambda s: b'\\n'.join([c for c in pycompat.iterbytestr(s)]) >>> difflineranges2 = lambda a, b: difflineranges(lines(a), lines(b)) ->>> difflineranges2('', '') -[] ->>> difflineranges2('a', '') +>>> difflineranges2(b'', b'') [] ->>> difflineranges2('', 'A') -[(1, 1)] ->>> difflineranges2('a', 'a') +>>> difflineranges2(b'a', b'') [] ->>> difflineranges2('a', 'A') +>>> difflineranges2(b'', b'A') [(1, 1)] ->>> difflineranges2('ab', '') +>>> difflineranges2(b'a', b'a') [] ->>> difflineranges2('', 'AB') +>>> difflineranges2(b'a', b'A') +[(1, 1)] +>>> difflineranges2(b'ab', b'') +[] +>>> difflineranges2(b'', b'AB') [(1, 2)] ->>> difflineranges2('abc', 'ac') +>>> difflineranges2(b'abc', b'ac') [] ->>> difflineranges2('ab', 'aCb') +>>> difflineranges2(b'ab', b'aCb') [(2, 2)] ->>> difflineranges2('abc', 'aBc') +>>> difflineranges2(b'abc', b'aBc') [(2, 2)] ->>> difflineranges2('ab', 'AB') +>>> difflineranges2(b'ab', b'AB') [(1, 2)] ->>> difflineranges2('abcde', 'aBcDe') +>>> difflineranges2(b'abcde', b'aBcDe') [(2, 2), (4, 4)] ->>> difflineranges2('abcde', 'aBCDe') +>>> difflineranges2(b'abcde', b'aBCDe') [(2, 4)] """ ranges = [] ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
[PATCH 1 of 2] tests: conditionalize test-stream-bundle-v2 for Windows
# HG changeset patch # User Matt Harbison# Date 1522457616 14400 # Fri Mar 30 20:53:36 2018 -0400 # Node ID d0bae217b58314cd50c43e345e754f2f373b0441 # Parent 74bbfa1b88c69471713bcaa0c8124df4ce93783c tests: conditionalize test-stream-bundle-v2 for Windows diff --git a/tests/test-stream-bundle-v2.t b/tests/test-stream-bundle-v2.t --- a/tests/test-stream-bundle-v2.t +++ b/tests/test-stream-bundle-v2.t @@ -70,6 +70,8 @@ Test that we can apply the bundle as a s bundle2-input-part: "stream2" (params: 3 mandatory) supported applying stream bundle 11 files to transfer, 1.65 KB of data + starting 4 threads for background file closing (?) + starting 4 threads for background file closing (?) adding [s] data/A.i (66 bytes) adding [s] data/B.i (66 bytes) adding [s] data/C.i (66 bytes) @@ -122,6 +124,8 @@ Test that we can apply the bundle as a s bundle2-input-part: "stream2" (params: 3 mandatory) supported applying stream bundle 11 files to transfer, 1.65 KB of data + starting 4 threads for background file closing (?) + starting 4 threads for background file closing (?) adding [s] data/A.i (66 bytes) adding [s] data/B.i (66 bytes) adding [s] data/C.i (66 bytes) ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
[PATCH 2 of 2] tests: partially stabilize test-fix-* for Windows
# HG changeset patch # User Matt Harbison# Date 1522458729 14400 # Fri Mar 30 21:12:09 2018 -0400 # Node ID 3262e4f5d83b86754e8d4bd56ba651cf166a87d8 # Parent d0bae217b58314cd50c43e345e754f2f373b0441 tests: partially stabilize test-fix-* for Windows It looks like {rootpath} may not be getting translated on Windows. But this eliminates all of the other test spew. --- c:/Users/Matt/projects/hg/tests/test-fix.t +++ c:/Users/Matt/projects/hg/tests/test-fix.t.err @@ -465,7 +465,7 @@ $ hg --config "fix.fail:command=sh $TESTTMP/cmd.sh {rootpath}" \ >--config "fix.fail:fileset=hello.txt" \ >fix --working-dir - [wdir] fail: hello.txt: some + [wdir] fail: : some [wdir] fail: error $ cat hello.txt hello 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 @@ -6,7 +6,7 @@ relationships. We indicate fixed file co > [extensions] > fix = > [fix] - > uppercase-whole-file:command=sed -e 's/.*/\U&/' + > uppercase-whole-file:command=sed -e "s/.*/\U&/" > uppercase-whole-file:fileset=set:** > EOF diff --git a/tests/test-fix.t b/tests/test-fix.t --- a/tests/test-fix.t +++ b/tests/test-fix.t @@ -10,10 +10,10 @@ choose which behavior to use by naming f > evolution.createmarkers=True > evolution.allowunstable=True > [fix] - > uppercase-whole-file:command=sed -e 's/.*/\U&/' + > uppercase-whole-file:command=sed -e "s/.*/\U&/" > uppercase-whole-file:fileset=set:**.whole > uppercase-changed-lines:command=sed - > uppercase-changed-lines:linerange=-e '{first},{last} s/.*/\U&/' + > uppercase-changed-lines:linerange=-e "{first},{last} s/.*/\U&/" > uppercase-changed-lines:fileset=set:**.changed > EOF @@ -458,8 +458,11 @@ print the filename if it is relevant. $ printf "hello\n" > hello.txt $ hg add adding hello.txt - $ hg --config "fix.fail:command=printf 'HELLO\n' ; \ - > printf '{rootpath}: some\nerror' >&2" \ + $ cat >> $TESTTMP/cmd.sh < printf 'HELLO\n' + > printf "$@: some\nerror" >&2 + > EOF + $ hg --config "fix.fail:command=sh $TESTTMP/cmd.sh {rootpath}" \ >--config "fix.fail:fileset=hello.txt" \ >fix --working-dir [wdir] fail: hello.txt: some @@ -878,7 +881,7 @@ useful for anyone trying to set up a new $ hg commit -Aqm "foo" $ printf "Foo\nbar\nBaz\n" > foo.changed $ hg --debug fix --working-dir - subprocess: sed -e '1,1 s/.*/\U&/' -e '3,3 s/.*/\U&/' + subprocess: sed -e "1,1 s/.*/\U&/" -e "3,3 s/.*/\U&/" $ cd .. ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
[PATCH V2] server: add an error feedback mechanism for when the daemon fails to launch
# HG changeset patch # User Matt Harbison# Date 1522210269 14400 # Wed Mar 28 00:11:09 2018 -0400 # Node ID 74bbfa1b88c69471713bcaa0c8124df4ce93783c # Parent b9dd8403d8ff4b36847ce405c0db127ca64491a1 server: add an error feedback mechanism for when the daemon fails to launch There's a recurring problem on Windows where `hg serve -d` will randomly fail to spawn a detached process. The reason for the failure is completely hidden, and it takes hours to get a single failure on my laptop. All this does is redirect stdout/stderr of the child to a file until the lock file is freed, and then the parent dumps it out if it fails to spawn. I chose to put the output into the lock file because that is always cleaned up. There's no way to report errors after that anyway. On Windows, killdaemons.py is roughly `kill -9`, so this ensures that junk won't pile up. This may end up being a case of EADDRINUSE. At least that's what I saw spit out a few times (among other odd errors and missing output on Windows). But I also managed to get the same thing on Fedora 26 by running test-hgwebdir.t with --loop -j10 for several hours. Running `netstat` immediately after killing that run printed a wall of sockets in the TIME_WAIT state, which were gone a couple seconds later. I couldn't match up ports that failed, because --loop doesn't print out the message about the port that was used. So maybe the fix is to rotate the use of HGPORT[12] in the tests. But, let's collect some more data first. diff --git a/mercurial/server.py b/mercurial/server.py --- a/mercurial/server.py +++ b/mercurial/server.py @@ -30,6 +30,27 @@ def runservice(opts, parentfn=None, init runargs=None, appendpid=False): '''Run a command as a service.''' +# When daemonized on Windows, redirect stdout/stderr to the lockfile (which +# gets cleaned up after the child is up and running), so that the parent can +# read and print the error if this child dies early. See 594dd384803c. On +# other platforms, the child can write to the parent's stdio directly, until +# it is redirected prior to runfn(). +if pycompat.iswindows and opts['daemon_postexec']: +for inst in opts['daemon_postexec']: +if inst.startswith('unlink:'): +lockpath = inst[7:] +if os.path.exists(lockpath): +procutil.stdout.flush() +procutil.stderr.flush() + +fd = os.open(lockpath, + os.O_WRONLY | os.O_APPEND | os.O_BINARY) +try: +os.dup2(fd, 1) +os.dup2(fd, 2) +finally: +os.close(fd) + def writepid(pid): if opts['pid_file']: if appendpid: @@ -61,6 +82,12 @@ def runservice(opts, parentfn=None, init return not os.path.exists(lockpath) pid = procutil.rundetached(runargs, condfn) if pid < 0: +# If the daemonized process managed to write out an error msg, +# report it. +if pycompat.iswindows and os.path.exists(lockpath): +with open(lockpath) as log: +for line in log: +procutil.stderr.write(line) raise error.Abort(_('child process failed to start')) writepid(pid) finally: @@ -81,10 +108,11 @@ def runservice(opts, parentfn=None, init os.setsid() except AttributeError: pass + +lockpath = None for inst in opts['daemon_postexec']: if inst.startswith('unlink:'): lockpath = inst[7:] -os.unlink(lockpath) elif inst.startswith('chdir:'): os.chdir(inst[6:]) elif inst != 'none': @@ -107,6 +135,11 @@ def runservice(opts, parentfn=None, init if logfile and logfilefd not in (0, 1, 2): os.close(logfilefd) +# Only unlink after redirecting stdout/stderr, so Windows doesn't +# complain about a sharing violation. +if lockpath: +os.unlink(lockpath) + if runfn: return runfn() ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
D2904: templatefuncs: add mailmap template function
This revision was automatically updated to reflect the committed changes. Closed by commit rHG2a2ce93e12f4: templatefuncs: add mailmap template function (authored by sheehan, committed by ). CHANGED PRIOR TO COMMIT https://phab.mercurial-scm.org/D2904?vs=7381=7453#toc REPOSITORY rHG Mercurial CHANGES SINCE LAST UPDATE https://phab.mercurial-scm.org/D2904?vs=7381=7453 REVISION DETAIL https://phab.mercurial-scm.org/D2904 AFFECTED FILES mercurial/templatefuncs.py mercurial/utils/stringutil.py tests/test-mailmap.t CHANGE DETAILS diff --git a/tests/test-mailmap.t b/tests/test-mailmap.t new file mode 100644 --- /dev/null +++ b/tests/test-mailmap.t @@ -0,0 +1,67 @@ +Create a repo and add some commits + + $ hg init mm + $ cd mm + $ echo "Test content" > testfile1 + $ hg add testfile1 + $ hg commit -m "First commit" -u "Proper" + $ echo "Test content 2" > testfile2 + $ hg add testfile2 + $ hg commit -m "Second commit" -u "Commit Name 2 " + $ echo "Test content 3" > testfile3 + $ hg add testfile3 + $ hg commit -m "Third commit" -u "Commit Name 3 " + $ echo "Test content 4" > testfile4 + $ hg add testfile4 + $ hg commit -m "Fourth commit" -u "Commit Name 4 " + +Add a .mailmap file with each possible entry type plus comments + $ cat > .mailmap << EOF + > # Comment shouldn't break anything + > # Should update email only + > Proper Name 2 # Should update name only + > Proper Name 3 # Should update name, email due to email + > Proper Name 4 Commit Name 4 # Should update name, email due to name, email + > EOF + $ hg add .mailmap + $ hg commit -m "Add mailmap file" -u "Testuser " + +Output of commits should be normal without filter + $ hg log -T "{author}\n" -r "all()" + Proper + Commit Name 2 + Commit Name 3 + Commit Name 4 + Testuser + +Output of commits with filter shows their mailmap values + $ hg log -T "{mailmap(author)}\n" -r "all()" + Proper + Proper Name 2 + Proper Name 3 + Proper Name 4 + Testuser + +Add new mailmap entry for testuser + $ cat >> .mailmap << EOF + > + > EOF + +Output of commits with filter shows their updated mailmap values + $ hg log -T "{mailmap(author)}\n" -r "all()" + Proper + Proper Name 2 + Proper Name 3 + Proper Name 4 + Testuser + +A commit with improperly formatted user field should not break the filter + $ echo "some more test content" > testfile1 + $ hg commit -m "Commit with improper user field" -u "Improper user" + $ hg log -T "{mailmap(author)}\n" -r "all()" + Proper + Proper Name 2 + Proper Name 3 + Proper Name 4 + Testuser + Improper user diff --git a/mercurial/utils/stringutil.py b/mercurial/utils/stringutil.py --- a/mercurial/utils/stringutil.py +++ b/mercurial/utils/stringutil.py @@ -14,6 +14,7 @@ import textwrap from ..i18n import _ +from ..thirdparty import attr from .. import ( encoding, @@ -158,6 +159,136 @@ f = author.find('@') return author[:f].replace('.', ' ') +@attr.s(hash=True) +class mailmapping(object): +'''Represents a username/email key or value in +a mailmap file''' +email = attr.ib() +name = attr.ib(default=None) + +def parsemailmap(mailmapcontent): +"""Parses data in the .mailmap format + +>>> mmdata = b"\\n".join([ +... b'# Comment', +... b'Name ', +... b' ', +... b'Name ', +... b'Name Commit ', +... ]) +>>> mm = parsemailmap(mmdata) +>>> for key in sorted(mm.keys()): +... print(key) +mailmapping(email='comm...@email.xx', name=None) +mailmapping(email='comm...@email.xx', name=None) +mailmapping(email='comm...@email.xx', name=None) +mailmapping(email='comm...@email.xx', name='Commit') +>>> for val in sorted(mm.values()): +... print(val) +mailmapping(email='comm...@email.xx', name='Name') +mailmapping(email='n...@email.xx', name=None) +mailmapping(email='pro...@email.xx', name='Name') +mailmapping(email='pro...@email.xx', name='Name') +""" +mailmap = {} + +if mailmapcontent is None: +return mailmap + +for line in mailmapcontent.splitlines(): + +# Don't bother checking the line if it is a comment or +# is an improperly formed author field +if line.lstrip().startswith('#') or any(c not in line for c in '<>@'): +continue + +# name, email hold the parsed emails and names for each line +# name_builder holds
D2976: extdiff: document that it copies modified files back to working directory
This revision was automatically updated to reflect the committed changes. Closed by commit rHG2208149c4b8e: extdiff: document that it copies modified files back to working directory (authored by spectral, committed by ). REPOSITORY rHG Mercurial CHANGES SINCE LAST UPDATE https://phab.mercurial-scm.org/D2976?vs=7410=7452 REVISION DETAIL https://phab.mercurial-scm.org/D2976 AFFECTED FILES hgext/extdiff.py tests/test-extension.t CHANGE DETAILS diff --git a/tests/test-extension.t b/tests/test-extension.t --- a/tests/test-extension.t +++ b/tests/test-extension.t @@ -730,6 +730,10 @@ called with a configurable set of options and two non-option arguments: paths to directories containing snapshots of files to compare. + If there is more than one file being compared and the "child" revision is the + working directory, any modifications made in the external diff program will be + copied back to the working directory from the temporary directory. + The extdiff extension also allows you to configure new diff commands, so you do not need to type 'hg extdiff -p kdiff3' always. diff --git a/hgext/extdiff.py b/hgext/extdiff.py --- a/hgext/extdiff.py +++ b/hgext/extdiff.py @@ -13,6 +13,11 @@ non-option arguments: paths to directories containing snapshots of files to compare. +If there is more than one file being compared and the "child" revision +is the working directory, any modifications made in the external diff +program will be copied back to the working directory from the temporary +directory. + The extdiff extension also allows you to configure new diff commands, so you do not need to type :hg:`extdiff -p kdiff3` always. :: To: spectral, #hg-reviewers, yuja Cc: mercurial-devel ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
D2904: templatefuncs: add mailmap template function
yuja added a comment. Queued, thanks. Can you send a followup? INLINE COMMENTS > templatefuncs.py:189 > + > +return stringutil.mapname(cache['mailmap'], author) or author > + Perhaps the last `or author` wouldn't be necessary because that's the default of `mapname()`. > stringutil.py:380 > +# is an improperly formed author field > +if line.lstrip().startswith('#') or any(c not in line for c in > '<>@'): > +continue An example to make it crash: `b'>@<'` (which is nice emoticon btw.) Perhaps we can remove this `any(...)` and add `if not email: continue` instead. REPOSITORY rHG Mercurial REVISION DETAIL https://phab.mercurial-scm.org/D2904 To: sheehan, #hg-reviewers, yuja Cc: yuja, mercurial-devel ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
D2958: infinitepush: introduce server option to route every push to bundlestore
mharbison72 added inline comments. INLINE COMMENTS > test-infinitepush-ci.t:79 > + > + $ hg unbundle > .hg/scratchbranches/filebundlestore/a4/c2/a4c202c147a9c4bb91bbadb56321fc5f3950f7f2 > + adding changesets On Windows, this command fails like so. Any thoughts on the unexpected end of stream? --- c:/Users/Matt/projects/hg/tests/test-infinitepush-ci.t +++ c:/Users/Matt/projects/hg/tests/test-infinitepush-ci.t.err @@ -78,15 +78,12 @@ $ hg unbundle .hg/scratchbranches/filebundlestore/a4/c2/a4c202c147a9c4bb91bbadb56321fc5f3950f7f2 adding changesets - adding manifests - adding file changes - added 1 changesets with 1 changes to 1 files - new changesets 6cb0989601f1 - (run 'hg update' to get a working copy) - - $ hg glog - o 1:6cb0989601f1 added a - | public + transaction abort! + rollback completed + abort: stream ended unexpectedly (got 68 bytes, expected 218759168) + [255] + + $ hg glog @ 0:67145f466344 initialcommit public REPOSITORY rHG Mercurial REVISION DETAIL https://phab.mercurial-scm.org/D2958 To: pulkit, #hg-reviewers, indygreg Cc: mharbison72, indygreg, mercurial-devel ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
D2988: fix: use a portable python script instead of sed in test
hooper 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/D2988 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 @@ -1,3 +1,55 @@ +A script that implements uppercasing of specific lines in a file. This +approximates the behavior of code formatters well enough for our tests. + + $ UPPERCASEPY="$TESTTMP/uppercase.py" + $ cat > $UPPERCASEPY < import sys + > lines = set() + > for arg in sys.argv[1:]: + > if arg == 'all': + > sys.stdout.write(sys.stdin.read().upper()) + > sys.exit(0) + > else: + > first, last = arg.split('-') + > lines.update(range(int(first), int(last) + 1)) + > for i, line in enumerate(sys.stdin.readlines()): + > if i + 1 in lines: + > sys.stdout.write(line.upper()) + > else: + > sys.stdout.write(line) + > EOF + $ TESTLINES="foo\nbar\nbaz\nqux\n" + $ printf $TESTLINES | $PYTHON $UPPERCASEPY + foo + bar + baz + qux + $ printf $TESTLINES | $PYTHON $UPPERCASEPY all + FOO + BAR + BAZ + QUX + $ printf $TESTLINES | $PYTHON $UPPERCASEPY 1-1 + FOO + bar + baz + qux + $ printf $TESTLINES | $PYTHON $UPPERCASEPY 1-2 + FOO + BAR + baz + qux + $ printf $TESTLINES | $PYTHON $UPPERCASEPY 2-3 + foo + BAR + BAZ + qux + $ printf $TESTLINES | $PYTHON $UPPERCASEPY 2-2 4-4 + foo + BAR + baz + QUX + Set up the config with two simple fixers: one that fixes specific line ranges, and one that always fixes the whole file. They both "fix" files by converting letters to uppercase. They use different file extensions, so each test case can @@ -10,10 +62,10 @@ > evolution.createmarkers=True > evolution.allowunstable=True > [fix] - > uppercase-whole-file:command=sed -e 's/.*/\U&/' + > uppercase-whole-file:command=$PYTHON $UPPERCASEPY all > uppercase-whole-file:fileset=set:**.whole - > uppercase-changed-lines:command=sed - > uppercase-changed-lines:linerange=-e '{first},{last} s/.*/\U&/' + > uppercase-changed-lines:command=$PYTHON $UPPERCASEPY + > uppercase-changed-lines:linerange={first}-{last} > uppercase-changed-lines:fileset=set:**.changed > EOF @@ -878,7 +930,7 @@ $ hg commit -Aqm "foo" $ printf "Foo\nbar\nBaz\n" > foo.changed $ hg --debug fix --working-dir - subprocess: sed -e '1,1 s/.*/\U&/' -e '3,3 s/.*/\U&/' + subprocess: /usr/bin/python $TESTTMP/uppercase.py 1-1 3-3 $ cd .. To: hooper, #hg-reviewers Cc: mercurial-devel ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
D2983: wireproto: port protocol handler to zope.interface
indygreg created this revision. Herald added a subscriber: mercurial-devel. Herald added a reviewer: hg-reviewers. REVISION SUMMARY zope.interface is superior to the abc module. Let's port to it. As part of this, we add tests for interface conformance for classes implementing the interface. REPOSITORY rHG Mercurial REVISION DETAIL https://phab.mercurial-scm.org/D2983 AFFECTED FILES mercurial/wireprotoserver.py mercurial/wireprototypes.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 @@ -19,6 +19,8 @@ statichttprepo, ui as uimod, unionrepo, +wireprotoserver, +wireprototypes, ) rootdir = os.path.normpath(os.path.join(os.path.dirname(__file__), '..')) @@ -122,4 +124,23 @@ repo = localrepo.localrepository(ui, rootdir) checkzobject(repo) +ziverify.verifyClass(wireprototypes.baseprotocolhandler, + wireprotoserver.sshv1protocolhandler) +ziverify.verifyClass(wireprototypes.baseprotocolhandler, + wireprotoserver.sshv2protocolhandler) +ziverify.verifyClass(wireprototypes.baseprotocolhandler, + wireprotoserver.httpv1protocolhandler) +ziverify.verifyClass(wireprototypes.baseprotocolhandler, + wireprotoserver.httpv2protocolhandler) + +sshv1 = wireprotoserver.sshv1protocolhandler(None, None, None) +checkzobject(sshv1) +sshv2 = wireprotoserver.sshv2protocolhandler(None, None, None) +checkzobject(sshv2) + +httpv1 = wireprotoserver.httpv1protocolhandler(None, None, None) +checkzobject(httpv1) +httpv2 = wireprotoserver.httpv2protocolhandler(None, None) +checkzobject(httpv2) + main() diff --git a/mercurial/wireprototypes.py b/mercurial/wireprototypes.py --- a/mercurial/wireprototypes.py +++ b/mercurial/wireprototypes.py @@ -5,7 +5,9 @@ from __future__ import absolute_import -import abc +from .thirdparty.zope import ( +interface as zi, +) # Names of the SSH protocol implementations. SSHV1 = 'ssh-v1' @@ -95,39 +97,33 @@ def __init__(self, gen=None): self.gen = gen -class baseprotocolhandler(object): +class baseprotocolhandler(zi.Interface): """Abstract base class for wire protocol handlers. A wire protocol handler serves as an interface between protocol command handlers and the wire protocol transport layer. Protocol handlers provide methods to read command arguments, redirect stdio for the duration of the request, handle response types, etc. """ -__metaclass__ = abc.ABCMeta - -@abc.abstractproperty -def name(self): +name = zi.Attribute( """The name of the protocol implementation. Used for uniquely identifying the transport type. -""" +""") -@abc.abstractmethod -def getargs(self, args): +def getargs(args): """return the value for arguments in returns a list of values (same order as )""" -@abc.abstractmethod -def forwardpayload(self, fp): +def forwardpayload(fp): """Read the raw payload and forward to a file. The payload is read in full before the function returns. """ -@abc.abstractmethod -def mayberedirectstdio(self): +def mayberedirectstdio(): """Context manager to possibly redirect stdio. The context manager yields a file-object like object that receives @@ -140,21 +136,18 @@ won't be captured. """ -@abc.abstractmethod -def client(self): +def client(): """Returns a string representation of this client (as bytes).""" -@abc.abstractmethod -def addcapabilities(self, repo, caps): +def addcapabilities(repo, caps): """Adds advertised capabilities specific to this protocol. Receives the list of capabilities collected so far. Returns a list of capabilities. The passed in argument can be returned. """ -@abc.abstractmethod -def checkperm(self, perm): +def checkperm(perm): """Validate that the client has permissions to perform a request. The argument is the permission required to proceed. If the client diff --git a/mercurial/wireprotoserver.py b/mercurial/wireprotoserver.py --- a/mercurial/wireprotoserver.py +++ b/mercurial/wireprotoserver.py @@ -12,6 +12,9 @@ import threading from .i18n import _ +from .thirdparty.zope import ( +interface as zi, +) from . import ( encoding, error, @@ -58,7 +61,8 @@ return ''.join(chunks) -class httpv1protocolhandler(wireprototypes.baseprotocolhandler): +@zi.implementer(wireprototypes.baseprotocolhandler) +class httpv1protocolhandler(object): def __init__(self, req, ui, checkperm): self._req = req self._ui = ui @@ -574,7 +578,8 @@ }, }
D2987: stringutil: add function to pretty print an object
indygreg created this revision. Herald added a subscriber: mercurial-devel. Herald added a reviewer: hg-reviewers. REVISION SUMMARY This is inspired by the pprint() module/function (which we can't use because the output is different on Python 2 and 3 - namely the use of b'' literals). We hook it up to `hg debugwireproto` for printing the response to a wire protocol command. This foreshadows future peer work, which will support decoding CBOR responses into rich data structures. REPOSITORY rHG Mercurial REVISION DETAIL https://phab.mercurial-scm.org/D2987 AFFECTED FILES mercurial/debugcommands.py mercurial/utils/stringutil.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 @@ -1345,7 +1345,7 @@ o> bookmarks \n o> namespaces\n o> phases - response: bookmarks \nnamespaces\nphases + response: b'bookmarks\nnamespaces\nphases' testing ssh2 creating ssh peer from handshake results @@ -1376,7 +1376,7 @@ o> bookmarks \n o> namespaces\n o> phases - response: bookmarks \nnamespaces\nphases + response: b'bookmarks\nnamespaces\nphases' $ cd .. @@ -1421,7 +1421,7 @@ i> flush() -> None o> bufferedreadline() -> 2: o> 0\n - response: + response: b'' testing ssh2 creating ssh peer from handshake results @@ -1448,7 +1448,7 @@ i> flush() -> None o> bufferedreadline() -> 2: o> 0\n - response: + response: b'' With a single bookmark set @@ -1483,7 +1483,7 @@ o> bufferedreadline() -> 3: o> 46\n o> bufferedread(46) -> 46: bookA 68986213bd4485ea51533535e3fc9e78007a711f - response: bookA 68986213bd4485ea51533535e3fc9e78007a711f + response: b'bookA68986213bd4485ea51533535e3fc9e78007a711f' testing ssh2 creating ssh peer from handshake results @@ -1511,7 +1511,7 @@ o> bufferedreadline() -> 3: o> 46\n o> bufferedread(46) -> 46: bookA 68986213bd4485ea51533535e3fc9e78007a711f - response: bookA 68986213bd4485ea51533535e3fc9e78007a711f + response: b'bookA68986213bd4485ea51533535e3fc9e78007a711f' With multiple bookmarks set @@ -1548,7 +1548,7 @@ o> bufferedread(93) -> 93: o> bookA 68986213bd4485ea51533535e3fc9e78007a711f\n o> bookB 1880f3755e2e52e3199e0ee5638128b08642f34d - response: bookA 68986213bd4485ea51533535e3fc9e78007a711f\nbookB 1880f3755e2e52e3199e0ee5638128b08642f34d + response: b'bookA68986213bd4485ea51533535e3fc9e78007a711f\nbookB 1880f3755e2e52e3199e0ee5638128b08642f34d' testing ssh2 creating ssh peer from handshake results @@ -1578,7 +1578,7 @@ o> bufferedread(93) -> 93: o> bookA 68986213bd4485ea51533535e3fc9e78007a711f\n o> bookB 1880f3755e2e52e3199e0ee5638128b08642f34d - response: bookA 68986213bd4485ea51533535e3fc9e78007a711f\nbookB 1880f3755e2e52e3199e0ee5638128b08642f34d + response: b'bookA68986213bd4485ea51533535e3fc9e78007a711f\nbookB 1880f3755e2e52e3199e0ee5638128b08642f34d' Test pushkey for bookmarks @@ -1624,7 +1624,7 @@ o> 2\n o> bufferedread(2) -> 2: o> 1\n - response: 1\n + response: b'1\n' testing ssh2 creating ssh peer from handshake results @@ -1661,7 +1661,7 @@ o> 2\n o> bufferedread(2) -> 2: o> 1\n - response: 1\n + response: b'1\n' $ hg bookmarks bookA 0:68986213bd44 @@ -1707,7 +1707,7 @@ o> bufferedreadline() -> 3: o> 15\n o> bufferedread(15) -> 15: publishingTrue - response: publishing True + response: b'publishing True' testing ssh2 creating ssh peer from handshake results @@ -1735,7 +1735,7 @@ o> bufferedreadline() -> 3: o> 15\n o> bufferedread(15) -> 15: publishingTrue - response: publishing True + response: b'publishing True' Create some commits @@ -1789,7 +1789,7 @@ o> 20b8a89289d80036e6c4e87c2083e3bea1586637 1\n o> c4750011d906c18ea2f0527419cbc1a544435150 1\n o> publishingTrue - response: 20b8a89289d80036e6c4e87c2083e3bea1586637 1\nc4750011d906c18ea2f0527419cbc1a544435150 1\npublishing True + response: b'20b8a89289d80036e6c4e87c2083e3bea1586637 1\nc4750011d906c18ea2f0527419cbc1a544435150 1\npublishing True' testing ssh2 creating ssh peer from handshake results @@ -1820,7 +1820,7 @@ o> 20b8a89289d80036e6c4e87c2083e3bea1586637 1\n o> c4750011d906c18ea2f0527419cbc1a544435150 1\n o> publishingTrue - response: 20b8a89289d80036e6c4e87c2083e3bea1586637 1\nc4750011d906c18ea2f0527419cbc1a544435150 1\npublishing True + response: b'20b8a89289d80036e6c4e87c2083e3bea1586637 1\nc4750011d906c18ea2f0527419cbc1a544435150 1\npublishing
D2982: wireproto: separate commands tables for version 1 and 2 commands
indygreg created this revision. Herald added a subscriber: mercurial-devel. Herald added a reviewer: hg-reviewers. REVISION SUMMARY We can't easily reuse existing command handlers for version 2 commands because the response types will be different. e.g. many commands return nodes encoded as hex. Our new wire protocol is binary safe, so we'll wish to encode nodes as binary. We /could/ teach each command handler to look at the protocol handler and change behavior based on the version in use. However, this would make logic a bit unwieldy over time and would make it harder to design a unified protocol handler interface. I think it's better to create a clean break between version 1 and version 2 of commands on the server. What I imagine happening is we will have separate @wireprotocommand functions for each protocol generation. Those functions will parse the request, dispatch to a common function to process it, then generate the response in its own, transport-specific manner. This commit establishes a separate table for tracking version 1 commands from version 2 commands. The HTTP server pieces have been updated to use this new table. Most commands are marked as both version 1 and version 2, so there is little practical impact to this change. A side-effect of this change is we now rely on transport registration in wireprototypes.TRANSPORTS and certain properties of the protocol interface. So a test had to be updated to conform. REPOSITORY rHG Mercurial REVISION DETAIL https://phab.mercurial-scm.org/D2982 AFFECTED FILES hgext/largefiles/uisetup.py mercurial/wireproto.py mercurial/wireprotoserver.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 @@ -13,6 +13,8 @@ class proto(object): def __init__(self, args): self.args = args +self.name = 'dummyproto' + def getargs(self, spec): args = self.args args.setdefault(b'*', {}) @@ -22,6 +24,11 @@ def checkperm(self, perm): pass +wireprototypes.TRANSPORTS['dummyproto'] = { +'transport': 'dummy', +'version': 1, +} + class clientpeer(wireproto.wirepeer): def __init__(self, serverrepo, ui): self.serverrepo = serverrepo diff --git a/mercurial/wireprotoserver.py b/mercurial/wireprotoserver.py --- a/mercurial/wireprotoserver.py +++ b/mercurial/wireprotoserver.py @@ -335,7 +335,7 @@ # extension. extracommands = {'multirequest'} -if command not in wireproto.commands and command not in extracommands: +if command not in wireproto.commandsv2 and command not in extracommands: res.status = b'404 Not Found' res.headers[b'Content-Type'] = b'text/plain' res.setbodybytes(_('unknown wire protocol command: %s\n') % command) @@ -346,7 +346,7 @@ proto = httpv2protocolhandler(req, ui) -if (not wireproto.commands.commandavailable(command, proto) +if (not wireproto.commandsv2.commandavailable(command, proto) and command not in extracommands): res.status = b'404 Not Found' res.headers[b'Content-Type'] = b'text/plain' @@ -502,7 +502,7 @@ proto = httpv2protocolhandler(req, ui, args=command['args']) if reqcommand == b'multirequest': -if not wireproto.commands.commandavailable(command['command'], proto): +if not wireproto.commandsv2.commandavailable(command['command'], proto): # TODO proper error mechanism res.status = b'200 OK' res.headers[b'Content-Type'] = b'text/plain' @@ -512,7 +512,7 @@ # TODO don't use assert here, since it may be elided by -O. assert authedperm in (b'ro', b'rw') -wirecommand = wireproto.commands[command['command']] +wirecommand = wireproto.commandsv2[command['command']] assert wirecommand.permission in ('push', 'pull') if authedperm == b'ro' and wirecommand.permission != 'pull': diff --git a/mercurial/wireproto.py b/mercurial/wireproto.py --- a/mercurial/wireproto.py +++ b/mercurial/wireproto.py @@ -502,7 +502,11 @@ def dispatch(repo, proto, command): repo = getdispatchrepo(repo, proto, command) -func, spec = commands[command] + +transportversion = wireprototypes.TRANSPORTS[proto.name]['version'] +commandtable = commandsv2 if transportversion == 2 else commands +func, spec = commandtable[command] + args = proto.getargs(spec) return func(repo, proto, *args) @@ -679,8 +683,12 @@ POLICY_V1_ONLY = 'v1-only' POLICY_V2_ONLY = 'v2-only' +# For version 1 transports. commands = commanddict() +# For version 2 transports. +commandsv2 = commanddict() + def wireprotocommand(name, args='', transportpolicy=POLICY_ALL, permission='push'): """Decorator to declare a wire protocol command. @@ -702,12 +710,15 @@ """ if
D2984: keepalive: implement readinto()
indygreg created this revision. Herald added a subscriber: mercurial-devel. Herald added a reviewer: hg-reviewers. REVISION SUMMARY This is part of the standard I/O interface. It is used by the framing protocol. So we need to implement it so frames can be decoded. REPOSITORY rHG Mercurial REVISION DETAIL https://phab.mercurial-scm.org/D2984 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 @@ -349,7 +349,7 @@ class HTTPResponse(httplib.HTTPResponse): # we need to subclass HTTPResponse in order to -# 1) add readline() and readlines() methods +# 1) add readline(), readlines(), and readinto() methods # 2) add close_connection() methods # 3) add info() and geturl() methods @@ -522,6 +522,14 @@ break return list +def readinto(self, dest): +res = self.read(len(dest)) +if not res: +return 0 + +dest[0:len(res)] = res +return len(res) + def safesend(self, str): """Send `str' to the server. 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
D2981: wireproto: mark SSHv2 as a version 1 transport
indygreg created this revision. Herald added a subscriber: mercurial-devel. Herald added a reviewer: hg-reviewers. REVISION SUMMARY The version component is used for filtering/routing wire protocol commands to their proper handler. The actual version 2 of the wire protocol commands will use a different encoding of responses. We already have tests using the version 2 SSH transport and version 2 of the wire protocol commands won't be implemented atomically. This commit marks the SSHv2 transport as version 1 so it will still invoke the version 1 commands. Once the commands are all implemented in version 2, we can restore its proper behavior. Some tests had to be disabled as a result of this change. REPOSITORY rHG Mercurial REVISION DETAIL https://phab.mercurial-scm.org/D2981 AFFECTED FILES mercurial/wireprototypes.py 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 @@ -1098,9 +1098,9 @@ i> write(6) -> 6: i> hello\n o> readline() -> 4: - o> 385\n - o> readline() -> 385: - o> capabilities: lookup branchmap pushkey known getbundle unbundlehash streamreqs=generaldelta,revlogv1 $USUAL_BUNDLE2_CAPS_SERVER$ unbundle=HG10GZ,HG10BZ,HG10UN batch\n + o> 403\n + o> readline() -> 403: + o> capabilities: lookup branchmap pushkey known getbundle unbundlehash changegroupsubset streamreqs=generaldelta,revlogv1 $USUAL_BUNDLE2_CAPS_SERVER$ unbundle=HG10GZ,HG10BZ,HG10UN batch\n Multiple upgrades is not allowed @@ -1279,30 +1279,32 @@ Legacy commands are not exposed to version 2 of protocol - $ hg --config experimental.sshpeer.advertise-v2=true debugwireproto --localssh << EOF - > command branches - > nodes - > EOF - creating ssh peer from handshake results - sending branches command - response: +TODO re-enable these once we're back to actually using v2 commands + +$ hg --config experimental.sshpeer.advertise-v2=true debugwireproto --localssh << EOF +> command branches +> nodes +> EOF +creating ssh peer from handshake results +sending branches command +response: - $ hg --config experimental.sshpeer.advertise-v2=true debugwireproto --localssh << EOF - > command changegroup - > roots - > EOF - creating ssh peer from handshake results - sending changegroup command - response: +$ hg --config experimental.sshpeer.advertise-v2=true debugwireproto --localssh << EOF +> command changegroup +> roots +> EOF +creating ssh peer from handshake results +sending changegroup command +response: - $ hg --config experimental.sshpeer.advertise-v2=true debugwireproto --localssh << EOF - > command changegroupsubset - > bases - > heads - > EOF - creating ssh peer from handshake results - sending changegroupsubset command - response: +$ hg --config experimental.sshpeer.advertise-v2=true debugwireproto --localssh << EOF +> command changegroupsubset +> bases +> heads +> EOF +creating ssh peer from handshake results +sending changegroupsubset command +response: $ cd .. diff --git a/mercurial/wireprototypes.py b/mercurial/wireprototypes.py --- a/mercurial/wireprototypes.py +++ b/mercurial/wireprototypes.py @@ -22,7 +22,8 @@ }, SSHV2: { 'transport': 'ssh', -'version': 2, +# TODO mark as version 2 once all commands are implemented. +'version': 1, }, 'http-v1': { 'transport': 'http', 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
D2986: wireproto: add frame flag to denote payloads as CBOR
indygreg created this revision. Herald added a subscriber: mercurial-devel. Herald added a reviewer: hg-reviewers. REVISION SUMMARY We may eventually want a separate frame type for this. But for now this is the easiest to implement. REPOSITORY rHG Mercurial REVISION DETAIL https://phab.mercurial-scm.org/D2986 AFFECTED FILES mercurial/help/internals/wireprotocol.txt mercurial/wireprotoframing.py CHANGE DETAILS diff --git a/mercurial/wireprotoframing.py b/mercurial/wireprotoframing.py --- a/mercurial/wireprotoframing.py +++ b/mercurial/wireprotoframing.py @@ -79,10 +79,12 @@ FLAG_BYTES_RESPONSE_CONTINUATION = 0x01 FLAG_BYTES_RESPONSE_EOS = 0x02 +FLAG_BYTES_RESPONSE_CBOR = 0x04 FLAGS_BYTES_RESPONSE = { b'continuation': FLAG_BYTES_RESPONSE_CONTINUATION, b'eos': FLAG_BYTES_RESPONSE_EOS, +b'cbor': FLAG_BYTES_RESPONSE_CBOR, } FLAG_ERROR_RESPONSE_PROTOCOL = 0x01 diff --git a/mercurial/help/internals/wireprotocol.txt b/mercurial/help/internals/wireprotocol.txt --- a/mercurial/help/internals/wireprotocol.txt +++ b/mercurial/help/internals/wireprotocol.txt @@ -631,19 +631,21 @@ server. The command has been fully issued and no new data for this command will be sent. The next frame will belong to a new command. -Bytes Response Data (``0x04``) --- +Response Data (``0x04``) + -This frame contains raw bytes response data to an issued command. +This frame contains raw response data to an issued command. The following flag values are defined for this type: 0x01 - Data continuation. When set, an additional frame containing raw - response data will follow. + Data continuation. When set, an additional frame containing response data + will follow. 0x02 - End of data. When sent, the response data has been fully sent and + End of data. When set, the response data has been fully sent and no additional frames for this response will be sent. +0x04 + CBOR data. When set, the frame payload consists of CBOR data. The ``0x01`` flag is mutually exclusive with the ``0x02`` flag. 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
D2985: wireproto: implement custom __repr__ for frame
indygreg created this revision. Herald added a subscriber: mercurial-devel. Herald added a reviewer: hg-reviewers. REVISION SUMMARY This version won't print the full payload (which could be large). It also prints human friendly values for types and flags. REPOSITORY rHG Mercurial REVISION DETAIL https://phab.mercurial-scm.org/D2985 AFFECTED FILES mercurial/wireprotoframing.py CHANGE DETAILS diff --git a/mercurial/wireprotoframing.py b/mercurial/wireprotoframing.py --- a/mercurial/wireprotoframing.py +++ b/mercurial/wireprotoframing.py @@ -106,6 +106,15 @@ ARGUMENT_RECORD_HEADER = struct.Struct(r'
D2980: zope: force module import by importing symbols
indygreg created this revision. Herald added a subscriber: mercurial-devel. Herald added a reviewer: hg-reviewers. REVISION SUMMARY Previously, we tried to import a module and handle the ImportError. Our lazy module importer doesn't verify the module exists and returns a dummy object representing the module. Only once we attempt to load a symbol in the module does the ImportError get raises. This means that simple imports inside `try..except ImportError` don't detect missing modules. This commit changes imports in zope.interface to access symbols, thus forcing module load and triggering ImportError. This fixes zope.interface for pure builds. REPOSITORY rHG Mercurial REVISION DETAIL https://phab.mercurial-scm.org/D2980 AFFECTED FILES mercurial/thirdparty/zope/interface/declarations.py CHANGE DETAILS diff --git a/mercurial/thirdparty/zope/interface/declarations.py b/mercurial/thirdparty/zope/interface/declarations.py --- a/mercurial/thirdparty/zope/interface/declarations.py +++ b/mercurial/thirdparty/zope/interface/declarations.py @@ -640,12 +640,9 @@ # Try to get C base: try: -from . import _zope_interface_coptimizations +from ._zope_interface_coptimizations import ClassProvidesBase except ImportError: pass -else: -from ._zope_interface_coptimizations import ClassProvidesBase - class ClassProvides(Declaration, ClassProvidesBase): """Special descriptor for class __provides__ @@ -917,15 +914,13 @@ _empty = Declaration() try: -from . import _zope_interface_coptimizations +from ._zope_interface_coptimizations import ( +getObjectSpecification, +implementedBy, +ObjectSpecificationDescriptor, +providedBy, +) except ImportError: pass -else: -from ._zope_interface_coptimizations import implementedBy -from ._zope_interface_coptimizations import providedBy -from ._zope_interface_coptimizations import ( -getObjectSpecification) -from ._zope_interface_coptimizations import ( -ObjectSpecificationDescriptor) objectSpecificationDescriptor = ObjectSpecificationDescriptor() 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
D2977: fix: remove unused imports
This revision was automatically updated to reflect the committed changes. Closed by commit rHGd3f1d3e4e58d: fix: remove unused imports (authored by hooper, committed by ). REPOSITORY rHG Mercurial CHANGES SINCE LAST UPDATE https://phab.mercurial-scm.org/D2977?vs=7431=7441 REVISION DETAIL https://phab.mercurial-scm.org/D2977 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 @@ -53,7 +53,6 @@ import os import re import subprocess -import sys from mercurial.i18n import _ from mercurial.node import nullrev @@ -64,11 +63,9 @@ context, copies, error, -match, mdiff, merge, obsolete, -posix, registrar, scmutil, util, To: hooper, #hg-reviewers, martinvonz Cc: mercurial-devel ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
D2951: wireproto: use CBOR for command requests
indygreg updated this revision to Diff 7439. REPOSITORY rHG Mercurial CHANGES SINCE LAST UPDATE https://phab.mercurial-scm.org/D2951?vs=7328=7439 REVISION DETAIL https://phab.mercurial-scm.org/D2951 AFFECTED FILES mercurial/help/internals/wireprotocol.txt mercurial/wireprotoframing.py mercurial/wireprotoserver.py tests/test-http-api-httpv2.t tests/test-wireproto-serverreactor.py CHANGE DETAILS diff --git a/tests/test-wireproto-serverreactor.py b/tests/test-wireproto-serverreactor.py --- a/tests/test-wireproto-serverreactor.py +++ b/tests/test-wireproto-serverreactor.py @@ -2,6 +2,9 @@ import unittest +from mercurial.thirdparty import ( +cbor, +) from mercurial import ( util, wireprotoframing as framing, @@ -96,7 +99,8 @@ frames = list(framing.createcommandframes(stream, 1, b'command', {}, data)) self.assertEqual(frames, [ -ffs(b'1 1 stream-begin command-name have-data command'), +ffs(b'1 1 stream-begin command-request new|have-data ' +b"cbor:{b'name': b'command'}"), ffs(b'1 1 0 command-data continuation %s' % data.getvalue()), ffs(b'1 1 0 command-data eos ') ]) @@ -108,7 +112,8 @@ frames = list(framing.createcommandframes(stream, 1, b'command', {}, data)) self.assertEqual(frames, [ -ffs(b'1 1 stream-begin command-name have-data command'), +ffs(b'1 1 stream-begin command-request new|have-data ' +b"cbor:{b'name': b'command'}"), ffs(b'1 1 0 command-data continuation %s' % ( b'x' * framing.DEFAULT_MAX_FRAME_SIZE)), ffs(b'1 1 0 command-data eos x'), @@ -125,10 +130,9 @@ }, data)) self.assertEqual(frames, [ -ffs(b'1 1 stream-begin command-name have-args|have-data command'), -ffs(br'1 1 0 command-argument 0 \x04\x00\x09\x00key1key1value'), -ffs(br'1 1 0 command-argument 0 \x04\x00\x09\x00key2key2value'), -ffs(br'1 1 0 command-argument eoa \x04\x00\x09\x00key3key3value'), +ffs(b'1 1 stream-begin command-request new|have-data ' +b"cbor:{b'name': b'command', b'args': {b'key1': b'key1value', " +b"b'key2': b'key2value', b'key3': b'key3value'}}"), ffs(b'1 1 0 command-data eos %s' % data.getvalue()), ]) @@ -286,10 +290,9 @@ stream = framing.stream(1) results = list(sendcommandframes(reactor, stream, 41, b'mycommand', {b'foo': b'bar'})) -self.assertEqual(len(results), 2) -self.assertaction(results[0], 'wantframe') -self.assertaction(results[1], 'runcommand') -self.assertEqual(results[1][1], { +self.assertEqual(len(results), 1) +self.assertaction(results[0], 'runcommand') +self.assertEqual(results[0][1], { 'requestid': 41, 'command': b'mycommand', 'args': {b'foo': b'bar'}, @@ -301,11 +304,9 @@ stream = framing.stream(1) results = list(sendcommandframes(reactor, stream, 1, b'mycommand', {b'foo': b'bar', b'biz': b'baz'})) -self.assertEqual(len(results), 3) -self.assertaction(results[0], 'wantframe') -self.assertaction(results[1], 'wantframe') -self.assertaction(results[2], 'runcommand') -self.assertEqual(results[2][1], { +self.assertEqual(len(results), 1) +self.assertaction(results[0], 'runcommand') +self.assertEqual(results[0][1], { 'requestid': 1, 'command': b'mycommand', 'args': {b'foo': b'bar', b'biz': b'baz'}, @@ -329,7 +330,8 @@ def testmultipledataframes(self): frames = [ -ffs(b'1 1 stream-begin command-name have-data mycommand'), +ffs(b'1 1 stream-begin command-request new|have-data ' +b"cbor:{b'name': b'mycommand'}"), ffs(b'1 1 0 command-data continuation data1'), ffs(b'1 1 0 command-data continuation data2'), ffs(b'1 1 0 command-data eos data3'), @@ -350,9 +352,9 @@ def testargumentanddata(self): frames = [ -ffs(b'1 1 stream-begin command-name have-args|have-data command'), -ffs(br'1 1 0 command-argument 0 \x03\x00\x03\x00keyval'), -ffs(br'1 1 0 command-argument eoa \x03\x00\x03\x00foobar'), +ffs(b'1 1 stream-begin command-request new|have-data ' +b"cbor:{b'name': b'command', b'args': {b'key': b'val'," +b"b'foo': b'bar'}}"), ffs(b'1 1 0 command-data continuation value1'), ffs(b'1 1 0 command-data eos value2'), ] @@ -371,76 +373,68 @@ 'data': b'value1value2', }) -def
D2907: wireproto: add streams to frame-based protocol
indygreg updated this revision to Diff 7435. REPOSITORY rHG Mercurial CHANGES SINCE LAST UPDATE https://phab.mercurial-scm.org/D2907?vs=7325=7435 REVISION DETAIL https://phab.mercurial-scm.org/D2907 AFFECTED FILES mercurial/debugcommands.py mercurial/help/internals/wireprotocol.txt mercurial/wireprotoframing.py mercurial/wireprotoserver.py tests/test-http-api-httpv2.t tests/test-wireproto-serverreactor.py CHANGE DETAILS diff --git a/tests/test-wireproto-serverreactor.py b/tests/test-wireproto-serverreactor.py --- a/tests/test-wireproto-serverreactor.py +++ b/tests/test-wireproto-serverreactor.py @@ -23,6 +23,8 @@ assert len(payload) == header.length yield reactor.onframerecv(framing.frame(header.requestid, +header.streamid, +header.streamflags, header.typeid, header.flags, payload)) @@ -37,44 +39,44 @@ def testdataexactframesize(self): data = util.bytesio(b'x' * framing.DEFAULT_MAX_FRAME_SIZE) -stream = framing.stream() +stream = framing.stream(1) frames = list(framing.createcommandframes(stream, 1, b'command', {}, data)) self.assertEqual(frames, [ -ffs(b'1 command-name have-data command'), -ffs(b'1 command-data continuation %s' % data.getvalue()), -ffs(b'1 command-data eos ') +ffs(b'1 1 stream-begin command-name have-data command'), +ffs(b'1 1 0 command-data continuation %s' % data.getvalue()), +ffs(b'1 1 0 command-data eos ') ]) def testdatamultipleframes(self): data = util.bytesio(b'x' * (framing.DEFAULT_MAX_FRAME_SIZE + 1)) -stream = framing.stream() +stream = framing.stream(1) frames = list(framing.createcommandframes(stream, 1, b'command', {}, data)) self.assertEqual(frames, [ -ffs(b'1 command-name have-data command'), -ffs(b'1 command-data continuation %s' % ( +ffs(b'1 1 stream-begin command-name have-data command'), +ffs(b'1 1 0 command-data continuation %s' % ( b'x' * framing.DEFAULT_MAX_FRAME_SIZE)), -ffs(b'1 command-data eos x'), +ffs(b'1 1 0 command-data eos x'), ]) def testargsanddata(self): data = util.bytesio(b'x' * 100) -stream = framing.stream() +stream = framing.stream(1) frames = list(framing.createcommandframes(stream, 1, b'command', { b'key1': b'key1value', b'key2': b'key2value', b'key3': b'key3value', }, data)) self.assertEqual(frames, [ -ffs(b'1 command-name have-args|have-data command'), -ffs(br'1 command-argument 0 \x04\x00\x09\x00key1key1value'), -ffs(br'1 command-argument 0 \x04\x00\x09\x00key2key2value'), -ffs(br'1 command-argument eoa \x04\x00\x09\x00key3key3value'), -ffs(b'1 command-data eos %s' % data.getvalue()), +ffs(b'1 1 stream-begin command-name have-args|have-data command'), +ffs(br'1 1 0 command-argument 0 \x04\x00\x09\x00key1key1value'), +ffs(br'1 1 0 command-argument 0 \x04\x00\x09\x00key2key2value'), +ffs(br'1 1 0 command-argument eoa \x04\x00\x09\x00key3key3value'), +ffs(b'1 1 0 command-data eos %s' % data.getvalue()), ]) def testtextoutputexcessiveargs(self): @@ -128,64 +130,68 @@ (b'bleh', [], [b'x' * 65536])])) def testtextoutput1simpleatom(self): -stream = framing.stream() +stream = framing.stream(1) val = list(framing.createtextoutputframe(stream, 1, [ (b'foo', [], [])])) self.assertEqual(val, [ -ffs(br'1 text-output 0 \x03\x00\x00\x00foo'), +ffs(br'1 1 stream-begin text-output 0 \x03\x00\x00\x00foo'), ]) def testtextoutput2simpleatoms(self): -stream = framing.stream() +stream = framing.stream(1) val = list(framing.createtextoutputframe(stream, 1, [ (b'foo', [], []), (b'bar', [], []), ])) self.assertEqual(val, [ -ffs(br'1 text-output 0 \x03\x00\x00\x00foo\x03\x00\x00\x00bar'), +ffs(br'1 1 stream-begin text-output 0 ' +br'\x03\x00\x00\x00foo\x03\x00\x00\x00bar'), ]) def testtextoutput1arg(self): -stream = framing.stream() +stream = framing.stream(1) val = list(framing.createtextoutputframe(stream, 1, [ (b'foo %s', [b'val1'], []), ])) self.assertEqual(val, [ -
D2948: wireproto: syntax for encoding CBOR into frames
indygreg updated this revision to Diff 7437. REPOSITORY rHG Mercurial CHANGES SINCE LAST UPDATE https://phab.mercurial-scm.org/D2948?vs=7352=7437 REVISION DETAIL https://phab.mercurial-scm.org/D2948 AFFECTED FILES mercurial/debugcommands.py mercurial/utils/stringutil.py mercurial/wireprotoframing.py tests/test-wireproto-serverreactor.py CHANGE DETAILS diff --git a/tests/test-wireproto-serverreactor.py b/tests/test-wireproto-serverreactor.py --- a/tests/test-wireproto-serverreactor.py +++ b/tests/test-wireproto-serverreactor.py @@ -35,6 +35,59 @@ framing.createcommandframes(stream, rid, cmd, args, datafh)) +class FrameHumanStringTests(unittest.TestCase): +def testbasic(self): +self.assertEqual(ffs(b'1 1 0 1 0 '), + b'\x00\x00\x00\x01\x00\x01\x00\x10') + +self.assertEqual(ffs(b'2 4 0 1 0 '), + b'\x00\x00\x00\x02\x00\x04\x00\x10') + +self.assertEqual(ffs(b'2 4 0 1 0 foo'), + b'\x03\x00\x00\x02\x00\x04\x00\x10foo') + +def testcborint(self): +self.assertEqual(ffs(b'1 1 0 1 0 cbor:15'), + b'\x01\x00\x00\x01\x00\x01\x00\x10\x0f') + +self.assertEqual(ffs(b'1 1 0 1 0 cbor:42'), + b'\x02\x00\x00\x01\x00\x01\x00\x10\x18*') + +self.assertEqual(ffs(b'1 1 0 1 0 cbor:1048576'), + b'\x05\x00\x00\x01\x00\x01\x00\x10\x1a' + b'\x00\x10\x00\x00') + +self.assertEqual(ffs(b'1 1 0 1 0 cbor:0'), + b'\x01\x00\x00\x01\x00\x01\x00\x10\x00') + +self.assertEqual(ffs(b'1 1 0 1 0 cbor:-1'), + b'\x01\x00\x00\x01\x00\x01\x00\x10 ') + +self.assertEqual(ffs(b'1 1 0 1 0 cbor:-342542'), + b'\x05\x00\x00\x01\x00\x01\x00\x10:\x00\x05:\r') + +def testcborstrings(self): +# String literals should be unicode. +self.assertEqual(ffs(b"1 1 0 1 0 cbor:'foo'"), + b'\x04\x00\x00\x01\x00\x01\x00\x10cfoo') + +self.assertEqual(ffs(b"1 1 0 1 0 cbor:b'foo'"), + b'\x04\x00\x00\x01\x00\x01\x00\x10Cfoo') + +self.assertEqual(ffs(b"1 1 0 1 0 cbor:u'foo'"), + b'\x04\x00\x00\x01\x00\x01\x00\x10cfoo') + +def testcborlists(self): +self.assertEqual(ffs(b"1 1 0 1 0 cbor:[None, True, False, 42, b'foo']"), + b'\n\x00\x00\x01\x00\x01\x00\x10\x85\xf6\xf5\xf4' + b'\x18*Cfoo') + +def testcbordicts(self): +self.assertEqual(ffs(b"1 1 0 1 0 " + b"cbor:{b'foo': b'val1', b'bar': b'val2'}"), + b'\x13\x00\x00\x01\x00\x01\x00\x10\xa2' + b'CbarDval2CfooDval1') + class FrameTests(unittest.TestCase): def testdataexactframesize(self): data = util.bytesio(b'x' * framing.DEFAULT_MAX_FRAME_SIZE) diff --git a/mercurial/wireprotoframing.py b/mercurial/wireprotoframing.py --- a/mercurial/wireprotoframing.py +++ b/mercurial/wireprotoframing.py @@ -16,6 +16,7 @@ from .i18n import _ from .thirdparty import ( attr, +cbor, ) from . import ( error, @@ -156,6 +157,9 @@ def makeframefromhumanstring(s): """Create a frame from a human readable string +DANGER: NOT SAFE TO USE WITH UNTRUSTED INPUT BECAUSE OF POTENTIAL +eval() USAGE. DO NOT USE IN CORE. + Strings have the form: @@ -169,6 +173,11 @@ named constant. Flags can be delimited by `|` to bitwise OR them together. + +If the payload begins with ``cbor:``, the following string will be +evaluated as Python code and the resulting object will be fed into +a CBOR encoder. Otherwise, the payload is interpreted as a Python +byte string literal. """ fields = s.split(b' ', 5) requestid, streamid, streamflags, frametype, frameflags, payload = fields @@ -196,7 +205,11 @@ else: finalflags |= int(flag) -payload = stringutil.unescapestr(payload) +if payload.startswith(b'cbor:'): +payload = cbor.dumps(stringutil.evalpython(payload[5:]), canonical=True) + +else: +payload = stringutil.unescapestr(payload) return makeframe(requestid=requestid, streamid=streamid, streamflags=finalstreamflags, typeid=frametype, diff --git a/mercurial/utils/stringutil.py b/mercurial/utils/stringutil.py --- a/mercurial/utils/stringutil.py +++ b/mercurial/utils/stringutil.py @@ -9,6 +9,7 @@ from __future__ import absolute_import +import __future__ import codecs import re as remod import textwrap @@ -336,3 +337,29 @@ If s is not a valid boolean, returns None. """ return _booleans.get(s.lower(), None) + +def evalpython(s): +"""Evaluate a string containing a Python expression. + +THIS FUNCTION IS NOT SAFE
D2979: wireproto: stop aliasing wire protocol types (API)
indygreg created this revision. Herald added a subscriber: mercurial-devel. Herald added a reviewer: hg-reviewers. REVISION SUMMARY We generally shy away from aliasing module symbols. I think I was keeping this around for API compatibility. We've already made tons of other API breaks in the wire protocol code this release. What's one more? .. api:: ``wireproto`` module no longer re-exports various types used to define responses to wire protocol commands. Access these types from the ``wireprototypes`` module. REPOSITORY rHG Mercurial REVISION DETAIL https://phab.mercurial-scm.org/D2979 AFFECTED FILES hgext/largefiles/proto.py mercurial/wireproto.py CHANGE DETAILS diff --git a/mercurial/wireproto.py b/mercurial/wireproto.py --- a/mercurial/wireproto.py +++ b/mercurial/wireproto.py @@ -42,13 +42,6 @@ urlerr = util.urlerr urlreq = util.urlreq -bytesresponse = wireprototypes.bytesresponse -ooberror = wireprototypes.ooberror -pushres = wireprototypes.pushres -pusherr = wireprototypes.pusherr -streamres = wireprototypes.streamres -streamres_legacy = wireprototypes.streamreslegacy - bundle2requiredmain = _('incompatible Mercurial client; bundle2 required') bundle2requiredhint = _('see https://www.mercurial-scm.org/wiki/' 'IncompatibleClient') @@ -771,17 +764,17 @@ result = func(repo, proto, *[data[k] for k in keys]) else: result = func(repo, proto) -if isinstance(result, ooberror): +if isinstance(result, wireprototypes.ooberror): return result # For now, all batchable commands must return bytesresponse or # raw bytes (for backwards compatibility). -assert isinstance(result, (bytesresponse, bytes)) -if isinstance(result, bytesresponse): +assert isinstance(result, (wireprototypes.bytesresponse, bytes)) +if isinstance(result, wireprototypes.bytesresponse): result = result.data res.append(escapearg(result)) -return bytesresponse(';'.join(res)) +return wireprototypes.bytesresponse(';'.join(res)) @wireprotocommand('between', 'pairs', transportpolicy=POLICY_V1_ONLY, permission='pull') @@ -791,7 +784,7 @@ for b in repo.between(pairs): r.append(encodelist(b) + "\n") -return bytesresponse(''.join(r)) +return wireprototypes.bytesresponse(''.join(r)) @wireprotocommand('branchmap', permission='pull') def branchmap(repo, proto): @@ -802,7 +795,7 @@ branchnodes = encodelist(nodes) heads.append('%s %s' % (branchname, branchnodes)) -return bytesresponse('\n'.join(heads)) +return wireprototypes.bytesresponse('\n'.join(heads)) @wireprotocommand('branches', 'nodes', transportpolicy=POLICY_V1_ONLY, permission='pull') @@ -812,7 +805,7 @@ for b in repo.branches(nodes): r.append(encodelist(b) + "\n") -return bytesresponse(''.join(r)) +return wireprototypes.bytesresponse(''.join(r)) @wireprotocommand('clonebundles', '', permission='pull') def clonebundles(repo, proto): @@ -824,7 +817,8 @@ depending on the request. e.g. you could advertise URLs for the closest data center given the client's IP address. """ -return bytesresponse(repo.vfs.tryread('clonebundles.manifest')) +return wireprototypes.bytesresponse( +repo.vfs.tryread('clonebundles.manifest')) wireprotocaps = ['lookup', 'branchmap', 'pushkey', 'known', 'getbundle', 'unbundlehash'] @@ -868,7 +862,7 @@ # `_capabilities` instead. @wireprotocommand('capabilities', permission='pull') def capabilities(repo, proto): -return bytesresponse(' '.join(_capabilities(repo, proto))) +return wireprototypes.bytesresponse(' '.join(_capabilities(repo, proto))) @wireprotocommand('changegroup', 'roots', transportpolicy=POLICY_V1_ONLY, permission='pull') @@ -878,7 +872,7 @@ missingheads=repo.heads()) cg = changegroupmod.makechangegroup(repo, outgoing, '01', 'serve') gen = iter(lambda: cg.read(32768), '') -return streamres(gen=gen) +return wireprototypes.streamres(gen=gen) @wireprotocommand('changegroupsubset', 'bases heads', transportpolicy=POLICY_V1_ONLY, @@ -890,15 +884,15 @@ missingheads=heads) cg = changegroupmod.makechangegroup(repo, outgoing, '01', 'serve') gen = iter(lambda: cg.read(32768), '') -return streamres(gen=gen) +return wireprototypes.streamres(gen=gen) @wireprotocommand('debugwireargs', 'one two *', permission='pull') def debugwireargs(repo, proto, one, two, others): # only accept optional args from the known set opts = options('debugwireargs', ['three', 'four'], others) -return bytesresponse(repo.debugwireargs(one, two, -**pycompat.strkwargs(opts))) +
D2906: wireproto: start to associate frame generation with a stream
indygreg updated this revision to Diff 7434. REPOSITORY rHG Mercurial CHANGES SINCE LAST UPDATE https://phab.mercurial-scm.org/D2906?vs=7324=7434 REVISION DETAIL https://phab.mercurial-scm.org/D2906 AFFECTED FILES mercurial/wireprotoframing.py mercurial/wireprotoserver.py tests/test-wireproto-serverreactor.py CHANGE DETAILS diff --git a/tests/test-wireproto-serverreactor.py b/tests/test-wireproto-serverreactor.py --- a/tests/test-wireproto-serverreactor.py +++ b/tests/test-wireproto-serverreactor.py @@ -27,25 +27,31 @@ header.flags, payload)) -def sendcommandframes(reactor, rid, cmd, args, datafh=None): +def sendcommandframes(reactor, stream, rid, cmd, args, datafh=None): """Generate frames to run a command and send them to a reactor.""" return sendframes(reactor, - framing.createcommandframes(rid, cmd, args, datafh)) + framing.createcommandframes(stream, rid, cmd, args, + datafh)) class FrameTests(unittest.TestCase): def testdataexactframesize(self): data = util.bytesio(b'x' * framing.DEFAULT_MAX_FRAME_SIZE) -frames = list(framing.createcommandframes(1, b'command', {}, data)) +stream = framing.stream() +frames = list(framing.createcommandframes(stream, 1, b'command', + {}, data)) self.assertEqual(frames, [ ffs(b'1 command-name have-data command'), ffs(b'1 command-data continuation %s' % data.getvalue()), ffs(b'1 command-data eos ') ]) def testdatamultipleframes(self): data = util.bytesio(b'x' * (framing.DEFAULT_MAX_FRAME_SIZE + 1)) -frames = list(framing.createcommandframes(1, b'command', {}, data)) + +stream = framing.stream() +frames = list(framing.createcommandframes(stream, 1, b'command', {}, + data)) self.assertEqual(frames, [ ffs(b'1 command-name have-data command'), ffs(b'1 command-data continuation %s' % ( @@ -56,7 +62,8 @@ def testargsanddata(self): data = util.bytesio(b'x' * 100) -frames = list(framing.createcommandframes(1, b'command', { +stream = framing.stream() +frames = list(framing.createcommandframes(stream, 1, b'command', { b'key1': b'key1value', b'key2': b'key2value', b'key3': b'key3value', @@ -75,59 +82,63 @@ with self.assertRaisesRegexp(ValueError, 'cannot use more than 255 formatting'): args = [b'x' for i in range(256)] -list(framing.createtextoutputframe(1, [(b'bleh', args, [])])) +list(framing.createtextoutputframe(None, 1, + [(b'bleh', args, [])])) def testtextoutputexcessivelabels(self): """At most 255 labels are allowed.""" with self.assertRaisesRegexp(ValueError, 'cannot use more than 255 labels'): labels = [b'l' for i in range(256)] -list(framing.createtextoutputframe(1, [(b'bleh', [], labels)])) +list(framing.createtextoutputframe(None, 1, + [(b'bleh', [], labels)])) def testtextoutputformattingstringtype(self): """Formatting string must be bytes.""" with self.assertRaisesRegexp(ValueError, 'must use bytes formatting '): -list(framing.createtextoutputframe(1, [ +list(framing.createtextoutputframe(None, 1, [ (b'foo'.decode('ascii'), [], [])])) def testtextoutputargumentbytes(self): with self.assertRaisesRegexp(ValueError, 'must use bytes for argument'): -list(framing.createtextoutputframe(1, [ +list(framing.createtextoutputframe(None, 1, [ (b'foo', [b'foo'.decode('ascii')], [])])) def testtextoutputlabelbytes(self): with self.assertRaisesRegexp(ValueError, 'must use bytes for labels'): -list(framing.createtextoutputframe(1, [ +list(framing.createtextoutputframe(None, 1, [ (b'foo', [], [b'foo'.decode('ascii')])])) def testtextoutputtoolongformatstring(self): with self.assertRaisesRegexp(ValueError, 'formatting string cannot be longer than'): -list(framing.createtextoutputframe(1, [ +list(framing.createtextoutputframe(None, 1, [ (b'x' * 65536, [], [])])) def testtextoutputtoolongargumentstring(self): with self.assertRaisesRegexp(ValueError, 'argument string cannot be longer than'): -
D2902: wireproto: define frame to represent progress updates
indygreg updated this revision to Diff 7438. REPOSITORY rHG Mercurial CHANGES SINCE LAST UPDATE https://phab.mercurial-scm.org/D2902?vs=7311=7438 REVISION DETAIL https://phab.mercurial-scm.org/D2902 AFFECTED FILES mercurial/help/internals/wireprotocol.txt mercurial/wireprotoframing.py CHANGE DETAILS diff --git a/mercurial/wireprotoframing.py b/mercurial/wireprotoframing.py --- a/mercurial/wireprotoframing.py +++ b/mercurial/wireprotoframing.py @@ -45,6 +45,7 @@ FRAME_TYPE_BYTES_RESPONSE = 0x04 FRAME_TYPE_ERROR_RESPONSE = 0x05 FRAME_TYPE_TEXT_OUTPUT = 0x06 +FRAME_TYPE_PROGRESS = 0x07 FRAME_TYPE_STREAM_SETTINGS = 0x08 FRAME_TYPES = { @@ -54,6 +55,7 @@ b'bytes-response': FRAME_TYPE_BYTES_RESPONSE, b'error-response': FRAME_TYPE_ERROR_RESPONSE, b'text-output': FRAME_TYPE_TEXT_OUTPUT, +b'progress': FRAME_TYPE_PROGRESS, b'stream-settings': FRAME_TYPE_STREAM_SETTINGS, } @@ -107,6 +109,7 @@ FRAME_TYPE_BYTES_RESPONSE: FLAGS_BYTES_RESPONSE, FRAME_TYPE_ERROR_RESPONSE: FLAGS_ERROR_RESPONSE, FRAME_TYPE_TEXT_OUTPUT: {}, +FRAME_TYPE_PROGRESS: {}, FRAME_TYPE_STREAM_SETTINGS: {}, } diff --git a/mercurial/help/internals/wireprotocol.txt b/mercurial/help/internals/wireprotocol.txt --- a/mercurial/help/internals/wireprotocol.txt +++ b/mercurial/help/internals/wireprotocol.txt @@ -740,6 +740,44 @@ The last atom in the frame SHOULD end with a newline (``\n``). If it doesn't, clients MAY add a newline to facilitate immediate printing. +Progress Update (``0x07``) +-- + +This frame holds the progress of an operation on the peer. Consumption +of these frames allows clients to display progress bars, estimated +completion times, etc. + +Each frame defines the progress of a single operation on the peer. The +payload consists of a CBOR map with the following bytestring keys: + +topic + Topic name (string) +pos + Current numeric position within the topic (integer) +total + Total/end numeric position of this topic (unsigned integer) +label (optional) + Unit label (string) +item (optional) + Item name (string) + +Progress state is created when a frame is received referencing a +*topic* that isn't currently tracked. Progress tracking for that +*topic* is finished when a frame is received reporting the current +position of that topic as ``-1``. + +Multiple *topics* may be active at any given time. + +Rendering of progress information is not mandated or governed by this +specification: implementations MAY render progress information however +they see fit, including not at all. + +The string data describing the topic SHOULD be static strings to +facilitate receivers localizing that string data. The emitter +MUST normalize all string data to valid UTF-8 and receivers SHOULD +validate that received data conforms to UTF-8. The topic name +SHOULD be ASCII. + Stream Encoding Settings (``0x08``) --- 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
D2947: wireproto: explicit API to create outgoing streams
indygreg updated this revision to Diff 7436. REPOSITORY rHG Mercurial CHANGES SINCE LAST UPDATE https://phab.mercurial-scm.org/D2947?vs=7326=7436 REVISION DETAIL https://phab.mercurial-scm.org/D2947 AFFECTED FILES mercurial/wireprotoframing.py mercurial/wireprotoserver.py tests/test-http-api-httpv2.t tests/test-wireproto-serverreactor.py CHANGE DETAILS diff --git a/tests/test-wireproto-serverreactor.py b/tests/test-wireproto-serverreactor.py --- a/tests/test-wireproto-serverreactor.py +++ b/tests/test-wireproto-serverreactor.py @@ -375,7 +375,7 @@ """Multiple fully serviced commands with same request ID is allowed.""" reactor = makereactor() results = [] -outstream = framing.stream(2) +outstream = reactor.makeoutputstream() results.append(self._sendsingleframe( reactor, ffs(b'1 1 stream-begin command-name eos command'))) result = reactor.onbytesresponseready(outstream, 1, b'response1') @@ -530,7 +530,7 @@ instream = framing.stream(1) list(sendcommandframes(reactor, instream, 1, b'mycommand', {})) -outstream = framing.stream(2) +outstream = reactor.makeoutputstream() result = reactor.onbytesresponseready(outstream, 1, b'response') self.assertaction(result, 'sendframes') self.assertframesequal(result[1]['framegen'], [ @@ -546,7 +546,7 @@ instream = framing.stream(1) list(sendcommandframes(reactor, instream, 1, b'mycommand', {})) -outstream = framing.stream(2) +outstream = reactor.makeoutputstream() result = reactor.onbytesresponseready(outstream, 1, first + second) self.assertaction(result, 'sendframes') self.assertframesequal(result[1]['framegen'], [ @@ -559,7 +559,7 @@ instream = framing.stream(1) list(sendcommandframes(reactor, instream, 1, b'mycommand', {})) -outstream = framing.stream(2) +outstream = reactor.makeoutputstream() result = reactor.onapplicationerror(outstream, 1, b'some message') self.assertaction(result, 'sendframes') self.assertframesequal(result[1]['framegen'], [ @@ -575,7 +575,7 @@ self.assertEqual(len(results), 1) self.assertaction(results[0], 'runcommand') -outstream = framing.stream(2) +outstream = reactor.makeoutputstream() result = reactor.onbytesresponseready(outstream, 1, b'response') self.assertaction(result, 'noop') result = reactor.oninputeof() @@ -590,7 +590,7 @@ list(sendcommandframes(reactor, instream, 1, b'command1', {})) list(sendcommandframes(reactor, instream, 3, b'command2', {})) -outstream = framing.stream(2) +outstream = reactor.makeoutputstream() result = reactor.onbytesresponseready(outstream, 1, b'response1') self.assertaction(result, 'noop') result = reactor.onbytesresponseready(outstream, 3, b'response2') @@ -610,7 +610,7 @@ list(sendcommandframes(reactor, instream, 5, b'command3', {})) # Register results for commands out of order. -outstream = framing.stream(2) +outstream = reactor.makeoutputstream() reactor.onbytesresponseready(outstream, 3, b'response3') reactor.onbytesresponseready(outstream, 1, b'response1') reactor.onbytesresponseready(outstream, 5, b'response5') @@ -640,7 +640,7 @@ reactor = makereactor() instream = framing.stream(1) list(sendcommandframes(reactor, instream, 1, b'command1', {})) -outstream = framing.stream(2) +outstream = reactor.makeoutputstream() reactor.onbytesresponseready(outstream, 1, b'response') # We've registered the response but haven't sent it. From the @@ -672,7 +672,7 @@ reactor = makereactor() instream = framing.stream(1) list(sendcommandframes(reactor, instream, 1, b'command1', {})) -outstream = framing.stream(2) +outstream = reactor.makeoutputstream() res = reactor.onbytesresponseready(outstream, 1, b'response') list(res[1]['framegen']) diff --git a/tests/test-http-api-httpv2.t b/tests/test-http-api-httpv2.t --- a/tests/test-http-api-httpv2.t +++ b/tests/test-http-api-httpv2.t @@ -472,7 +472,7 @@ s> \x1d\x00\x00\x01\x00\x02\x01Bcustomreadonly bytes response s> \r\n s> 25\r\n - s> \x1d\x00\x00\x03\x00\x02\x01Bcustomreadonly bytes response + s> \x1d\x00\x00\x03\x00\x02\x00Bcustomreadonly bytes response s> \r\n s> 0\r\n s> \r\n @@ -511,7 +511,7 @@ s> \x00\x00\x00\x03\x00\x02\x01B s> \r\n s> 26\r\n - s> \x1e\x00\x00\x01\x00\x02\x01Bbookmarks\n + s> \x1e\x00\x00\x01\x00\x02\x00Bbookmarks\n s> namespaces\n s> phases s> \r\n diff --git a/mercurial/wireprotoserver.py b/mercurial/wireprotoserver.py ---
D2950: tests: fix duplicate and failing test
indygreg updated this revision to Diff 7433. REPOSITORY rHG Mercurial CHANGES SINCE LAST UPDATE https://phab.mercurial-scm.org/D2950?vs=7323=7433 REVISION DETAIL https://phab.mercurial-scm.org/D2950 AFFECTED FILES tests/test-wireproto-serverreactor.py CHANGE DETAILS diff --git a/tests/test-wireproto-serverreactor.py b/tests/test-wireproto-serverreactor.py --- a/tests/test-wireproto-serverreactor.py +++ b/tests/test-wireproto-serverreactor.py @@ -174,8 +174,8 @@ ]) class ServerReactorTests(unittest.TestCase): -def _sendsingleframe(self, reactor, s): -results = list(sendframes(reactor, [ffs(s)])) +def _sendsingleframe(self, reactor, f): +results = list(sendframes(reactor, [f])) self.assertEqual(len(results), 1) return results[0] @@ -296,7 +296,7 @@ def testunexpectedcommandargument(self): """Command argument frame when not running a command is an error.""" result = self._sendsingleframe(makereactor(), - b'1 command-argument 0 ignored') + ffs(b'1 command-argument 0 ignored')) self.assertaction(result, 'error') self.assertEqual(result[1], { 'message': b'expected command frame; got 2', @@ -318,7 +318,7 @@ def testunexpectedcommanddata(self): """Command argument frame when not running a command is an error.""" result = self._sendsingleframe(makereactor(), - b'1 command-data 0 ignored') + ffs(b'1 command-data 0 ignored')) self.assertaction(result, 'error') self.assertEqual(result[1], { 'message': b'expected command frame; got 3', @@ -340,19 +340,32 @@ def testmissingcommandframeflags(self): """Command name frame must have flags set.""" result = self._sendsingleframe(makereactor(), - b'1 command-name 0 command') + ffs(b'1 command-name 0 command')) self.assertaction(result, 'error') self.assertEqual(result[1], { 'message': b'missing frame flags on command frame', }) -def testconflictingrequestid(self): +def testconflictingrequestidallowed(self): """Multiple fully serviced commands with same request ID is allowed.""" -results = list(sendframes(makereactor(), [ -ffs(b'1 command-name eos command'), -ffs(b'1 command-name eos command'), -ffs(b'1 command-name eos command'), -])) +reactor = makereactor() +results = [] +results.append(self._sendsingleframe( +reactor, ffs(b'1 command-name eos command'))) +result = reactor.onbytesresponseready(1, b'response1') +self.assertaction(result, 'sendframes') +list(result[1]['framegen']) +results.append(self._sendsingleframe( +reactor, ffs(b'1 command-name eos command'))) +result = reactor.onbytesresponseready(1, b'response2') +self.assertaction(result, 'sendframes') +list(result[1]['framegen']) +results.append(self._sendsingleframe( +reactor, ffs(b'1 command-name eos command'))) +result = reactor.onbytesresponseready(1, b'response3') +self.assertaction(result, 'sendframes') +list(result[1]['framegen']) + for i in range(3): self.assertaction(results[i], 'runcommand') self.assertEqual(results[i][1], { 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
D2978: cbor: import CBORDecoder and CBOREncoder
indygreg created this revision. Herald added a subscriber: mercurial-devel. Herald added a reviewer: hg-reviewers. REVISION SUMMARY And format the imports so it is cleaner. REPOSITORY rHG Mercurial REVISION DETAIL https://phab.mercurial-scm.org/D2978 AFFECTED FILES mercurial/thirdparty/cbor/__init__.py CHANGE DETAILS diff --git a/mercurial/thirdparty/cbor/__init__.py b/mercurial/thirdparty/cbor/__init__.py --- a/mercurial/thirdparty/cbor/__init__.py +++ b/mercurial/thirdparty/cbor/__init__.py @@ -1 +1,10 @@ -from .cbor2 import load, loads, dump, dumps, CBORDecodeError, CBOREncodeError +from .cbor2 import ( +CBORDecodeError, +CBORDecoder, +CBOREncodeError, +CBOREncoder, +dump, +dumps, +load, +loads, +) 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
D2977: fix: remove unused imports
hooper 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/D2977 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 @@ -53,7 +53,6 @@ import os import re import subprocess -import sys from mercurial.i18n import _ from mercurial.node import nullrev @@ -64,11 +63,9 @@ context, copies, error, -match, mdiff, merge, obsolete, -posix, registrar, scmutil, util, To: hooper, #hg-reviewers Cc: mercurial-devel ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
D2952: infinitepush: delete infinitepush.fillmetadatabranchpattern config option
This revision was automatically updated to reflect the committed changes. Closed by commit rHG8b5d7ef81066: infinitepush: delete infinitepush.fillmetadatabranchpattern config option (authored by pulkit, committed by ). REPOSITORY rHG Mercurial CHANGES SINCE LAST UPDATE https://phab.mercurial-scm.org/D2952?vs=7335=7424 REVISION DETAIL https://phab.mercurial-scm.org/D2952 AFFECTED FILES hgext/infinitepush/__init__.py tests/test-infinitepush.t CHANGE DETAILS diff --git a/tests/test-infinitepush.t b/tests/test-infinitepush.t --- a/tests/test-infinitepush.t +++ b/tests/test-infinitepush.t @@ -288,31 +288,3 @@ $ hg debugfillinfinitepushmetadata --node 09904fb20c53ff351bd3b1d47681f569a4dab7e5 --config infinitepush.metadatafilelimit=2 $ cat .hg/scratchbranches/index/nodemetadatamap/09904fb20c53ff351bd3b1d47681f569a4dab7e5 {"changed_files": {"file": {"adds": 1, "isbinary": false, "removes": 0, "status": "added"}, "file1": {"adds": 1, "isbinary": false, "removes": 0, "status": "added"}}, "changed_files_truncated": true} (no-eol) - -Test infinitepush.fillmetadatabranchpattern - $ cd ../repo - $ cat >> .hg/hgrc << EOF - > [infinitepush] - > fillmetadatabranchpattern=re:scratch/fillmetadata/.* - > EOF - $ cd ../client - $ echo tofillmetadata > tofillmetadata - $ hg ci -Aqm "tofillmetadata" - $ hg log -r . -T '{node}\n' - d2b0410d4da084bc534b1d90df0de9eb21583496 - $ hg push -r . -B scratch/fillmetadata/fill - pushing to ssh://user@dummy/repo - searching for changes - remote: pushing 6 commits: - remote: 33910bfe6ffe testpullbycommithash1 - remote: d8fde0ddfc96 testpullbycommithash2 - remote: 3edfe7e9089a add and rm files - remote: c7ac39f638c6 cpfile and mvfile - remote: 09904fb20c53 add many files - remote: d2b0410d4da0 tofillmetadata - -Make sure background process finished - $ sleep 3 - $ cd ../repo - $ cat .hg/scratchbranches/index/nodemetadatamap/d2b0410d4da084bc534b1d90df0de9eb21583496 - {"changed_files": {"tofillmetadata": {"adds": 1, "isbinary": false, "removes": 0, "status": "added"}}} (no-eol) diff --git a/hgext/infinitepush/__init__.py b/hgext/infinitepush/__init__.py --- a/hgext/infinitepush/__init__.py +++ b/hgext/infinitepush/__init__.py @@ -68,12 +68,6 @@ # patterns to list if no patterns are specified. defaultremotepatterns = ['*'] -# Server-side option. If bookmark that was pushed matches -# `fillmetadatabranchpattern` then background -# `hg debugfillinfinitepushmetadata` process will save metadata -# in infinitepush index for nodes that are ancestor of the bookmark. -fillmetadatabranchpattern = '' - # Instructs infinitepush to forward all received bundle2 parts to the # bundle for storage. Defaults to False. storeallparts = True @@ -154,9 +148,6 @@ configitem('infinitepush', 'indexpath', default='', ) -configitem('infinitepush', 'fillmetadatabranchpattern', -default='', -) configitem('infinitepush', 'storeallparts', default=False, ) @@ -1082,13 +1073,6 @@ log(scratchbranchparttype, eventtype='success', elapsedms=(time.time() - parthandlerstart) * 1000) -fillmetadatabranchpattern = op.repo.ui.config( -'infinitepush', 'fillmetadatabranchpattern', '') -if bookmark and fillmetadatabranchpattern: -__, __, matcher = util.stringmatcher(fillmetadatabranchpattern) -if matcher(bookmark): -_asyncsavemetadata(op.repo.root, - [ctx.hex() for ctx in nodesctx]) except Exception as e: log(scratchbranchparttype, eventtype='failure', elapsedms=(time.time() - parthandlerstart) * 1000, 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
D2106: infinitepush: drop logic related to treemanifest extension
This revision was automatically updated to reflect the committed changes. Closed by commit rHG7fa00a6f8180: infinitepush: drop logic related to treemanifest extension (authored by pulkit, committed by ). REPOSITORY rHG Mercurial CHANGES SINCE LAST UPDATE https://phab.mercurial-scm.org/D2106?vs=5367=7421 REVISION DETAIL https://phab.mercurial-scm.org/D2106 AFFECTED FILES hgext/infinitepush/__init__.py hgext/infinitepush/bundleparts.py CHANGE DETAILS diff --git a/hgext/infinitepush/bundleparts.py b/hgext/infinitepush/bundleparts.py --- a/hgext/infinitepush/bundleparts.py +++ b/hgext/infinitepush/bundleparts.py @@ -68,19 +68,6 @@ advisoryparams=params.iteritems(), data=cg)) -try: -treemod = extensions.find('treemanifest') -mfnodes = [] -for node in outgoing.missing: -mfnodes.append(('', repo[node].manifestnode())) - -# Only include the tree parts if they all exist -if not repo.manifestlog.datastore.getmissing(mfnodes): -parts.append(treemod.createtreepackpart( -repo, outgoing, treemod.TREEGROUP_PARTTYPE2)) -except KeyError: -pass - return parts def _validaterevset(repo, revset, bookmark): diff --git a/hgext/infinitepush/__init__.py b/hgext/infinitepush/__init__.py --- a/hgext/infinitepush/__init__.py +++ b/hgext/infinitepush/__init__.py @@ -440,16 +440,6 @@ cgpart.addparam('version', version) parts.append(cgpart) -try: -treemod = extensions.find('treemanifest') -except KeyError: -pass -else: -if treemod._cansendtrees(bundlerepo, outgoing.missing): -treepart = treemod.createtreepackpart(bundlerepo, outgoing, - treemod.TREEGROUP_PARTTYPE2) -parts.append(treepart) - return parts def _getbundleroots(oldrepo, bundlerepo, bundlerevs): @@ -858,7 +848,6 @@ return pushop.stepsdone.add('changesets') -pushop.stepsdone.add('treepack') if not pushop.outgoing.missing: pushop.ui.status(_('no changes found\n')) pushop.cgresult = 0 @@ -953,13 +942,6 @@ handleallparts = repo.ui.configbool('infinitepush', 'storeallparts') -partforwardingwhitelist = [] -try: -treemfmod = extensions.find('treemanifest') -partforwardingwhitelist.append(treemfmod.TREEGROUP_PARTTYPE2) -except KeyError: -pass - bundler = bundle2.bundle20(repo.ui) cgparams = None with bundle2.partiterator(repo, op, unbundler) as parts: @@ -987,7 +969,7 @@ op.records.add(scratchbranchparttype + '_skipphaseheads', True) else: -if handleallparts or part.type in partforwardingwhitelist: +if handleallparts: # Ideally we would not process any parts, and instead just # forward them to the bundle for storage, but since this # differs from previous behavior, we need to put it behind a 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
D2957: infinitepush: don't wrap bundle2.processparts while calling `hg unbundle`
This revision was automatically updated to reflect the committed changes. Closed by commit rHGe5cd0ef5c362: infinitepush: dont wrap bundle2.processparts while calling `hg unbundle` (authored by pulkit, committed by ). REPOSITORY rHG Mercurial CHANGES SINCE LAST UPDATE https://phab.mercurial-scm.org/D2957?vs=7340=7429 REVISION DETAIL https://phab.mercurial-scm.org/D2957 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 @@ -869,6 +869,13 @@ return logger def processparts(orig, repo, op, unbundler): + +# make sure we don't wrap processparts in case of `hg unbundle` +tr = repo.currenttransaction() +if tr: +if tr.names[0].startswith('unbundle'): +return orig(repo, op, unbundler) + if unbundler.params.get('infinitepush') != 'True': return orig(repo, op, unbundler) 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
D2958: infinitepush: introduce server option to route every push to bundlestore
This revision was automatically updated to reflect the committed changes. Closed by commit rHG571f25dae740: infinitepush: introduce server option to route every push to bundlestore (authored by pulkit, committed by ). REPOSITORY rHG Mercurial CHANGES SINCE LAST UPDATE https://phab.mercurial-scm.org/D2958?vs=7341=7430 REVISION DETAIL https://phab.mercurial-scm.org/D2958 AFFECTED FILES hgext/infinitepush/__init__.py tests/test-infinitepush-ci.t CHANGE DETAILS diff --git a/tests/test-infinitepush-ci.t b/tests/test-infinitepush-ci.t new file mode 100644 --- /dev/null +++ b/tests/test-infinitepush-ci.t @@ -0,0 +1,344 @@ +Testing the case when there is no infinitepush extension present on the client +side and the server routes each push to bundlestore. This case is very much +similar to CI use case. + +Setup +- + + $ . "$TESTDIR/library-infinitepush.sh" + $ cat >> $HGRCPATH < [alias] + > glog = log -GT "{rev}:{node|short} {desc}\n{phase}" + > EOF + $ cp $HGRCPATH $TESTTMP/defaulthgrc + $ hg init repo + $ cd repo + $ setupserver + $ echo "pushtobundlestore = True" >> .hg/hgrc + $ echo "[extensions]" >> .hg/hgrc + $ echo "infinitepush=" >> .hg/hgrc + $ echo initialcommit > initialcommit + $ hg ci -Aqm "initialcommit" + $ hg phase --public . + + $ cd .. + $ hg clone repo client -q + $ cd client + +Pushing a new commit from the client to the server +- + + $ echo foobar > a + $ hg ci -Aqm "added a" + $ hg glog + @ 1:6cb0989601f1 added a + | draft + o 0:67145f466344 initialcommit + public + + $ hg push + pushing to $TESTTMP/repo + searching for changes + storing changesets on the bundlestore + pushing 1 commit: + 6cb0989601f1 added a + + $ scratchnodes + 6cb0989601f1fb5805238edfb16f3606713d9a0b a4c202c147a9c4bb91bbadb56321fc5f3950f7f2 + +Understanding how data is stored on the bundlestore in server +- + +There are two things, filebundlestore and index + $ ls ../repo/.hg/scratchbranches + filebundlestore + index + +filebundlestore stores the bundles + $ ls ../repo/.hg/scratchbranches/filebundlestore/a4/c2/ + a4c202c147a9c4bb91bbadb56321fc5f3950f7f2 + +index/nodemap stores a map of node id and file in which bundle is stored in filebundlestore + $ ls ../repo/.hg/scratchbranches/index/ + nodemap + $ ls ../repo/.hg/scratchbranches/index/nodemap/ + 6cb0989601f1fb5805238edfb16f3606713d9a0b + + $ cd ../repo + +Checking that the commit was not applied to revlog on the server +-- + + $ hg glog + @ 0:67145f466344 initialcommit + public + +Applying the changeset from the bundlestore + + + $ hg unbundle .hg/scratchbranches/filebundlestore/a4/c2/a4c202c147a9c4bb91bbadb56321fc5f3950f7f2 + adding changesets + adding manifests + adding file changes + added 1 changesets with 1 changes to 1 files + new changesets 6cb0989601f1 + (run 'hg update' to get a working copy) + + $ hg glog + o 1:6cb0989601f1 added a + | public + @ 0:67145f466344 initialcommit + public + +Pushing more changesets from the local repo + + + $ cd ../client + $ echo b > b + $ hg ci -Aqm "added b" + $ echo c > c + $ hg ci -Aqm "added c" + $ hg glog + @ 3:bf8a6e3011b3 added c + | draft + o 2:eaba929e866c added b + | draft + o 1:6cb0989601f1 added a + | public + o 0:67145f466344 initialcommit + public + + $ hg push + pushing to $TESTTMP/repo + searching for changes + storing changesets on the bundlestore + pushing 2 commits: + eaba929e866c added b + bf8a6e3011b3 added c + +Checking that changesets are not applied on the server +-- + + $ hg glog -R ../repo + o 1:6cb0989601f1 added a + | public + @ 0:67145f466344 initialcommit + public + +Both of the new changesets are stored in a single bundle-file + $ scratchnodes + 6cb0989601f1fb5805238edfb16f3606713d9a0b a4c202c147a9c4bb91bbadb56321fc5f3950f7f2 + bf8a6e3011b345146bbbedbcb1ebd4837571492a ee41a41cefb7817cbfb235b4f6e9f27dbad6ca1f + eaba929e866c59bc9a6aada5a9dd2f6990db83c0 ee41a41cefb7817cbfb235b4f6e9f27dbad6ca1f + +Pushing more changesets to the server +- + + $ echo d > d + $ hg ci -Aqm "added d" + $ echo e > e + $ hg ci -Aqm "added e" + +XXX: we should have pushed only the parts which are not in bundlestore + $ hg push + pushing to $TESTTMP/repo + searching for changes + storing changesets on the bundlestore + pushing 4 commits: + eaba929e866c added b + bf8a6e3011b3 added c + 1bb96358eda2 added d + b4e4bce66051 added e + +Sneak peek into the bundlestore at the server + $ scratchnodes + 1bb96358eda285b536c6d1c66846a7cdb2336cea 57e00c0d4f26e2a2a72b751b63d9abc4f3eb28e7 +
D2954: infinitepush: drop the wrapping of update command on client side
This revision was automatically updated to reflect the committed changes. Closed by commit rHG95cc57a74363: infinitepush: drop the wrapping of update command on client side (authored by pulkit, committed by ). REPOSITORY rHG Mercurial CHANGES SINCE LAST UPDATE https://phab.mercurial-scm.org/D2954?vs=7337=7426 REVISION DETAIL https://phab.mercurial-scm.org/D2954 AFFECTED FILES hgext/infinitepush/__init__.py tests/test-infinitepush.t CHANGE DETAILS diff --git a/tests/test-infinitepush.t b/tests/test-infinitepush.t --- a/tests/test-infinitepush.t +++ b/tests/test-infinitepush.t @@ -165,49 +165,3 @@ (run 'hg heads .' to see heads, 'hg merge' to merge) $ hg log -r scratch/scratchontopofpublic -T '{phase}' draft (no-eol) -Strip scratchontopofpublic commit and do hg update - $ hg log -r tip -T '{node}\n' - c70aee6da07d7cdb9897375473690df3a8563339 - $ echo "[extensions]" >> .hg/hgrc - $ echo "strip=" >> .hg/hgrc - $ hg strip -q tip - $ hg up c70aee6da07d7cdb9897375473690df3a8563339 - 'c70aee6da07d7cdb9897375473690df3a8563339' does not exist locally - looking for it remotely... - pulling from ssh://user@dummy/repo - searching for changes - adding changesets - adding manifests - adding file changes - added 1 changesets with 1 changes to 1 files - new changesets c70aee6da07d - (run 'hg update' to get a working copy) - 'c70aee6da07d7cdb9897375473690df3a8563339' found remotely - 2 files updated, 0 files merged, 2 files removed, 0 files unresolved - -Trying to pull from bad path - $ hg strip -q tip - $ hg --config paths.default=badpath up c70aee6da07d7cdb9897375473690df3a8563339 - 'c70aee6da07d7cdb9897375473690df3a8563339' does not exist locally - looking for it remotely... - pulling from $TESTTMP/client2/badpath (glob) - pull failed: repository $TESTTMP/client2/badpath not found - abort: unknown revision 'c70aee6da07d7cdb9897375473690df3a8563339'! - [255] - -Strip commit and pull it using hg update with bookmark name - $ hg strip -q d8fde0ddfc96 - $ hg book -d scratch/mybranch - $ hg up scratch/mybranch - 'scratch/mybranch' does not exist locally - looking for it remotely... - pulling from ssh://user@dummy/repo - searching for changes - adding changesets - adding manifests - adding file changes - added 1 changesets with 1 changes to 2 files - new changesets d8fde0ddfc96 - (run 'hg update' to get a working copy) - 'scratch/mybranch' found remotely - 2 files updated, 0 files merged, 1 files removed, 0 files unresolved - (activating bookmark scratch/mybranch) - $ hg log -r scratch/mybranch -T '{node}' - d8fde0ddfc962183977f92d2bc52d303b8840f9d (no-eol) diff --git a/hgext/infinitepush/__init__.py b/hgext/infinitepush/__init__.py --- a/hgext/infinitepush/__init__.py +++ b/hgext/infinitepush/__init__.py @@ -91,7 +91,6 @@ import re import socket import subprocess -import sys import tempfile import time @@ -312,7 +311,6 @@ _('force push to go to bundle store (EXPERIMENTAL)'))) extensions.wrapcommand(commands.table, 'pull', _pull) -extensions.wrapcommand(commands.table, 'update', _update) extensions.wrapfunction(discovery, 'checkheads', _checkheads) @@ -577,39 +575,6 @@ return "%s %s\n" % (0, r) return _lookup -def _update(orig, ui, repo, node=None, rev=None, **opts): -if rev and node: -raise error.Abort(_("please specify just one revision")) - -if not opts.get('date') and (rev or node) not in repo: -mayberemote = rev or node -mayberemote = _tryhoist(ui, mayberemote) -dopull = False -kwargs = {} -if _scratchbranchmatcher(mayberemote): -dopull = True -kwargs['bookmark'] = [mayberemote] -elif len(mayberemote) == 40 and _maybehash(mayberemote): -dopull = True -kwargs['rev'] = [mayberemote] - -if dopull: -ui.warn( -_("'%s' does not exist locally - looking for it " + - "remotely...\n") % mayberemote) -# Try pulling node from remote repo -try: -cmdname = '^pull' -pullcmd = commands.table[cmdname][0] -pullopts = dict(opt[1:3] for opt in commands.table[cmdname][1]) -pullopts.update(kwargs) -pullcmd(ui, repo, **pullopts) -except Exception: -ui.warn(_('pull failed: %s\n') % sys.exc_info()[1]) -else: -ui.warn(_("'%s' found remotely\n") % mayberemote) -return orig(ui, repo, node, rev, **opts) - def _pull(orig, ui, repo, source="default", **opts): # Copy paste from `pull` command source, branches = hg.parseurl(ui.expandpath(source), opts.get('branch')) To: pulkit, #hg-reviewers, indygreg Cc: mercurial-devel ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org
D2956: inifnitepush: use utils.{stringutil|procutil}.* instead of util.*
This revision was automatically updated to reflect the committed changes. Closed by commit rHG0d6c12668691: inifnitepush: use utils.{stringutil|procutil}.* instead of util.* (authored by pulkit, committed by ). REPOSITORY rHG Mercurial CHANGES SINCE LAST UPDATE https://phab.mercurial-scm.org/D2956?vs=7339=7427 REVISION DETAIL https://phab.mercurial-scm.org/D2956 AFFECTED FILES hgext/infinitepush/__init__.py hgext/infinitepush/fileindexapi.py CHANGE DETAILS diff --git a/hgext/infinitepush/fileindexapi.py b/hgext/infinitepush/fileindexapi.py --- a/hgext/infinitepush/fileindexapi.py +++ b/hgext/infinitepush/fileindexapi.py @@ -15,7 +15,7 @@ import os -from mercurial import util +from mercurial.utils import stringutil from . import indexapi @@ -77,7 +77,7 @@ def _listbookmarks(self, pattern): if pattern.endswith('*'): pattern = 're:^' + pattern[:-1] + '.*' -kind, pat, matcher = util.stringmatcher(pattern) +kind, pat, matcher = stringutil.stringmatcher(pattern) prefixlen = len(self._bookmarkmap) + 1 for dirpath, _, books in self._repo.vfs.walk(self._bookmarkmap): for book in books: diff --git a/hgext/infinitepush/__init__.py b/hgext/infinitepush/__init__.py --- a/hgext/infinitepush/__init__.py +++ b/hgext/infinitepush/__init__.py @@ -101,6 +101,11 @@ from mercurial.i18n import _ +from mercurial.utils import ( +procutil, +stringutil, +) + from mercurial import ( bundle2, changegroup, @@ -270,7 +275,8 @@ scratchbranchpat = ui.config('infinitepush', 'branchpattern') if scratchbranchpat: global _scratchbranchmatcher -kind, pat, _scratchbranchmatcher = util.stringmatcher(scratchbranchpat) +kind, pat, _scratchbranchmatcher = \ +stringutil.stringmatcher(scratchbranchpat) def serverextsetup(ui): origpushkeyhandler = bundle2.parthandlermapping['pushkey'] @@ -331,7 +337,7 @@ results.update(index.getbookmarks(pattern)) if pattern.endswith('*'): pattern = 're:^' + pattern[:-1] + '.*' -kind, pat, matcher = util.stringmatcher(pattern) +kind, pat, matcher = stringutil.stringmatcher(pattern) for bookmark, node in bookmarks.iteritems(): if matcher(bookmark): results[bookmark] = node @@ -843,7 +849,7 @@ if not logger: ui = op.repo.ui try: -username = util.getuser() +username = procutil.getuser() except Exception: username = 'unknown' # Generate random request id to be able to find all logged entries 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
D2108: infinitepush: drop the `--to` flag to push and use `-B` instead
This revision was automatically updated to reflect the committed changes. Closed by commit rHGc5687ce3b411: infinitepush: drop the `--to` flag to push and use `-B` instead (authored by pulkit, committed by ). CHANGED PRIOR TO COMMIT https://phab.mercurial-scm.org/D2108?vs=7334=7422#toc REPOSITORY rHG Mercurial CHANGES SINCE LAST UPDATE https://phab.mercurial-scm.org/D2108?vs=7334=7422 REVISION DETAIL https://phab.mercurial-scm.org/D2108 AFFECTED FILES hgext/infinitepush/__init__.py tests/test-infinitepush-bundlestore.t tests/test-infinitepush.t CHANGE DETAILS diff --git a/tests/test-infinitepush.t b/tests/test-infinitepush.t --- a/tests/test-infinitepush.t +++ b/tests/test-infinitepush.t @@ -49,7 +49,7 @@ $ hg ci -Am "scratchfirstpart" adding scratchfirstpart created new head - $ hg push -r . --to scratch/firstpart + $ hg push -r . -B scratch/firstpart pushing to ssh://user@dummy/repo searching for changes remote: pushing 1 commit: @@ -60,7 +60,7 @@ $ hg ci -Am "scratchsecondpart" adding scratchsecondpart created new head - $ hg push -r . --to scratch/secondpart + $ hg push -r . -B scratch/secondpart pushing to ssh://user@dummy/repo searching for changes remote: pushing 1 commit: @@ -96,7 +96,7 @@ $ hg log -r '.' -T '{node}\n' > ../testpullbycommithash1 $ echo testpullbycommithash2 > testpullbycommithash2 $ hg ci -Aqm "testpullbycommithash2" - $ hg push -r . --to scratch/mybranch -q + $ hg push -r . -B scratch/mybranch -q Create third client and pull by commit hash. Make sure testpullbycommithash2 has not fetched @@ -144,7 +144,7 @@ 1 files updated, 0 files merged, 0 files removed, 0 files unresolved $ echo scratchontopofpublic > scratchontopofpublic $ hg ci -Aqm "scratchontopofpublic" - $ hg push -r . --to scratch/scratchontopofpublic + $ hg push -r . -B scratch/scratchontopofpublic pushing to ssh://user@dummy/repo searching for changes remote: pushing 1 commit: @@ -300,7 +300,7 @@ $ hg ci -Aqm "tofillmetadata" $ hg log -r . -T '{node}\n' d2b0410d4da084bc534b1d90df0de9eb21583496 - $ hg push -r . --to scratch/fillmetadata/fill + $ hg push -r . -B scratch/fillmetadata/fill pushing to ssh://user@dummy/repo searching for changes remote: pushing 6 commits: diff --git a/tests/test-infinitepush-bundlestore.t b/tests/test-infinitepush-bundlestore.t --- a/tests/test-infinitepush-bundlestore.t +++ b/tests/test-infinitepush-bundlestore.t @@ -26,7 +26,7 @@ remote: adding file changes remote: added 1 changesets with 1 changes to 1 files $ mkcommit scratchcommit - $ hg push -r . --to scratch/mybranch + $ hg push -r . -B scratch/mybranch pushing to ssh://user@dummy/repo searching for changes remote: pushing 1 commit: @@ -119,7 +119,7 @@ $ cd ../client2 $ hg up -q scratch/mybranch $ mkcommit 'new scratch commit' - $ hg push -r . --to scratch/mybranch + $ hg push -r . -B scratch/mybranch pushing to ssh://user@dummy/repo searching for changes remote: pushing 2 commits: @@ -140,7 +140,7 @@ scratch/mybranch 1de1d7d92f8965260391d0513fe8a8d5973d3042 Push scratch bookmark with no new revs - $ hg push -r . --to scratch/anotherbranch + $ hg push -r . -B scratch/anotherbranch pushing to ssh://user@dummy/repo searching for changes remote: pushing 2 commits: @@ -216,7 +216,7 @@ Test with pushrebase $ mkcommit scratchcommitwithpushrebase - $ hg push -r . --to scratch/mybranch + $ hg push -r . -B scratch/mybranch pushing to ssh://user@dummy/repo searching for changes remote: pushing 4 commits: @@ -237,7 +237,7 @@ Change the order of pushrebase and infinitepush $ mkcommit scratchcommitwithpushrebase2 - $ hg push -r . --to scratch/mybranch + $ hg push -r . -B scratch/mybranch pushing to ssh://user@dummy/repo searching for changes remote: pushing 5 commits: @@ -300,15 +300,15 @@ $ scratchbookmarks scratch/anotherbranch 1de1d7d92f8965260391d0513fe8a8d5973d3042 scratch/mybranch 6c10d49fe92751666c40263f96721b918170d3da - $ hg push -r . --to scratch/mybranch + $ hg push -r . -B scratch/mybranch pushing to ssh://user@dummy/repo searching for changes remote: non-forward push remote: (use --non-forward-move to override) abort: push failed on remote [255] - $ hg push -r . --to scratch/mybranch --non-forward-move + $ hg push -r . -B scratch/mybranch --non-forward-move pushing to ssh://user@dummy/repo searching for changes remote: pushing 5 commits: diff --git a/hgext/infinitepush/__init__.py b/hgext/infinitepush/__init__.py --- a/hgext/infinitepush/__init__.py +++ b/hgext/infinitepush/__init__.py @@ -315,9 +315,6 @@ def clientextsetup(ui): entry = extensions.wrapcommand(commands.table, 'push', _push) -# Don't add the 'to' arg if it already exists -if not any(a for a in entry[1] if a[1] == 'to'): -entry[1].append(('', 'to', '', _('push revs to this bookmark'))) if not
D2953: infinitepush: delete infinitepushcommands.py and related tests
This revision was automatically updated to reflect the committed changes. Closed by commit rHGaa015dd92591: infinitepush: delete infinitepushcommands.py and related tests (authored by pulkit, committed by ). CHANGED PRIOR TO COMMIT https://phab.mercurial-scm.org/D2953?vs=7336=7425#toc REPOSITORY rHG Mercurial CHANGES SINCE LAST UPDATE https://phab.mercurial-scm.org/D2953?vs=7336=7425 REVISION DETAIL https://phab.mercurial-scm.org/D2953 AFFECTED FILES hgext/infinitepush/__init__.py hgext/infinitepush/infinitepushcommands.py tests/test-infinitepush.t CHANGE DETAILS diff --git a/tests/test-infinitepush.t b/tests/test-infinitepush.t --- a/tests/test-infinitepush.t +++ b/tests/test-infinitepush.t @@ -211,80 +211,3 @@ (activating bookmark scratch/mybranch) $ hg log -r scratch/mybranch -T '{node}' d8fde0ddfc962183977f92d2bc52d303b8840f9d (no-eol) - -Test debugfillinfinitepushmetadata - $ cd ../repo - $ hg debugfillinfinitepushmetadata - abort: nodes are not specified - [255] - $ hg debugfillinfinitepushmetadata --node randomnode - abort: node randomnode is not found - [255] - $ hg debugfillinfinitepushmetadata --node d8fde0ddfc962183977f92d2bc52d303b8840f9d - $ cat .hg/scratchbranches/index/nodemetadatamap/d8fde0ddfc962183977f92d2bc52d303b8840f9d - {"changed_files": {"testpullbycommithash2": {"adds": 1, "isbinary": false, "removes": 0, "status": "added"}}} (no-eol) - - $ cd ../client - $ hg up d8fde0ddfc962183977f92d2bc52d303b8840f9d - 'd8fde0ddfc962183977f92d2bc52d303b8840f9d' does not exist locally - looking for it remotely... - pulling from ssh://user@dummy/repo - searching for changes - adding changesets - adding manifests - adding file changes - added 2 changesets with 2 changes to 2 files (+1 heads) - new changesets 33910bfe6ffe:d8fde0ddfc96 - (run 'hg heads .' to see heads, 'hg merge' to merge) - 'd8fde0ddfc962183977f92d2bc52d303b8840f9d' found remotely - 2 files updated, 0 files merged, 1 files removed, 0 files unresolved - $ echo file > file - $ hg add file - $ hg rm testpullbycommithash2 - $ hg ci -m 'add and rm files' - $ hg log -r . -T '{node}\n' - 3edfe7e9089ab9f728eb8e0d0c62a5d18cf19239 - $ hg cp file cpfile - $ hg mv file mvfile - $ hg ci -m 'cpfile and mvfile' - $ hg log -r . -T '{node}\n' - c7ac39f638c6b39bcdacf868fa21b6195670f8ae - $ hg push -r . --bundle-store - pushing to ssh://user@dummy/repo - searching for changes - remote: pushing 4 commits: - remote: 33910bfe6ffe testpullbycommithash1 - remote: d8fde0ddfc96 testpullbycommithash2 - remote: 3edfe7e9089a add and rm files - remote: c7ac39f638c6 cpfile and mvfile - $ cd ../repo - $ hg debugfillinfinitepushmetadata --node 3edfe7e9089ab9f728eb8e0d0c62a5d18cf19239 --node c7ac39f638c6b39bcdacf868fa21b6195670f8ae - $ cat .hg/scratchbranches/index/nodemetadatamap/3edfe7e9089ab9f728eb8e0d0c62a5d18cf19239 - {"changed_files": {"file": {"adds": 1, "isbinary": false, "removes": 0, "status": "added"}, "testpullbycommithash2": {"adds": 0, "isbinary": false, "removes": 1, "status": "removed"}}} (no-eol) - $ cat .hg/scratchbranches/index/nodemetadatamap/c7ac39f638c6b39bcdacf868fa21b6195670f8ae - {"changed_files": {"cpfile": {"adds": 1, "copies": "file", "isbinary": false, "removes": 0, "status": "added"}, "file": {"adds": 0, "isbinary": false, "removes": 1, "status": "removed"}, "mvfile": {"adds": 1, "copies": "file", "isbinary": false, "removes": 0, "status": "added"}}} (no-eol) - -Test infinitepush.metadatafilelimit number - $ cd ../client - $ echo file > file - $ hg add file - $ echo file1 > file1 - $ hg add file1 - $ echo file2 > file2 - $ hg add file2 - $ hg ci -m 'add many files' - $ hg log -r . -T '{node}' - 09904fb20c53ff351bd3b1d47681f569a4dab7e5 (no-eol) - $ hg push -r . --bundle-store - pushing to ssh://user@dummy/repo - searching for changes - remote: pushing 5 commits: - remote: 33910bfe6ffe testpullbycommithash1 - remote: d8fde0ddfc96 testpullbycommithash2 - remote: 3edfe7e9089a add and rm files - remote: c7ac39f638c6 cpfile and mvfile - remote: 09904fb20c53 add many files - - $ cd ../repo - $ hg debugfillinfinitepushmetadata --node 09904fb20c53ff351bd3b1d47681f569a4dab7e5 --config infinitepush.metadatafilelimit=2 - $ cat .hg/scratchbranches/index/nodemetadatamap/09904fb20c53ff351bd3b1d47681f569a4dab7e5 - {"changed_files": {"file": {"adds": 1, "isbinary": false, "removes": 0, "status": "added"}, "file1": {"adds": 1, "isbinary": false, "removes": 0, "status": "added"}}, "changed_files_truncated": true} (no-eol) diff --git a/hgext/infinitepush/infinitepushcommands.py b/hgext/infinitepush/infinitepushcommands.py deleted file mode 100644 --- a/hgext/infinitepush/infinitepushcommands.py +++ /dev/null @@ -1,101 +0,0 @@ -# Copyright 2016 Facebook, Inc. -# -# This software may be used and distributed according to the terms of the -# GNU General Public License version 2 or any later
D2103: infinitepush: drop `--list-remote`, `--remote-path` flags to bookmark cmd
This revision was automatically updated to reflect the committed changes. Closed by commit rHG320b1f95f676: infinitepush: drop `--list-remote`, `--remote-path` flags to bookmark cmd (authored by pulkit, committed by ). REPOSITORY rHG Mercurial CHANGES SINCE LAST UPDATE https://phab.mercurial-scm.org/D2103?vs=5364=7418 REVISION DETAIL https://phab.mercurial-scm.org/D2103 AFFECTED FILES hgext/infinitepush/__init__.py tests/test-infinitepush-bundlestore.t CHANGE DETAILS diff --git a/tests/test-infinitepush-bundlestore.t b/tests/test-infinitepush-bundlestore.t --- a/tests/test-infinitepush-bundlestore.t +++ b/tests/test-infinitepush-bundlestore.t @@ -369,47 +369,6 @@ |/ o initialcommit public - $ hg book --list-remote scratch/* - scratch/anotherbranch 1de1d7d92f8965260391d0513fe8a8d5973d3042 - scratch/mybranch 8872775dd97a750e1533dc1fbbca665644b32547 - $ hg book --list-remote - abort: --list-remote requires a bookmark pattern - (use "hg book" to get a list of your local bookmarks) - [255] - $ hg book --config infinitepush.defaultremotepatterns=scratch/another* --list-remote - abort: --list-remote requires a bookmark pattern - (use "hg book" to get a list of your local bookmarks) - [255] - $ hg book --list-remote scratch/my - $ hg book --list-remote scratch/my* - scratch/mybranch 8872775dd97a750e1533dc1fbbca665644b32547 - $ hg book --list-remote scratch/my* -T json - [ - { -"bookmark": "scratch/mybranch", -"node": "8872775dd97a750e1533dc1fbbca665644b32547" - } - ] - $ cd ../repo - $ hg book scratch/serversidebook - $ hg book serversidebook - $ cd ../client - $ hg book --list-remote scratch/* -T json - [ - { -"bookmark": "scratch/anotherbranch", -"node": "1de1d7d92f8965260391d0513fe8a8d5973d3042" - }, - { -"bookmark": "scratch/mybranch", -"node": "8872775dd97a750e1533dc1fbbca665644b32547" - }, - { -"bookmark": "scratch/serversidebook", -"node": "" - } - ] - Push to svn server should fail $ hg push svn+ssh://svn.vip.facebook.com/svnroot/tfb/trunk/www -r . --to scratch/serversidebook abort: infinite push does not work with svn repo diff --git a/hgext/infinitepush/__init__.py b/hgext/infinitepush/__init__.py --- a/hgext/infinitepush/__init__.py +++ b/hgext/infinitepush/__init__.py @@ -336,21 +336,6 @@ ('', 'bundle-store', None, _('force push to go to bundle store (EXPERIMENTAL)'))) -bookcmd = extensions.wrapcommand(commands.table, 'bookmarks', exbookmarks) -bookcmd[1].append( -('', 'list-remote', None, - 'list remote bookmarks. ' - 'Positional arguments are interpreted as wildcard patterns. ' - 'Only allowed wildcard is \'*\' in the end of the pattern. ' - 'If no positional arguments are specified then it will list ' - 'the most "important" remote bookmarks. ' - 'Otherwise it will list remote bookmarks ' - 'that match at least one pattern ' - '')) -bookcmd[1].append( -('', 'remote-path', '', - 'name of the remote path to list the bookmarks')) - extensions.wrapcommand(commands.table, 'pull', _pull) extensions.wrapcommand(commands.table, 'update', _update) @@ -363,59 +348,6 @@ partorder.insert( index, partorder.pop(partorder.index(scratchbranchparttype))) -def _showbookmarks(ui, bookmarks, **opts): -# Copy-paste from commands.py -fm = ui.formatter('bookmarks', opts) -for bmark, n in sorted(bookmarks.iteritems()): -fm.startitem() -if not ui.quiet: -fm.plain(' ') -fm.write('bookmark', '%s', bmark) -pad = ' ' * (25 - encoding.colwidth(bmark)) -fm.condwrite(not ui.quiet, 'node', pad + ' %s', n) -fm.plain('\n') -fm.end() - -def exbookmarks(orig, ui, repo, *names, **opts): -pattern = opts.get('list_remote') -delete = opts.get('delete') -remotepath = opts.get('remote_path') -path = ui.paths.getpath(remotepath or None, default=('default')) -if pattern: -destpath = path.pushloc or path.loc -other = hg.peer(repo, opts, destpath) -if not names: -raise error.Abort( -'--list-remote requires a bookmark pattern', -hint='use "hg book" to get a list of your local bookmarks') -else: -fetchedbookmarks = other.listkeyspatterns('bookmarks', - patterns=names) -_showbookmarks(ui, fetchedbookmarks, **opts) -return -elif delete and 'remotenames' in extensions._extensions: -existing_local_bms = set(repo._bookmarks.keys()) -scratch_bms = [] -other_bms = [] -for name in names: -if _scratchbranchmatcher(name) and name not in existing_local_bms: -scratch_bms.append(name) -else: -
D2101: infinitepush: remove wrapping around bundle2._addpartsfromopts()
This revision was automatically updated to reflect the committed changes. Closed by commit rHGe702ca152b33: infinitepush: remove wrapping around bundle2._addpartsfromopts() (authored by pulkit, committed by ). REPOSITORY rHG Mercurial CHANGES SINCE LAST UPDATE https://phab.mercurial-scm.org/D2101?vs=5362=7416 REVISION DETAIL https://phab.mercurial-scm.org/D2101 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 @@ -165,9 +165,6 @@ configitem('infinitepush', 'reponame', default='', ) -configitem('infinitepush', 'bundle-stream', -default=False, -) configitem('scratchbranch', 'storepath', default='', ) @@ -360,7 +357,6 @@ extensions.wrapcommand(commands.table, 'update', _update) extensions.wrapfunction(discovery, 'checkheads', _checkheads) -extensions.wrapfunction(bundle2, '_addpartsfromopts', _addpartsfromopts) wireproto.wirepeer.listkeyspatterns = listkeyspatterns @@ -427,18 +423,6 @@ return return orig(pushop) -def _addpartsfromopts(orig, ui, repo, bundler, *args, **kwargs): -""" adds a stream level part to bundle2 storing whether this is an -infinitepush bundle or not -This functionality is hidden behind a config option: - -[infinitepush] -bundle-stream = True -""" -if ui.configbool('infinitepush', 'bundle-stream', False): -bundler.addparam('infinitepush', True) -return orig(ui, repo, bundler, *args, **kwargs) - def wireprotolistkeyspatterns(repo, proto, namespace, patterns): patterns = wireproto.decodelist(patterns) d = repo.listkeys(encoding.tolocal(namespace), patterns).iteritems() @@ -1255,14 +1239,6 @@ if bundle: bundle.close() -@bundle2.b2streamparamhandler('infinitepush') -def processinfinitepush(unbundler, param, value): -""" process the bundle2 stream level parameter containing whether this push -is an infinitepush or not. """ -if value and unbundler.ui.configbool('infinitepush', - 'bundle-stream', False): -pass - @bundle2.parthandler(scratchbranchparttype, ('bookmark', 'bookprevnode' 'create', 'force', 'pushbackbookmarks', 'cgversion')) 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
D2105: infinitepush: drop hack related to --to, --create flags of remotenames-ext
This revision was automatically updated to reflect the committed changes. Closed by commit rHG14acab54e08b: infinitepush: drop hack related to --to, --create flags of remotenames-ext (authored by pulkit, committed by ). REPOSITORY rHG Mercurial CHANGES SINCE LAST UPDATE https://phab.mercurial-scm.org/D2105?vs=5366=7420 REVISION DETAIL https://phab.mercurial-scm.org/D2105 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 @@ -771,16 +771,6 @@ with ui.configoverride(overrides, 'infinitepush'): scratchpush = opts.get('bundle_store') if _scratchbranchmatcher(bookmark): -# Hack to fix interaction with remotenames. Remotenames push -# '--to' bookmark to the server but we don't want to push scratch -# bookmark to the server. Let's delete '--to' and '--create' and -# also set allow_anon to True (because if --to is not set -# remotenames will think that we are pushing anonymoush head) -if 'to' in opts: -del opts['to'] -if 'create' in opts: -del opts['create'] -opts['allow_anon'] = True scratchpush = True # bundle2 can be sent back after push (for example, bundle2 # containing `pushkey` part to update bookmarks) 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
D2104: infinitepush: drop error handling while pushing to svn server
This revision was automatically updated to reflect the committed changes. Closed by commit rHG3be6f435db4f: infinitepush: drop error handling while pushing to svn server (authored by pulkit, committed by ). REPOSITORY rHG Mercurial CHANGES SINCE LAST UPDATE https://phab.mercurial-scm.org/D2104?vs=5365=7419 REVISION DETAIL https://phab.mercurial-scm.org/D2104 AFFECTED FILES hgext/infinitepush/__init__.py tests/test-infinitepush-bundlestore.t CHANGE DETAILS diff --git a/tests/test-infinitepush-bundlestore.t b/tests/test-infinitepush-bundlestore.t --- a/tests/test-infinitepush-bundlestore.t +++ b/tests/test-infinitepush-bundlestore.t @@ -369,8 +369,3 @@ |/ o initialcommit public -Push to svn server should fail - $ hg push svn+ssh://svn.vip.facebook.com/svnroot/tfb/trunk/www -r . --to scratch/serversidebook - abort: infinite push does not work with svn repo - (did you forget to `hg push default`?) - [255] diff --git a/hgext/infinitepush/__init__.py b/hgext/infinitepush/__init__.py --- a/hgext/infinitepush/__init__.py +++ b/hgext/infinitepush/__init__.py @@ -799,9 +799,6 @@ raise error.Abort(_('default repository not configured!'), hint=_("see 'hg help config.paths'")) destpath = path.pushloc or path.loc -if destpath.startswith('svn+') and scratchpush: -raise error.Abort('infinite push does not work with svn repo', - hint='did you forget to `hg push default`?') # Remote scratch bookmarks will be deleted because remotenames doesn't # know about them. Let's save it before push and restore after remotescratchbookmarks = _readscratchremotebookmarks(ui, repo, destpath) 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
D2107: infinitepush: drop the `--create` flag to push command
This revision was automatically updated to reflect the committed changes. Closed by commit rHG78c2e9418278: infinitepush: drop the `--create` flag to push command (authored by pulkit, committed by ). REPOSITORY rHG Mercurial CHANGES SINCE LAST UPDATE https://phab.mercurial-scm.org/D2107?vs=5368=7423 REVISION DETAIL https://phab.mercurial-scm.org/D2107 AFFECTED FILES hgext/infinitepush/__init__.py hgext/infinitepush/bundleparts.py tests/test-infinitepush-bundlestore.t tests/test-infinitepush.t CHANGE DETAILS diff --git a/tests/test-infinitepush.t b/tests/test-infinitepush.t --- a/tests/test-infinitepush.t +++ b/tests/test-infinitepush.t @@ -49,7 +49,7 @@ $ hg ci -Am "scratchfirstpart" adding scratchfirstpart created new head - $ hg push -r . --to scratch/firstpart --create + $ hg push -r . --to scratch/firstpart pushing to ssh://user@dummy/repo searching for changes remote: pushing 1 commit: @@ -60,7 +60,7 @@ $ hg ci -Am "scratchsecondpart" adding scratchsecondpart created new head - $ hg push -r . --to scratch/secondpart --create + $ hg push -r . --to scratch/secondpart pushing to ssh://user@dummy/repo searching for changes remote: pushing 1 commit: @@ -96,7 +96,7 @@ $ hg log -r '.' -T '{node}\n' > ../testpullbycommithash1 $ echo testpullbycommithash2 > testpullbycommithash2 $ hg ci -Aqm "testpullbycommithash2" - $ hg push -r . --to scratch/mybranch --create -q + $ hg push -r . --to scratch/mybranch -q Create third client and pull by commit hash. Make sure testpullbycommithash2 has not fetched @@ -144,7 +144,7 @@ 1 files updated, 0 files merged, 0 files removed, 0 files unresolved $ echo scratchontopofpublic > scratchontopofpublic $ hg ci -Aqm "scratchontopofpublic" - $ hg push -r . --to scratch/scratchontopofpublic --create + $ hg push -r . --to scratch/scratchontopofpublic pushing to ssh://user@dummy/repo searching for changes remote: pushing 1 commit: @@ -300,7 +300,7 @@ $ hg ci -Aqm "tofillmetadata" $ hg log -r . -T '{node}\n' d2b0410d4da084bc534b1d90df0de9eb21583496 - $ hg push -r . --to scratch/fillmetadata/fill --create + $ hg push -r . --to scratch/fillmetadata/fill pushing to ssh://user@dummy/repo searching for changes remote: pushing 6 commits: diff --git a/tests/test-infinitepush-bundlestore.t b/tests/test-infinitepush-bundlestore.t --- a/tests/test-infinitepush-bundlestore.t +++ b/tests/test-infinitepush-bundlestore.t @@ -18,15 +18,15 @@ $ hg clone ssh://user@dummy/repo client -q $ cd client $ mkcommit initialcommit - $ hg push -r . --create + $ hg push -r . pushing to ssh://user@dummy/repo searching for changes remote: adding changesets remote: adding manifests remote: adding file changes remote: added 1 changesets with 1 changes to 1 files $ mkcommit scratchcommit - $ hg push -r . --to scratch/mybranch --create + $ hg push -r . --to scratch/mybranch pushing to ssh://user@dummy/repo searching for changes remote: pushing 1 commit: @@ -140,7 +140,7 @@ scratch/mybranch 1de1d7d92f8965260391d0513fe8a8d5973d3042 Push scratch bookmark with no new revs - $ hg push -r . --to scratch/anotherbranch --create + $ hg push -r . --to scratch/anotherbranch pushing to ssh://user@dummy/repo searching for changes remote: pushing 2 commits: diff --git a/hgext/infinitepush/bundleparts.py b/hgext/infinitepush/bundleparts.py --- a/hgext/infinitepush/bundleparts.py +++ b/hgext/infinitepush/bundleparts.py @@ -23,7 +23,7 @@ scratchbranchparttype = 'b2x:infinitepush' def getscratchbranchparts(repo, peer, outgoing, confignonforwardmove, - ui, bookmark, create): + ui, bookmark): if not outgoing.missing: raise error.Abort(_('no commits to push')) @@ -49,8 +49,6 @@ params['bookprevnode'] = '' if bookmark in repo: params['bookprevnode'] = repo[bookmark].hex() -if create: -params['create'] = '1' if confignonforwardmove: params['force'] = '1' diff --git a/hgext/infinitepush/__init__.py b/hgext/infinitepush/__init__.py --- a/hgext/infinitepush/__init__.py +++ b/hgext/infinitepush/__init__.py @@ -175,9 +175,6 @@ configitem('experimental', 'server-bundlestore-bookmark', default='', ) -configitem('experimental', 'server-bundlestore-create', -default='', -) configitem('experimental', 'infinitepush-scratchpush', default=False, ) @@ -187,7 +184,6 @@ experimental = 'experimental' configbookmark = 'server-bundlestore-bookmark' -configcreate = 'server-bundlestore-create' configscratchpush = 'infinitepush-scratchpush' confignonforwardmove = 'non-forward-move' @@ -328,10 +324,6 @@ _('allows moving a remote bookmark to an ' 'arbitrary place'))) -if not any(a for a in entry[1] if a[1] == 'create'): -entry[1].append( -('',
D2098: infinitepush: drop the logic related to inhibit extension
This revision was automatically updated to reflect the committed changes. Closed by commit rHGb377b7dfe682: infinitepush: drop the logic related to inhibit extension (authored by pulkit, committed by ). REPOSITORY rHG Mercurial CHANGES SINCE LAST UPDATE https://phab.mercurial-scm.org/D2098?vs=5359=7413 REVISION DETAIL https://phab.mercurial-scm.org/D2098 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 @@ -791,24 +791,6 @@ opts['bookmark'] = bookmarks opts['rev'] = revs -try: -inhibitmod = extensions.find('inhibit') -except KeyError: -# Ignore if inhibit is not enabled -pass -else: -# Pulling revisions that were filtered results in a error. -# Let's inhibit them -unfi = repo.unfiltered() -for rev in opts.get('rev', []): -try: -repo[rev] -except error.FilteredRepoLookupError: -node = unfi[rev].node() -inhibitmod.revive([repo.unfiltered()[node]]) -except error.RepoLookupError: -pass - if scratchbookmarks or unknownnodes: # Set anyincoming to True extensions.wrapfunction(discovery, 'findcommonincoming', 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
D2097: infinitepush: remove backupcommands.py
This revision was automatically updated to reflect the committed changes. Closed by commit rHGde4c2f3af97f: infinitepush: remove backupcommands.py (authored by pulkit, committed by ). REPOSITORY rHG Mercurial CHANGES SINCE LAST UPDATE https://phab.mercurial-scm.org/D2097?vs=5358=7412 REVISION DETAIL https://phab.mercurial-scm.org/D2097 AFFECTED FILES hgext/infinitepush/__init__.py hgext/infinitepush/backupcommands.py hgext/infinitepush/infinitepushcommands.py CHANGE DETAILS diff --git a/hgext/infinitepush/infinitepushcommands.py b/hgext/infinitepush/infinitepushcommands.py --- a/hgext/infinitepush/infinitepushcommands.py +++ b/hgext/infinitepush/infinitepushcommands.py @@ -30,13 +30,12 @@ ) from . import ( -backupcommands, common, ) downloadbundle = common.downloadbundle -cmdtable = backupcommands.cmdtable +cmdtable = {} command = registrar.command(cmdtable) @command('debugfillinfinitepushmetadata', diff --git a/hgext/infinitepush/backupcommands.py b/hgext/infinitepush/backupcommands.py deleted file mode 100644 --- a/hgext/infinitepush/backupcommands.py +++ /dev/null @@ -1,992 +0,0 @@ -# Copyright 2017 Facebook, Inc. -# -# This software may be used and distributed according to the terms of the -# GNU General Public License version 2 or any later version. -""" -[infinitepushbackup] -# Whether to enable automatic backups. If this option is True then a backup -# process will be started after every mercurial command that modifies the -# repo, for example, commit, amend, histedit, rebase etc. -autobackup = False - -# path to the directory where pushback logs should be stored -logdir = path/to/dir - -# Backup at most maxheadstobackup heads, other heads are ignored. -# Negative number means backup everything. -maxheadstobackup = -1 - -# Nodes that should not be backed up. Ancestors of these nodes won't be -# backed up either -dontbackupnodes = [] - -# Special option that may be used to trigger re-backuping. For example, -# if there was a bug in infinitepush backups, then changing the value of -# this option will force all clients to make a "clean" backup -backupgeneration = 0 - -# Hostname value to use. If not specified then socket.gethostname() will -# be used -hostname = '' - -# Enable reporting of infinitepush backup status as a summary at the end -# of smartlog. -enablestatus = False - -# Whether or not to save information about the latest successful backup. -# This information includes the local revision number and unix timestamp -# of the last time we successfully made a backup. -savelatestbackupinfo = False -""" - -from __future__ import absolute_import - -import collections -import errno -import json -import os -import re -import socket -import stat -import subprocess -import time - -from mercurial.node import ( -bin, -hex, -nullrev, -short, -) - -from mercurial.i18n import _ - -from mercurial import ( -bundle2, -changegroup, -commands, -discovery, -dispatch, -encoding, -error, -extensions, -hg, -localrepo, -lock as lockmod, -phases, -policy, -registrar, -scmutil, -util, -) - -from . import bundleparts - -getscratchbookmarkspart = bundleparts.getscratchbookmarkspart -getscratchbranchparts = bundleparts.getscratchbranchparts - -from hgext3rd import shareutil - -osutil = policy.importmod(r'osutil') - -cmdtable = {} -command = registrar.command(cmdtable) -revsetpredicate = registrar.revsetpredicate() -templatekeyword = registrar.templatekeyword() - -backupbookmarktuple = collections.namedtuple('backupbookmarktuple', - ['hostname', 'reporoot', 'localbookmark']) - -class backupstate(object): -def __init__(self): -self.heads = set() -self.localbookmarks = {} - -def empty(self): -return not self.heads and not self.localbookmarks - -class WrongPermissionsException(Exception): -def __init__(self, logdir): -self.logdir = logdir - -restoreoptions = [ - ('', 'reporoot', '', 'root of the repo to restore'), - ('', 'user', '', 'user who ran the backup'), - ('', 'hostname', '', 'hostname of the repo to restore'), -] - -_backuplockname = 'infinitepushbackup.lock' - -def extsetup(ui): -if ui.configbool('infinitepushbackup', 'autobackup', False): -extensions.wrapfunction(dispatch, 'runcommand', -_autobackupruncommandwrapper) -extensions.wrapfunction(localrepo.localrepository, 'transaction', -_transaction) - -@command('pushbackup', - [('', 'background', None, 'run backup in background')]) -def backup(ui, repo, dest=None, **opts): -""" -Pushes commits, bookmarks and heads to infinitepush. -New non-extinct commits are saved since the last `hg pushbackup` -or since 0 revision if this backup is the first. -
D2100: infinitepush: delete the bundle2 part ordering related to pushrebase
This revision was automatically updated to reflect the committed changes. Closed by commit rHG2fdc827f76ec: infinitepush: delete the bundle2 part ordering related to pushrebase (authored by pulkit, committed by ). REPOSITORY rHG Mercurial CHANGES SINCE LAST UPDATE https://phab.mercurial-scm.org/D2100?vs=5361=7415 REVISION DETAIL https://phab.mercurial-scm.org/D2100 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 @@ -190,7 +190,6 @@ default=False, ) -pushrebaseparttype = 'b2x:rebase' experimental = 'experimental' configbookmark = 'server-bundlestore-bookmark' configcreate = 'server-bundlestore-create' @@ -365,12 +364,8 @@ wireproto.wirepeer.listkeyspatterns = listkeyspatterns -# Move infinitepush part before pushrebase part -# to avoid generation of both parts. partorder = exchange.b2partsgenorder index = partorder.index('changeset') -if pushrebaseparttype in partorder: -index = min(index, partorder.index(pushrebaseparttype)) partorder.insert( index, partorder.pop(partorder.index(scratchbranchparttype))) 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
D2102: infinitepush: drop the scratchbookmarksparttype bundle2 part
This revision was automatically updated to reflect the committed changes. Closed by commit rHG5a9692d0d6fc: infinitepush: drop the scratchbookmarksparttype bundle2 part (authored by pulkit, committed by ). REPOSITORY rHG Mercurial CHANGES SINCE LAST UPDATE https://phab.mercurial-scm.org/D2102?vs=5363=7417 REVISION DETAIL https://phab.mercurial-scm.org/D2102 AFFECTED FILES hgext/infinitepush/__init__.py hgext/infinitepush/bundleparts.py hgext/infinitepush/common.py CHANGE DETAILS diff --git a/hgext/infinitepush/common.py b/hgext/infinitepush/common.py --- a/hgext/infinitepush/common.py +++ b/hgext/infinitepush/common.py @@ -5,9 +5,7 @@ from __future__ import absolute_import -import json import os -import struct import tempfile from mercurial.node import hex @@ -21,14 +19,6 @@ return ('remotenames' in extensions._extensions and ui.configbool('remotenames', 'bookmarks')) -def encodebookmarks(bookmarks): -encoded = {} -for bookmark, node in bookmarks.iteritems(): -encoded[bookmark] = node -dumped = json.dumps(encoded) -result = struct.pack('>i', len(dumped)) + dumped -return result - def downloadbundle(repo, unknownbinhead): index = repo.bundlestore.index store = repo.bundlestore.store diff --git a/hgext/infinitepush/bundleparts.py b/hgext/infinitepush/bundleparts.py --- a/hgext/infinitepush/bundleparts.py +++ b/hgext/infinitepush/bundleparts.py @@ -18,11 +18,9 @@ from . import common -encodebookmarks = common.encodebookmarks isremotebooksenabled = common.isremotebooksenabled scratchbranchparttype = 'b2x:infinitepush' -scratchbookmarksparttype = 'b2x:infinitepushscratchbookmarks' def getscratchbranchparts(repo, peer, outgoing, confignonforwardmove, ui, bookmark, create): @@ -85,15 +83,6 @@ return parts -def getscratchbookmarkspart(peer, bookmarks): -if scratchbookmarksparttype not in bundle2.bundle2caps(peer): -raise error.Abort( -_('no server support for %r') % scratchbookmarksparttype) - -return bundle2.bundlepart( -scratchbookmarksparttype.upper(), -data=encodebookmarks(bookmarks)) - def _validaterevset(repo, revset, bookmark): """Abort if the revs to be pushed aren't valid for a scratch branch.""" if not repo.revs(revset): diff --git a/hgext/infinitepush/__init__.py b/hgext/infinitepush/__init__.py --- a/hgext/infinitepush/__init__.py +++ b/hgext/infinitepush/__init__.py @@ -91,13 +91,11 @@ import contextlib import errno import functools -import json import logging import os import random import re import socket -import struct import subprocess import sys import tempfile @@ -682,19 +680,6 @@ return "%s %s\n" % (0, r) return _lookup -def _decodebookmarks(stream): -sizeofjsonsize = struct.calcsize('>i') -size = struct.unpack('>i', stream.read(sizeofjsonsize))[0] -unicodedict = json.loads(stream.read(size)) -# python json module always returns unicode strings. We need to convert -# it back to bytes string -result = {} -for bookmark, node in unicodedict.iteritems(): -bookmark = bookmark.encode('ascii') -node = node.encode('ascii') -result[bookmark] = node -return result - def _update(orig, ui, repo, node=None, rev=None, **opts): if rev and node: raise error.Abort(_("please specify just one revision")) @@ -985,7 +970,6 @@ return handlereply bundle2.capabilities[bundleparts.scratchbranchparttype] = () -bundle2.capabilities[bundleparts.scratchbookmarksparttype] = () def _getrevs(bundle, oldnode, force, bookmark): 'extracts and validates the revs to be imported' @@ -1059,7 +1043,6 @@ bundler = bundle2.bundle20(repo.ui) cgparams = None -scratchbookpart = None with bundle2.partiterator(repo, op, unbundler) as parts: for part in parts: bundlepart = None @@ -1084,14 +1067,6 @@ op.records.add(scratchbranchparttype + '_skippushkey', True) op.records.add(scratchbranchparttype + '_skipphaseheads', True) -elif part.type == bundleparts.scratchbookmarksparttype: -# Save this for later processing. Details below. -# -# Upstream https://phab.mercurial-scm.org/D1389 and its -# follow-ups stop part.seek support to reduce memory usage -# (https://bz.mercurial-scm.org/5691). So we need to copy -# the part so it can be consumed later. -scratchbookpart = bundleparts.copiedpart(part) else: if handleallparts or part.type in partforwardingwhitelist: # Ideally we would not process any parts, and instead just @@ -1137,12 +1112,6 @@ # we would rather see the original exception pass -# The scratch
D2099: infinitepush: delete the hack to load the extension after remotenames
This revision was automatically updated to reflect the committed changes. Closed by commit rHGecdd8c3044de: infinitepush: delete the hack to load the extension after remotenames (authored by pulkit, committed by ). REPOSITORY rHG Mercurial CHANGES SINCE LAST UPDATE https://phab.mercurial-scm.org/D2099?vs=5360=7414 REVISION DETAIL https://phab.mercurial-scm.org/D2099 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 @@ -286,14 +286,6 @@ if _isserver(ui) and repo.local(): repo.bundlestore = bundlestore(repo) -def uisetup(ui): -# remotenames circumvents the default push implementation entirely, so make -# sure we load after it so that we wrap it. -order = extensions._order -order.remove('infinitepush') -order.append('infinitepush') -extensions._order = order - def extsetup(ui): commonsetup(ui) if _isserver(ui): 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
D2096: infinitepush: move the extension to core from fb-hgext
indygreg accepted this revision. indygreg added a comment. This revision is now accepted and ready to land. OK. I applied this series locally and looked at the final code. There are some minor issues with the current series. But I can fix those in flight. I've also captured a number of other issues in the review of this commit. IMO they can be addressed as follow-ups. A larger issue that I think may be worth pursuing is dropping the code to support pre-bundle2. I think it is reasonable for a server operator to say that a repo using this feature requires bundle2. Because attempting to handle e.g. bookmark or phases updates pre-bundle2 is a recipe for disaster since these updates are performed on a separate wire protocol command, after changegroup data is exchanged. Clients pushing without bundle2 may see errors on `pushkey` operations because nodes aren't readily available. And, having a server update bookmarks, phases, etc in multiple bundles isn't reasonable. I would make it so enabling this extension also implies `server.bundle1=false`. INLINE COMMENTS > README:1 > +## What is it? > + I think we can delete this file since it is redundant with info in the docstring of the extension. > __init__.py:1409-1428 > +def _asyncsavemetadata(root, nodes): > +'''starts a separate process that fills metadata for the nodes > + > +This function creates a separate process and doesn't wait for it's > +completion. This was done to avoid slowing down pushes > +''' > + This code can be deleted since `hg debugfilleinfinitepushmetadata` was deleted. > indexapi.py:10 > + > +class indexapi(object): > +"""Class that manages access to infinitepush index. We'll want to port this to `zope.interface`. > sqlindexapi.py:15 > +import warnings > +import mysql.connector > + I think we should rename this module since it is MySQL specific. Various database packages do conform to a similar API. So we could potentially make the SQL layer implementation agnostic by coding to an interface. > sqlindexapi.py:64 > +self.sqlconn = mysql.connector.connect( > +force_ipv6=True, **self.sqlargs) > + `force_ipv6=True`. Kudos to Facebook for getting away with that in their network. But this won't fly in the real world. > sqlindexapi.py:84-85 > +self.sqlcursor = self.sqlconn.cursor() > +self.sqlcursor.execute("SET wait_timeout=%s" % waittimeout) > +self.sqlcursor.execute("SET innodb_lock_wait_timeout=%s" % > + self._locktimeout) And here we have some MySQL specific functionality :/ REPOSITORY rHG Mercurial REVISION DETAIL https://phab.mercurial-scm.org/D2096 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
D2976: extdiff: document that it copies modified files back to working directory
spectral 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/D2976 AFFECTED FILES hgext/extdiff.py tests/test-extension.t CHANGE DETAILS diff --git a/tests/test-extension.t b/tests/test-extension.t --- a/tests/test-extension.t +++ b/tests/test-extension.t @@ -730,6 +730,10 @@ called with a configurable set of options and two non-option arguments: paths to directories containing snapshots of files to compare. + If there is more than one file being compared and the "child" revision is the + working directory, any modifications made in the external diff program will be + copied back to the working directory from the temporary directory. + The extdiff extension also allows you to configure new diff commands, so you do not need to type 'hg extdiff -p kdiff3' always. diff --git a/hgext/extdiff.py b/hgext/extdiff.py --- a/hgext/extdiff.py +++ b/hgext/extdiff.py @@ -13,6 +13,11 @@ non-option arguments: paths to directories containing snapshots of files to compare. +If there is more than one file being compared and the "child" revision +is the working directory, any modifications made in the external diff +program will be copied back to the working directory from the temporary +directory. + The extdiff extension also allows you to configure new diff commands, so you do not need to type :hg:`extdiff -p kdiff3` always. :: To: spectral, #hg-reviewers Cc: mercurial-devel ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
D2897: fix: new extension for automatically modifying file contents
This revision was automatically updated to reflect the committed changes. Closed by commit rHGded5ea279a93: fix: new extension for automatically modifying file contents (authored by hooper, committed by ). REPOSITORY rHG Mercurial CHANGES SINCE LAST UPDATE https://phab.mercurial-scm.org/D2897?vs=7366=7406 REVISION DETAIL https://phab.mercurial-scm.org/D2897 AFFECTED FILES hgext/fix.py tests/test-doctest.py tests/test-fix-clang-format.t tests/test-fix-topology.t tests/test-fix.t CHANGE DETAILS diff --git a/tests/test-fix.t b/tests/test-fix.t new file mode 100644 --- /dev/null +++ b/tests/test-fix.t @@ -0,0 +1,969 @@ +Set up the config with two simple fixers: one that fixes specific line ranges, +and one that always fixes the whole file. They both "fix" files by converting +letters to uppercase. They use different file extensions, so each test case can +choose which behavior to use by naming files. + + $ cat >> $HGRCPATH < [extensions] + > fix = + > [experimental] + > evolution.createmarkers=True + > evolution.allowunstable=True + > [fix] + > uppercase-whole-file:command=sed -e 's/.*/\U&/' + > uppercase-whole-file:fileset=set:**.whole + > uppercase-changed-lines:command=sed + > uppercase-changed-lines:linerange=-e '{first},{last} s/.*/\U&/' + > uppercase-changed-lines:fileset=set:**.changed + > EOF + +Help text for fix. + + $ hg help fix + hg fix [OPTION]... [FILE]... + + rewrite file content in changesets or working directory + + Runs any configured tools to fix the content of files. Only affects files + with changes, unless file arguments are provided. Only affects changed + lines of files, unless the --whole flag is used. Some tools may always + affect the whole file regardless of --whole. + + If revisions are specified with --rev, those revisions will be checked, + and they may be replaced with new revisions that have fixed file content. + It is desirable to specify all descendants of each specified revision, so + that the fixes propagate to the descendants. If all descendants are fixed + at the same time, no merging, rebasing, or evolution will be required. + + If --working-dir is used, files with uncommitted changes in the working + copy will be fixed. If the checked-out revision is also fixed, the working + directory will update to the replacement revision. + + When determining what lines of each file to fix at each revision, the + whole set of revisions being fixed is considered, so that fixes to earlier + 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. + + (use 'hg help -e fix' to show help for the fix extension) + + options ([+] can be repeated): + + --base REV [+] revisions to diff against (overrides automatic selection, + and applies to every revision being fixed) + -r --rev REV [+] revisions to fix + -w --working-dir fix the working directory + --wholealways fix every line of a file + + (some details hidden, use --verbose to show complete help) + + $ hg help -e fix + fix extension - rewrite file content in changesets or working copy + (EXPERIMENTAL) + + Provides a command that runs configured tools on the contents of modified + files, writing back any fixes to the working copy or replacing changesets. + + Here is an example configuration that causes 'hg fix' to apply automatic + formatting fixes to modified lines in C++ code: + +[fix] +clang-format:command=clang-format --assume-filename={rootpath} +clang-format:linerange=--lines={first}:{last} +clang-format:fileset=set:**.cpp or **.hpp + + The :command suboption forms the first part of the shell command that will be + used to fix a file. The content of the file is passed on standard input, and + the fixed file content is expected on standard output. If there is any output + on standard error, the file will not be affected. Some values may be + substituted into the command: + +{rootpath} The path of the file being fixed, relative to the repo root +{basename} The name of the file being fixed, without the directory path + + If the :linerange suboption is set, the tool will only be run if there are + changed lines in a file. The value of this suboption is appended to the shell + command once for every range of changed lines in the file. Some values may be + substituted into the command: + +{first} The 1-based line number of the first line in the modified range +{last}The 1-based line number of the last line in the modified range + + The :fileset suboption determines which files will be passed through each + configured tool. See 'hg help fileset' for possible values. If there are file + arguments to 'hg fix', the intersection of these filesets is used. + + There is also a
D2973: narrow: use repo.local() instead of isinstance()
This revision was automatically updated to reflect the committed changes. Closed by commit rHG6d43b39fbaa0: narrow: use repo.local() instead of isinstance() (authored by martinvonz, committed by ). REPOSITORY rHG Mercurial CHANGES SINCE LAST UPDATE https://phab.mercurial-scm.org/D2973?vs=7402=7409 REVISION DETAIL https://phab.mercurial-scm.org/D2973 AFFECTED FILES hgext/narrow/__init__.py CHANGE DETAILS diff --git a/hgext/narrow/__init__.py b/hgext/narrow/__init__.py --- a/hgext/narrow/__init__.py +++ b/hgext/narrow/__init__.py @@ -71,7 +71,7 @@ def reposetup(ui, repo): """Wraps local repositories with narrow repo support.""" -if not isinstance(repo, localrepo.localrepository): +if not repo.local(): return narrowrepo.wraprepo(repo) To: martinvonz, durin42, #hg-reviewers, pulkit Cc: mercurial-devel ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
D2974: contrib: rename clang-format-blacklist to clang-format-ignorelist
This revision was automatically updated to reflect the committed changes. Closed by commit rHG0024961aa493: contrib: rename clang-format-blacklist to clang-format-ignorelist (authored by indygreg, committed by ). REPOSITORY rHG Mercurial CHANGES SINCE LAST UPDATE https://phab.mercurial-scm.org/D2974?vs=7404=7407 REVISION DETAIL https://phab.mercurial-scm.org/D2974 AFFECTED FILES Makefile contrib/clang-format-blacklist contrib/clang-format-ignorelist tests/test-check-clang-format.t CHANGE DETAILS diff --git a/tests/test-check-clang-format.t b/tests/test-check-clang-format.t --- a/tests/test-check-clang-format.t +++ b/tests/test-check-clang-format.t @@ -3,7 +3,7 @@ $ . "$TESTDIR/helpers-testrepo.sh" $ cd "$TESTDIR"/.. - $ for f in `testrepohg files 'set:(**.c or **.cc or **.h) and not "listfile:contrib/clang-format-blacklist"'` ; do + $ for f in `testrepohg files 'set:(**.c or **.cc or **.h) and not "listfile:contrib/clang-format-ignorelist"'` ; do > clang-format --style file $f > $f.formatted > cmp $f $f.formatted || diff -u $f $f.formatted > rm $f.formatted diff --git a/contrib/clang-format-blacklist b/contrib/clang-format-ignorelist rename from contrib/clang-format-blacklist rename to contrib/clang-format-ignorelist diff --git a/Makefile b/Makefile --- a/Makefile +++ b/Makefile @@ -124,7 +124,7 @@ format-c: clang-format --style file -i \ - `hg files 'set:(**.c or **.cc or **.h) and not "listfile:contrib/clang-format-blacklist"'` + `hg files 'set:(**.c or **.cc or **.h) and not "listfile:contrib/clang-format-ignorelist"'` update-pot: i18n/hg.pot To: indygreg, #hg-reviewers, pulkit Cc: mercurial-devel ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
D2975: tests: add zope.interface to clang-format ignore list
This revision was automatically updated to reflect the committed changes. Closed by commit rHG027db60ae756: tests: add zope.interface to clang-format ignore list (authored by indygreg, committed by ). REPOSITORY rHG Mercurial CHANGES SINCE LAST UPDATE https://phab.mercurial-scm.org/D2975?vs=7405=7408 REVISION DETAIL https://phab.mercurial-scm.org/D2975 AFFECTED FILES contrib/clang-format-ignorelist CHANGE DETAILS diff --git a/contrib/clang-format-ignorelist b/contrib/clang-format-ignorelist --- a/contrib/clang-format-ignorelist +++ b/contrib/clang-format-ignorelist @@ -67,3 +67,4 @@ mercurial/thirdparty/xdiff/xtypes.h mercurial/thirdparty/xdiff/xutils.c mercurial/thirdparty/xdiff/xutils.h +mercurial/thirdparty/zope/interface/_zope_interface_coptimizations.c To: indygreg, #hg-reviewers, pulkit Cc: mercurial-devel ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
D2096: infinitepush: move the extension to core from fb-hgext
indygreg added inline comments. INLINE COMMENTS > __init__.py:136 > +common, > +infinitepushcommands, > +) This deleted module isn't dropped later in the series. > __init__.py:266 > +self._repo = repo > +storetype = self._repo.ui.config('infinitepush', 'storetype', '') > +if storetype == 'disk': Default value can be dropped. > __init__.py:276 > + > +indextype = self._repo.ui.config('infinitepush', 'indextype', '') > +if indextype == 'disk': Default value can be dropped. REPOSITORY rHG Mercurial REVISION DETAIL https://phab.mercurial-scm.org/D2096 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
D2096: infinitepush: move the extension to core from fb-hgext
indygreg added inline comments. INLINE COMMENTS > __init__.py:258 > +if common.isremotebooksenabled(ui): > +hoist = ui.config('remotenames', 'hoist') + '/' > +if remotebookmark.startswith(hoist): This will need updated to `hoistedpeer`. REPOSITORY rHG Mercurial REVISION DETAIL https://phab.mercurial-scm.org/D2096 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
D2943: grep: fixes errorneous output of grep in forward order
pulkit closed this revision. pulkit added a comment. This was committed as https://www.mercurial-scm.org/repo/hg/rev/a2a6755a3def. REPOSITORY rHG Mercurial REVISION DETAIL https://phab.mercurial-scm.org/D2943 To: pulkit, #hg-reviewers, yuja, sangeet259 Cc: yuja, mercurial-devel ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
D2897: fix: new extension for automatically modifying file contents
pulkit accepted this revision. pulkit added inline comments. INLINE COMMENTS > hooper wrote in test-fix.t:857 > Would it abort or merge if the working copy is dirty? Is that behavior > expected to end up in cleanupnodes? It could also just force --working-dir. > It's similar to creating an orphan if we don't fix the dirty working copy. > > One of my goals is to avoid any need for merging or conflict resolution in > this command. > One of my goals is to avoid any need for merging or conflict resolution in > this command. That makes sense. I am good with current behavior then. REPOSITORY rHG Mercurial REVISION DETAIL https://phab.mercurial-scm.org/D2897 To: hooper, #hg-reviewers, pulkit Cc: durin42, krbullock, martinvonz, yuja, indygreg, pulkit, mercurial-devel ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
D2975: tests: add zope.interface to clang-format ignore list
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/D2975 AFFECTED FILES contrib/clang-format-ignorelist CHANGE DETAILS diff --git a/contrib/clang-format-ignorelist b/contrib/clang-format-ignorelist --- a/contrib/clang-format-ignorelist +++ b/contrib/clang-format-ignorelist @@ -67,3 +67,4 @@ mercurial/thirdparty/xdiff/xtypes.h mercurial/thirdparty/xdiff/xutils.c mercurial/thirdparty/xdiff/xutils.h +mercurial/thirdparty/zope/interface/_zope_interface_coptimizations.c 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
D2974: contrib: rename clang-format-blacklist to clang-format-ignorelist
indygreg created this revision. Herald added a subscriber: mercurial-devel. Herald added a reviewer: hg-reviewers. REVISION SUMMARY "blacklist" is racially charged. Let's rename it to something that isn't. REPOSITORY rHG Mercurial REVISION DETAIL https://phab.mercurial-scm.org/D2974 AFFECTED FILES Makefile contrib/clang-format-blacklist contrib/clang-format-ignorelist tests/test-check-clang-format.t CHANGE DETAILS diff --git a/tests/test-check-clang-format.t b/tests/test-check-clang-format.t --- a/tests/test-check-clang-format.t +++ b/tests/test-check-clang-format.t @@ -3,7 +3,7 @@ $ . "$TESTDIR/helpers-testrepo.sh" $ cd "$TESTDIR"/.. - $ for f in `testrepohg files 'set:(**.c or **.cc or **.h) and not "listfile:contrib/clang-format-blacklist"'` ; do + $ for f in `testrepohg files 'set:(**.c or **.cc or **.h) and not "listfile:contrib/clang-format-ignorelist"'` ; do > clang-format --style file $f > $f.formatted > cmp $f $f.formatted || diff -u $f $f.formatted > rm $f.formatted diff --git a/contrib/clang-format-blacklist b/contrib/clang-format-ignorelist rename from contrib/clang-format-blacklist rename to contrib/clang-format-ignorelist diff --git a/Makefile b/Makefile --- a/Makefile +++ b/Makefile @@ -124,7 +124,7 @@ format-c: clang-format --style file -i \ - `hg files 'set:(**.c or **.cc or **.h) and not "listfile:contrib/clang-format-blacklist"'` + `hg files 'set:(**.c or **.cc or **.h) and not "listfile:contrib/clang-format-ignorelist"'` update-pot: i18n/hg.pot 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
D2958: infinitepush: introduce server option to route every push to bundlestore
indygreg accepted this revision. indygreg added a comment. This revision is now accepted and ready to land. This looks reasonable. Could we also please get an explicit test for `hg pull -r ` in this server configuration? Yes, I believe that will be redundant with other tests. But it is useful to have explicit coverage for this specific server operation mode. INLINE COMMENTS > test-infinitepush-ci.t:142 > + > +XXX: we should have pushed only the parts which are not in bundlestore > + $ hg push I actually think the behavior is acceptable. Having to dynamically overlay multiple bundles from the bundle store on the server feels like it will be a lot of work. For cases where the server is mainly ingesting ad-hoc commits, it is fine to have to re-push changesets. This could get annoying if people are pushing very large changesets. But until we have a better store, I don't think there's much we can do. REPOSITORY rHG Mercurial REVISION DETAIL https://phab.mercurial-scm.org/D2958 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
D2930: thirdparty: port zope.interface to relative imports
This revision was automatically updated to reflect the committed changes. Closed by commit rHG68ee61822182: thirdparty: port zope.interface to relative imports (authored by indygreg, committed by ). REPOSITORY rHG Mercurial CHANGES SINCE LAST UPDATE https://phab.mercurial-scm.org/D2930?vs=7243=7397 REVISION DETAIL https://phab.mercurial-scm.org/D2930 AFFECTED FILES mercurial/thirdparty/zope/interface/__init__.py mercurial/thirdparty/zope/interface/_compat.py mercurial/thirdparty/zope/interface/_flatten.py mercurial/thirdparty/zope/interface/_zope_interface_coptimizations.c mercurial/thirdparty/zope/interface/adapter.py mercurial/thirdparty/zope/interface/advice.py mercurial/thirdparty/zope/interface/common/idatetime.py mercurial/thirdparty/zope/interface/common/interfaces.py mercurial/thirdparty/zope/interface/common/mapping.py mercurial/thirdparty/zope/interface/common/sequence.py mercurial/thirdparty/zope/interface/declarations.py mercurial/thirdparty/zope/interface/document.py mercurial/thirdparty/zope/interface/exceptions.py mercurial/thirdparty/zope/interface/interface.py mercurial/thirdparty/zope/interface/interfaces.py mercurial/thirdparty/zope/interface/registry.py mercurial/thirdparty/zope/interface/ro.py mercurial/thirdparty/zope/interface/verify.py CHANGE DETAILS diff --git a/mercurial/thirdparty/zope/interface/verify.py b/mercurial/thirdparty/zope/interface/verify.py --- a/mercurial/thirdparty/zope/interface/verify.py +++ b/mercurial/thirdparty/zope/interface/verify.py @@ -13,10 +13,12 @@ ## """Verify interface implementations """ -from zope.interface.exceptions import BrokenImplementation, DoesNotImplement -from zope.interface.exceptions import BrokenMethodImplementation +from __future__ import absolute_import + +from .exceptions import BrokenImplementation, DoesNotImplement +from .exceptions import BrokenMethodImplementation from types import FunctionType, MethodType -from zope.interface.interface import fromMethod, fromFunction, Method +from .interface import fromMethod, fromFunction, Method import sys # This will be monkey-patched when running under Zope 2, so leave this diff --git a/mercurial/thirdparty/zope/interface/ro.py b/mercurial/thirdparty/zope/interface/ro.py --- a/mercurial/thirdparty/zope/interface/ro.py +++ b/mercurial/thirdparty/zope/interface/ro.py @@ -13,6 +13,9 @@ ## """Compute a resolution order for an object and its bases """ + +from __future__ import absolute_import + __docformat__ = 'restructuredtext' def _mergeOrderings(orderings): diff --git a/mercurial/thirdparty/zope/interface/registry.py b/mercurial/thirdparty/zope/interface/registry.py --- a/mercurial/thirdparty/zope/interface/registry.py +++ b/mercurial/thirdparty/zope/interface/registry.py @@ -13,31 +13,34 @@ ## """Basic components support """ + +from __future__ import absolute_import + from collections import defaultdict try: -from zope.event import notify +from ..event import notify except ImportError: # pragma: no cover def notify(*arg, **kw): pass -from zope.interface.interfaces import ISpecification -from zope.interface.interfaces import ComponentLookupError -from zope.interface.interfaces import IAdapterRegistration -from zope.interface.interfaces import IComponents -from zope.interface.interfaces import IHandlerRegistration -from zope.interface.interfaces import ISubscriptionAdapterRegistration -from zope.interface.interfaces import IUtilityRegistration -from zope.interface.interfaces import Registered -from zope.interface.interfaces import Unregistered +from .interfaces import ISpecification +from .interfaces import ComponentLookupError +from .interfaces import IAdapterRegistration +from .interfaces import IComponents +from .interfaces import IHandlerRegistration +from .interfaces import ISubscriptionAdapterRegistration +from .interfaces import IUtilityRegistration +from .interfaces import Registered +from .interfaces import Unregistered -from zope.interface.interface import Interface -from zope.interface.declarations import implementedBy -from zope.interface.declarations import implementer -from zope.interface.declarations import implementer_only -from zope.interface.declarations import providedBy -from zope.interface.adapter import AdapterRegistry -from zope.interface._compat import CLASS_TYPES -from zope.interface._compat import STRING_TYPES +from .interface import Interface +from .declarations import implementedBy +from .declarations import implementer +from .declarations import implementer_only +from .declarations import providedBy +from .adapter import AdapterRegistry +from ._compat import CLASS_TYPES +from ._compat import STRING_TYPES class _UnhashableComponentCounter(object):
D2932: setup: register zope.interface packages and compile C extension
This revision was automatically updated to reflect the committed changes. Closed by commit rHG922b3fae9c7d: setup: register zope.interface packages and compile C extension (authored by indygreg, committed by ). REPOSITORY rHG Mercurial CHANGES SINCE LAST UPDATE https://phab.mercurial-scm.org/D2932?vs=7351=7399 REVISION DETAIL https://phab.mercurial-scm.org/D2932 AFFECTED FILES contrib/import-checker.py setup.py CHANGE DETAILS diff --git a/setup.py b/setup.py --- a/setup.py +++ b/setup.py @@ -812,6 +812,8 @@ 'mercurial.thirdparty.attr', 'mercurial.thirdparty.cbor', 'mercurial.thirdparty.cbor.cbor2', +'mercurial.thirdparty.zope', +'mercurial.thirdparty.zope.interface', 'mercurial.utils', 'hgext', 'hgext.convert', 'hgext.fsmonitor', 'hgext.fsmonitor.pywatchman', 'hgext.highlight', @@ -894,6 +896,10 @@ extra_compile_args=osutil_cflags, extra_link_args=osutil_ldflags, depends=common_depends), +Extension( +'mercurial.thirdparty.zope.interface._zope_interface_coptimizations', [ +'mercurial/thirdparty/zope/interface/_zope_interface_coptimizations.c', +]), Extension('hgext.fsmonitor.pywatchman.bser', ['hgext/fsmonitor/pywatchman/bser.c']), ] diff --git a/contrib/import-checker.py b/contrib/import-checker.py --- a/contrib/import-checker.py +++ b/contrib/import-checker.py @@ -37,6 +37,8 @@ 'mercurial.pure.parsers', # third-party imports should be directly imported 'mercurial.thirdparty', +'mercurial.thirdparty.zope', +'mercurial.thirdparty.zope.interface', ) # Whitelist of symbols that can be directly imported. 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
D2931: thirdparty: allow zope.interface.advice to be lazily imported
This revision was automatically updated to reflect the committed changes. Closed by commit rHG49630e75635d: thirdparty: allow zope.interface.advice to be lazily imported (authored by indygreg, committed by ). REPOSITORY rHG Mercurial CHANGES SINCE LAST UPDATE https://phab.mercurial-scm.org/D2931?vs=7244=7398 REVISION DETAIL https://phab.mercurial-scm.org/D2931 AFFECTED FILES mercurial/thirdparty/zope/interface/declarations.py CHANGE DETAILS diff --git a/mercurial/thirdparty/zope/interface/declarations.py b/mercurial/thirdparty/zope/interface/declarations.py --- a/mercurial/thirdparty/zope/interface/declarations.py +++ b/mercurial/thirdparty/zope/interface/declarations.py @@ -34,7 +34,7 @@ from types import ModuleType import weakref -from .advice import addClassAdvisor +from . import advice as advicemod from .interface import InterfaceClass from .interface import SpecificationBase from .interface import Specification @@ -451,7 +451,7 @@ raise TypeError(name+" can be used only once in a class definition.") locals['__implements_advice_data__'] = interfaces, classImplements -addClassAdvisor(_implements_advice, depth=3) +advicemod.addClassAdvisor(_implements_advice, depth=3) def implements(*interfaces): """Declare interfaces implemented by instances of a class @@ -732,7 +732,7 @@ locals["__provides__"] = _normalizeargs(interfaces) -addClassAdvisor(_classProvides_advice, depth=2) +advicemod.addClassAdvisor(_classProvides_advice, depth=2) def _classProvides_advice(cls): # This entire approach is invalid under Py3K. Don't even try to fix 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
D2929: thirdparty: don't make zope a namespace package
This revision was automatically updated to reflect the committed changes. Closed by commit rHG338367d44d34: thirdparty: dont make zope a namespace package (authored by indygreg, committed by ). REPOSITORY rHG Mercurial CHANGES SINCE LAST UPDATE https://phab.mercurial-scm.org/D2929?vs=7242=7395 REVISION DETAIL https://phab.mercurial-scm.org/D2929 AFFECTED FILES mercurial/thirdparty/zope/__init__.py CHANGE DETAILS diff --git a/mercurial/thirdparty/zope/__init__.py b/mercurial/thirdparty/zope/__init__.py --- a/mercurial/thirdparty/zope/__init__.py +++ b/mercurial/thirdparty/zope/__init__.py @@ -1,7 +0,0 @@ -# this is a namespace package -try: -import pkg_resources -pkg_resources.declare_namespace(__name__) -except ImportError: -import pkgutil -__path__ = pkgutil.extend_path(__path__, __name__) 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
D2972: tests: ignore zope packages when running pyflakes
This revision was automatically updated to reflect the committed changes. Closed by commit rHG559069689121: tests: ignore zope packages when running pyflakes (authored by indygreg, committed by ). REPOSITORY rHG Mercurial CHANGES SINCE LAST UPDATE https://phab.mercurial-scm.org/D2972?vs=7401=7403 REVISION DETAIL https://phab.mercurial-scm.org/D2972 AFFECTED FILES tests/test-check-pyflakes.t CHANGE DETAILS diff --git a/tests/test-check-pyflakes.t b/tests/test-check-pyflakes.t --- a/tests/test-check-pyflakes.t +++ b/tests/test-check-pyflakes.t @@ -17,6 +17,7 @@ > -X hgext/fsmonitor/pywatchman \ > -X mercurial/pycompat.py -X contrib/python-zstandard \ > -X mercurial/thirdparty/cbor \ + > -X mercurial/thirdparty/zope \ > 2>/dev/null \ > | xargs pyflakes 2>/dev/null | "$TESTDIR/filterpyflakes.py" 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
D2973: narrow: use repo.local() instead of isinstance()
martinvonz created this revision. Herald added a reviewer: durin42. Herald added a subscriber: mercurial-devel. Herald added a reviewer: hg-reviewers. REPOSITORY rHG Mercurial REVISION DETAIL https://phab.mercurial-scm.org/D2973 AFFECTED FILES hgext/narrow/__init__.py CHANGE DETAILS diff --git a/hgext/narrow/__init__.py b/hgext/narrow/__init__.py --- a/hgext/narrow/__init__.py +++ b/hgext/narrow/__init__.py @@ -71,7 +71,7 @@ def reposetup(ui, repo): """Wraps local repositories with narrow repo support.""" -if not isinstance(repo, localrepo.localrepository): +if not repo.local(): return narrowrepo.wraprepo(repo) To: martinvonz, durin42, #hg-reviewers Cc: mercurial-devel ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
D2972: tests: ignore zope packages when running pyflakes
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/D2972 AFFECTED FILES tests/test-check-pyflakes.t CHANGE DETAILS diff --git a/tests/test-check-pyflakes.t b/tests/test-check-pyflakes.t --- a/tests/test-check-pyflakes.t +++ b/tests/test-check-pyflakes.t @@ -17,6 +17,7 @@ > -X hgext/fsmonitor/pywatchman \ > -X mercurial/pycompat.py -X contrib/python-zstandard \ > -X mercurial/thirdparty/cbor \ + > -X mercurial/thirdparty/zope \ > 2>/dev/null \ > | xargs pyflakes 2>/dev/null | "$TESTDIR/filterpyflakes.py" 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
D2970: context: set repo property in basectx
indygreg added a comment. I mean accidentally pushed to Phabricator after the queuing. The queueing was correct. REPOSITORY rHG Mercurial REVISION DETAIL https://phab.mercurial-scm.org/D2970 To: martinvonz, #hg-reviewers, indygreg Cc: mercurial-devel ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
D2970: context: set repo property in basectx
indygreg added a comment. I accidentally pushed this. Derp. REPOSITORY rHG Mercurial REVISION DETAIL https://phab.mercurial-scm.org/D2970 To: martinvonz, #hg-reviewers, indygreg Cc: mercurial-devel ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
D2928: thirdparty: vendor zope.interface 4.4.3
This revision was automatically updated to reflect the committed changes. Closed by commit rHG943d77fc07a3: thirdparty: vendor zope.interface 4.4.3 (authored by indygreg, committed by ). REPOSITORY rHG Mercurial CHANGES SINCE LAST UPDATE https://phab.mercurial-scm.org/D2928?vs=7241=7396 REVISION DETAIL https://phab.mercurial-scm.org/D2928 AFFECTED FILES mercurial/thirdparty/zope/__init__.py mercurial/thirdparty/zope/interface/LICENSE.txt mercurial/thirdparty/zope/interface/__init__.py mercurial/thirdparty/zope/interface/_compat.py mercurial/thirdparty/zope/interface/_flatten.py mercurial/thirdparty/zope/interface/_zope_interface_coptimizations.c mercurial/thirdparty/zope/interface/adapter.py mercurial/thirdparty/zope/interface/advice.py mercurial/thirdparty/zope/interface/common/__init__.py mercurial/thirdparty/zope/interface/common/idatetime.py mercurial/thirdparty/zope/interface/common/interfaces.py mercurial/thirdparty/zope/interface/common/mapping.py mercurial/thirdparty/zope/interface/common/sequence.py mercurial/thirdparty/zope/interface/declarations.py mercurial/thirdparty/zope/interface/document.py mercurial/thirdparty/zope/interface/exceptions.py mercurial/thirdparty/zope/interface/interface.py mercurial/thirdparty/zope/interface/interfaces.py mercurial/thirdparty/zope/interface/registry.py mercurial/thirdparty/zope/interface/ro.py mercurial/thirdparty/zope/interface/verify.py 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
D2970: context: set repo property in basectx
indygreg updated this revision to Diff 7394. REPOSITORY rHG Mercurial CHANGES SINCE LAST UPDATE https://phab.mercurial-scm.org/D2970?vs=7393=7394 REVISION DETAIL https://phab.mercurial-scm.org/D2970 AFFECTED FILES mercurial/context.py CHANGE DETAILS diff --git a/mercurial/context.py b/mercurial/context.py --- a/mercurial/context.py +++ b/mercurial/context.py @@ -63,6 +63,9 @@ memctx: a context that represents changes in-memory and can also be committed.""" +def __init__(self, repo): +self._repo = repo + def __bytes__(self): return short(self.node()) @@ -406,10 +409,10 @@ the repo.""" def __init__(self, repo, changeid='.'): """changeid is a revision number, node, or tag""" +super(changectx, self).__init__(repo) if changeid == '': changeid = '.' -self._repo = repo try: if isinstance(changeid, int): @@ -1134,7 +1137,7 @@ wants the ability to commit, e.g. workingctx or memctx.""" def __init__(self, repo, text="", user=None, date=None, extra=None, changes=None): -self._repo = repo +super(committablectx, self).__init__(repo) self._rev = None self._node = None self._text = text @@ -1818,7 +1821,6 @@ def __init__(self, repo): super(overlayworkingctx, self).__init__(repo) -self._repo = repo self.clean() def setbase(self, wrappedctx): To: martinvonz, #hg-reviewers, indygreg Cc: mercurial-devel ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
D2933: repository: define interface for local repositories
This revision was automatically updated to reflect the committed changes. indygreg marked 2 inline comments as done. Closed by commit rHG0dfb5672f015: repository: define interface for local repositories (authored by indygreg, committed by ). REPOSITORY rHG Mercurial CHANGES SINCE LAST UPDATE https://phab.mercurial-scm.org/D2933?vs=7246=7400 REVISION DETAIL https://phab.mercurial-scm.org/D2933 AFFECTED FILES mercurial/localrepo.py mercurial/repository.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 @@ -2,16 +2,27 @@ from __future__ import absolute_import, print_function +import os + +from mercurial.thirdparty.zope import ( +interface as zi, +) +from mercurial.thirdparty.zope.interface import ( +verify as ziverify, +) from mercurial import ( bundlerepo, httppeer, localrepo, +repository, sshpeer, statichttprepo, ui as uimod, unionrepo, ) +rootdir = os.path.normpath(os.path.join(os.path.dirname(__file__), '..')) + def checkobject(o): """Verify a constructed object conforms to interface rules. @@ -41,6 +52,30 @@ print('public attributes not in abstract interface: %s.%s' % ( name, attr)) +def checkzobject(o): +"""Verify an object with a zope interface.""" +ifaces = zi.providedBy(o) +if not ifaces: +print('%r does not provide any zope interfaces' % o) +return + +# Run zope.interface's built-in verification routine. This verifies that +# everything that is supposed to be present is present. +for iface in ifaces: +ziverify.verifyObject(iface, o) + +# Now verify that the object provides no extra public attributes that +# aren't declared as part of interfaces. +allowed = set() +for iface in ifaces: +allowed |= set(iface.names(all=True)) + +public = {a for a in dir(o) if not a.startswith('_')} + +for attr in sorted(public - allowed): +print('public attribute not declared in interfaces: %s.%s' % ( +o.__class__.__name__, attr)) + # Facilitates testing localpeer. class dummyrepo(object): def __init__(self): @@ -68,6 +103,8 @@ def main(): ui = uimod.ui() +# Needed so we can open a local repo with obsstore without a warning. +ui.setconfig('experimental', 'evolution.createmarkers', True) checkobject(badpeer()) checkobject(httppeer.httppeer(None, None, None, dummyopener())) @@ -80,4 +117,9 @@ checkobject(statichttprepo.statichttppeer(dummyrepo())) checkobject(unionrepo.unionpeer(dummyrepo())) +ziverify.verifyClass(repository.completelocalrepository, + localrepo.localrepository) +repo = localrepo.localrepository(ui, rootdir) +checkzobject(repo) + main() diff --git a/mercurial/repository.py b/mercurial/repository.py --- a/mercurial/repository.py +++ b/mercurial/repository.py @@ -10,6 +10,9 @@ import abc from .i18n import _ +from .thirdparty.zope import ( +interface as zi, +) from . import ( error, ) @@ -266,3 +269,360 @@ class legacypeer(peer, _baselegacywirecommands): """peer but with support for legacy wire protocol commands.""" + +class completelocalrepository(zi.Interface): +"""Monolithic interface for local repositories. + +This currently captures the reality of things - not how things should be. +""" + +supportedformats = zi.Attribute( +"""Set of requirements that apply to stream clone. + +This is actually a class attribute and is shared among all instances. +""") + +openerreqs = zi.Attribute( +"""Set of requirements that are passed to the opener. + +This is actually a class attribute and is shared among all instances. +""") + +supported = zi.Attribute( +"""Set of requirements that this repo is capable of opening.""") + +requirements = zi.Attribute( +"""Set of requirements this repo uses.""") + +filtername = zi.Attribute( +"""Name of the repoview that is active on this repo.""") + +wvfs = zi.Attribute( +"""VFS used to access the working directory.""") + +vfs = zi.Attribute( +"""VFS rooted at the .hg directory. + +Used to access repository data not in the store. +""") + +svfs = zi.Attribute( +"""VFS rooted at the store. + +Used to access repository data in the store. Typically .hg/store. +But can point elsewhere if the store is shared. +""") + +root = zi.Attribute( +"""Path to the root of the working directory.""") + +path = zi.Attribute( +"""Path to the .hg directory.""") + +origroot = zi.Attribute( +"""The filesystem path that was used to construct the repo.""") + +auditor = zi.Attribute( +"""A pathauditor for the working directory. + +
D2957: infinitepush: don't wrap bundle2.processparts while calling `hg unbundle`
indygreg accepted this revision. indygreg added a comment. This revision is now accepted and ready to land. The next patch adds test coverage. So I think this is fine. A follow-up to make this less hacky (if possible) would be appreciated, but isn't required. REPOSITORY rHG Mercurial REVISION DETAIL https://phab.mercurial-scm.org/D2957 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
D2957: infinitepush: don't wrap bundle2.processparts while calling `hg unbundle`
indygreg requested changes to this revision. indygreg added a comment. This revision now requires changes to proceed. Can the `op` argument be used instead? Also, given the hackiness of this, I'd feel much better if there were test coverage for `hg unbundle` continuing to work with this extension enabled. REPOSITORY rHG Mercurial REVISION DETAIL https://phab.mercurial-scm.org/D2957 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
D2970: context: set repo property in basectx
This revision was automatically updated to reflect the committed changes. Closed by commit rHGfbe34945220d: context: set repo property in basectx (authored by martinvonz, committed by ). REPOSITORY rHG Mercurial CHANGES SINCE LAST UPDATE https://phab.mercurial-scm.org/D2970?vs=7372=7393 REVISION DETAIL https://phab.mercurial-scm.org/D2970 AFFECTED FILES mercurial/context.py CHANGE DETAILS diff --git a/mercurial/context.py b/mercurial/context.py --- a/mercurial/context.py +++ b/mercurial/context.py @@ -63,6 +63,9 @@ memctx: a context that represents changes in-memory and can also be committed.""" +def __init__(self, repo): +self._repo = repo + def __bytes__(self): return short(self.node()) @@ -406,10 +409,10 @@ the repo.""" def __init__(self, repo, changeid='.'): """changeid is a revision number, node, or tag""" +super(changectx, self).__init__(repo) if changeid == '': changeid = '.' -self._repo = repo try: if isinstance(changeid, int): @@ -1134,7 +1137,7 @@ wants the ability to commit, e.g. workingctx or memctx.""" def __init__(self, repo, text="", user=None, date=None, extra=None, changes=None): -self._repo = repo +super(committablectx, self).__init__(repo) self._rev = None self._node = None self._text = text @@ -1818,7 +1821,6 @@ def __init__(self, repo): super(overlayworkingctx, self).__init__(repo) -self._repo = repo self.clean() def setbase(self, wrappedctx): To: martinvonz, #hg-reviewers, indygreg Cc: mercurial-devel ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
D2969: context: move reuse of context object to repo.__getitem__ (API)
This revision was automatically updated to reflect the committed changes. Closed by commit rHGbb47dc2f71a0: context: move reuse of context object to repo.__getitem__ (API) (authored by martinvonz, committed by ). REPOSITORY rHG Mercurial CHANGES SINCE LAST UPDATE https://phab.mercurial-scm.org/D2969?vs=7371=7392 REVISION DETAIL https://phab.mercurial-scm.org/D2969 AFFECTED FILES mercurial/context.py mercurial/localrepo.py CHANGE DETAILS diff --git a/mercurial/localrepo.py b/mercurial/localrepo.py --- a/mercurial/localrepo.py +++ b/mercurial/localrepo.py @@ -782,6 +782,8 @@ def __getitem__(self, changeid): if changeid is None: return context.workingctx(self) +if isinstance(changeid, context.basectx): +return changeid if isinstance(changeid, slice): # wdirrev isn't contiguous so the slice shouldn't include it return [context.changectx(self, i) diff --git a/mercurial/context.py b/mercurial/context.py --- a/mercurial/context.py +++ b/mercurial/context.py @@ -62,11 +62,6 @@ be committed, memctx: a context that represents changes in-memory and can also be committed.""" -def __new__(cls, repo, changeid='', *args, **kwargs): -if isinstance(changeid, basectx): -return changeid - -return super(basectx, cls).__new__(cls) def __bytes__(self): return short(self.node()) @@ -412,11 +407,6 @@ def __init__(self, repo, changeid='.'): """changeid is a revision number, node, or tag""" -# since basectx.__new__ already took care of copying the object, we -# don't need to do anything in __init__, so we just exit here -if isinstance(changeid, basectx): -return - if changeid == '': changeid = '.' self._repo = repo @@ -2486,9 +2476,6 @@ dateutil.parsedate() and defaults to current date, extra is a dictionary of metadata or is left empty. """ -def __new__(cls, repo, originalctx, *args, **kwargs): -return super(metadataonlyctx, cls).__new__(cls, repo) - def __init__(self, repo, originalctx, parents=None, text=None, user=None, date=None, extra=None, editor=False): if text is None: To: martinvonz, #hg-reviewers, indygreg Cc: indygreg, yuja, smf, mercurial-devel ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
D2969: context: move reuse of context object to repo.__getitem__ (API)
indygreg accepted this revision. indygreg added a comment. This revision is now accepted and ready to land. That's 2 of us who think this is a good idea. I'm going to queue it. If @smf knows of a reason why this is bad, we can always drop it or revert it. REPOSITORY rHG Mercurial REVISION DETAIL https://phab.mercurial-scm.org/D2969 To: martinvonz, #hg-reviewers, indygreg Cc: indygreg, yuja, smf, mercurial-devel ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
D2968: memctx: create parent contexts using "repo[p]" syntax
This revision was automatically updated to reflect the committed changes. Closed by commit rHG05ff1a155a21: memctx: create parent contexts using repo[p] syntax (authored by martinvonz, committed by ). REPOSITORY rHG Mercurial CHANGES SINCE LAST UPDATE https://phab.mercurial-scm.org/D2968?vs=7370=7391 REVISION DETAIL https://phab.mercurial-scm.org/D2968 AFFECTED FILES mercurial/context.py CHANGE DETAILS diff --git a/mercurial/context.py b/mercurial/context.py --- a/mercurial/context.py +++ b/mercurial/context.py @@ -2284,7 +2284,7 @@ self._node = None parents = [(p or nullid) for p in parents] p1, p2 = parents -self._parents = [changectx(self._repo, p) for p in (p1, p2)] +self._parents = [self._repo[p] for p in (p1, p2)] files = sorted(set(files)) self._files = files if branch is not None: To: martinvonz, #hg-reviewers, indygreg Cc: mercurial-devel ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
D2967: context: avoid using a context object as a changeid
This revision was automatically updated to reflect the committed changes. Closed by commit rHGdaef13da66fe: context: avoid using a context object as a changeid (authored by martinvonz, committed by ). REPOSITORY rHG Mercurial CHANGES SINCE LAST UPDATE https://phab.mercurial-scm.org/D2967?vs=7369=7390 REVISION DETAIL https://phab.mercurial-scm.org/D2967 AFFECTED FILES mercurial/localrepo.py mercurial/merge.py CHANGE DETAILS diff --git a/mercurial/merge.py b/mercurial/merge.py --- a/mercurial/merge.py +++ b/mercurial/merge.py @@ -561,7 +561,7 @@ fcd = self._filectxorabsent(hash, wctx, dfile) fco = self._filectxorabsent(onode, octx, ofile) # TODO: move this to filectxorabsent -fca = self._repo.filectx(afile, fileid=anode, changeid=actx) +fca = self._repo.filectx(afile, fileid=anode, changectx=actx) # "premerge" x flags flo = fco.flags() fla = fca.flags() diff --git a/mercurial/localrepo.py b/mercurial/localrepo.py --- a/mercurial/localrepo.py +++ b/mercurial/localrepo.py @@ -1086,10 +1086,11 @@ if f not in pctx and s not in pctx: self.dirstate.copy(None, f) -def filectx(self, path, changeid=None, fileid=None): +def filectx(self, path, changeid=None, fileid=None, changectx=None): """changeid can be a changeset revision, node, or tag. fileid can be a file revision or node.""" -return context.filectx(self, path, changeid, fileid) +return context.filectx(self, path, changeid, fileid, + changectx=changectx) def getcwd(self): return self.dirstate.getcwd() To: martinvonz, #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
D2966: context: remove unwanted assignments in basectx.__new__() (API)
This revision was automatically updated to reflect the committed changes. Closed by commit rHGd7f3fdab94c4: context: remove unwanted assignments in basectx.__new__() (API) (authored by martinvonz, committed by ). REPOSITORY rHG Mercurial CHANGES SINCE LAST UPDATE https://phab.mercurial-scm.org/D2966?vs=7368=7389 REVISION DETAIL https://phab.mercurial-scm.org/D2966 AFFECTED FILES mercurial/context.py CHANGE DETAILS diff --git a/mercurial/context.py b/mercurial/context.py --- a/mercurial/context.py +++ b/mercurial/context.py @@ -66,13 +66,7 @@ if isinstance(changeid, basectx): return changeid -o = super(basectx, cls).__new__(cls) - -o._repo = repo -o._rev = nullrev -o._node = nullid - -return o +return super(basectx, cls).__new__(cls) def __bytes__(self): return short(self.node()) To: martinvonz, #hg-reviewers, indygreg Cc: mercurial-devel ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel