D231: httppeer: add support for httppostargs when we're sending a file
martinvonz added inline comments. INLINE COMMENTS > httppeer.py:95 > +raise ValueError( > +'fileprepender only supports file objects that ' > +'have a length but this one does not:', type(f), f) I'm guessing 'fileprepender' here and a few placed below is the old name for '_multifile' (so please update) > httppeer.py:96 > +'fileprepender only supports file objects that ' > +'have a length but this one does not:', type(f), f) > +self._fileobjs = fileobjs It doesn't matter much since it's just a programming error if it happens, but how will these arguments to ValueError be rendered? > httppeer.py:105 > +def read(self, amt=None): > +if not amt: > +return ''.join(f.read() for f in self._fileobjs) i read that negative amount means the same thing (read all). do we care to follow that contract here? > httppeer.py:111 > +got = len(parts[-1]) > +if got < amt: > +self._index += 1 nit: i think this can be "if got <= amt" to avoid an unnecessary 0-length read the next time _multifile.read() (and it does look like that will be the normal case, that the reader will read exactly the size of the first "file" first) > httppeer.py:125 > +'could be fixed if you need it') > +for f in self._fileobjs: > +f.seek(0) also need to set self._index=0, no? > httppeer.py:193 > strargs = urlreq.urlencode(sorted(args.items())) > if strargs: > if not data: Nit: to reduce indentation, it looks like you can change the condition above to "if postargsok and args" instead (because bool(strargs) == bool(args) AFAICT) REPOSITORY rHG Mercurial REVISION DETAIL https://phab.mercurial-scm.org/D231 To: durin42, #hg-reviewers Cc: martinvonz, mercurial-devel ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
[PATCH] contrib: add check for use of admonitions and its validity
# HG changeset patch # User Rishabh Madan# Date 1501903168 -19800 # Sat Aug 05 08:49:28 2017 +0530 # Node ID cc695f1458baf2c39ffdec4a1256a93fd659d62d # Parent 609606d217659e0a6c1cf6f907b6512be5340e57 contrib: add check for use of admonitions and its validity While using releasenotes extension, we will be using admonitions in commit messages. This check will look for an admonition within the message. If it exists, it will verify if it is stated under default or custom admonition. The check fails if the admonition is not present in any of them. diff -r 609606d21765 -r cc695f1458ba contrib/check-commit --- a/contrib/check-commit Thu Jul 20 01:30:41 2017 -0700 +++ b/contrib/check-commit Sat Aug 05 08:49:28 2017 +0530 @@ -21,9 +21,16 @@ import re import sys +from mercurial import ( +config, +hg, +ui as uimod, +) + commitheader = r"^(?:# [^\n]*\n)*" afterheader = commitheader + r"(?!#)" beforepatch = afterheader + r"(?!\n(?!@@))" +admonitioncheck = r"\.\. ([a-zA-Z0-9_]+)::" errors = [ (beforepatch + r".*[(]bc[)]", "(BC) needs to be uppercase"), @@ -59,6 +66,7 @@ exitcode = 0 printed = node is None hits = [] +exitcode = checkadmonition(commit, node) signtag = (afterheader + r'Added (tag [^ ]+|signature) for changeset [a-f0-9]{12}') if re.search(signtag, commit): @@ -95,13 +103,38 @@ def readcommit(node): return os.popen("hg export %s" % node).read() +def getcustomadmonitions(node): +repo = hg.repository(uimod.ui(), '.') +ctx = repo[node] +p = config.config() + +def read(f, sections=None, remap=None): +if f in ctx: +data = ctx[f].data() +p.parse(f, data, sections, remap, read) + +if '.hgreleasenotes' in ctx: +read('.hgreleasenotes') +return p['sections'].keys() + +def checkadmonition(commit, node=None): +admonitions = ["fix", "feature", "bc", "api", "perf"] +x = re.search(admonitioncheck, commit) +if x: +if node: +admonitions += getcustomadmonitions(node) +if x.group(1) in admonitions: +return 0 +else: +print("admonition: %s is invalid" % x.group(1)) +return 1 + if __name__ == "__main__": exitcode = 0 node = os.environ.get("HG_NODE") - if node: commit = readcommit(node) -exitcode = checkcommit(commit) +exitcode = checkcommit(commit, node) elif sys.argv[1:]: for node in sys.argv[1:]: exitcode |= checkcommit(readcommit(node), node) ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
[PATCH 1 of 2 v8] releasenotes: add import check for fuzzywuzzy
# HG changeset patch # User Rishabh Madan# Date 1501317386 -19800 # Sat Jul 29 14:06:26 2017 +0530 # Node ID 1d79b04c402f3f431ca052b677b1021ddd93a10e # Parent 9a944e908ecf9ac3aabf30a24406513370eeebe7 releasenotes: add import check for fuzzywuzzy This patch adds the has_fuzzywuzzy for import check of external dependency fuzzywuzzy. diff -r 9a944e908ecf -r 1d79b04c402f tests/hghave.py --- a/tests/hghave.py Tue Jul 18 23:04:08 2017 +0530 +++ b/tests/hghave.py Sat Jul 29 14:06:26 2017 +0530 @@ -652,3 +652,12 @@ @check("fsmonitor", "running tests with fsmonitor") def has_fsmonitor(): return 'HGFSMONITOR_TESTS' in os.environ + +@check("fuzzywuzzy", "Fuzzy string matching library") +def has_fuzzywuzzy(): +try: +import fuzzywuzzy +fuzzywuzzy.__version__ +return True +except ImportError: +return False ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
[PATCH 2 of 2 v8] releasenotes: add similarity check function to compare incoming notes
# HG changeset patch # User Rishabh Madan# Date 1501890936 -19800 # Sat Aug 05 05:25:36 2017 +0530 # Node ID 4121eab826799f3a257eb1fe26015583b36bbb66 # Parent 1d79b04c402f3f431ca052b677b1021ddd93a10e releasenotes: add similarity check function to compare incoming notes It is possible that the incoming note fragments have some similar content as the existing release notes. In case of a bug fix, we match for issue in the existing notes. For other general cases, it makes use of fuzzywuzzy library to get a similarity score. If the score is above a certain threshold, we ignore the fragment, otherwise add it. But the score might be misleading for small commit messages. So, it uses similarity function only if the length of string (in words) is above a certain value. The patch adds tests related to its usage. But it needs improvement in the sense of combining incoming notes. We can use interactive mode for adding notes. Maybe we can do this if similarity is under a certain range. diff -r 1d79b04c402f -r 4121eab82679 hgext/releasenotes.py --- a/hgext/releasenotes.py Sat Jul 29 14:06:26 2017 +0530 +++ b/hgext/releasenotes.py Sat Aug 05 05:25:36 2017 +0530 @@ -14,6 +14,7 @@ from __future__ import absolute_import import errno +import fuzzywuzzy.fuzz as fuzz import re import sys import textwrap @@ -46,6 +47,7 @@ ] RE_DIRECTIVE = re.compile('^\.\. ([a-zA-Z0-9_]+)::\s*([^$]+)?$') +RE_ISSUE = r'\bissue ?[0-9]{4,6}(?![0-9])\b' BULLET_SECTION = _('Other Changes') @@ -92,6 +94,8 @@ This is used to combine multiple sources of release notes together. """ for section in other: +existingnotes = converttitled(self.titledforsection(section)) + \ +convertnontitled(self.nontitledforsection(section)) for title, paragraphs in other.titledforsection(section): if self.hastitledinsection(section, title): # TODO prompt for resolution if different and running in @@ -100,16 +104,32 @@ (title, section)) continue -# TODO perform similarity comparison and try to match against -# existing. +incoming_str = converttitled([(title, paragraphs)])[0] +if section == 'fix': +issue = getissuenum(incoming_str) +if issue: +if findissue(ui, existingnotes, issue): +continue + +if similar(ui, existingnotes, incoming_str): +continue + self.addtitleditem(section, title, paragraphs) for paragraphs in other.nontitledforsection(section): if paragraphs in self.nontitledforsection(section): continue -# TODO perform similarily comparison and try to match against -# existing. +incoming_str = convertnontitled([paragraphs])[0] +if section == 'fix': +issue = getissuenum(incoming_str) +if issue: +if findissue(ui, existingnotes, issue): +continue + +if similar(ui, existingnotes, incoming_str): +continue + self.addnontitleditem(section, paragraphs) class releasenotessections(object): @@ -136,6 +156,78 @@ return None +def converttitled(titledparagraphs): +""" +Convert titled paragraphs to strings +""" +string_list = [] +for title, paragraphs in titledparagraphs: +lines = [] +for para in paragraphs: +lines.extend(para) +string_list.append(' '.join(lines)) +return string_list + +def convertnontitled(nontitledparagraphs): +""" +Convert non-titled bullets to strings +""" +string_list = [] +for paragraphs in nontitledparagraphs: +lines = [] +for para in paragraphs: +lines.extend(para) +string_list.append(' '.join(lines)) +return string_list + +def getissuenum(incoming_str): +""" +Returns issue number from the incoming string if it exists +""" +issue = re.search(RE_ISSUE, incoming_str, re.IGNORECASE) +if issue: +issue = issue.group() +return issue + + +def findissue(ui, existing, issue): +""" +Returns true if issue number already exists in notes. +""" +if any(issue in s for s in existing): +ui.write(_("\"%s\" already exists in notes; " + "ignoring\n") % issue) +return True +else: +return False + +def similar(ui, existing, incoming_str): +""" +Returns true if similar note found in existing notes. +""" +if len(incoming_str.split()) > 10: +merge = similaritycheck(incoming_str, existing) +if not merge: +ui.write(_("\"%s\" already
Re: [PATCH 2 of 2 v7] releasenotes: add similarity check function to compare incoming notes
On Thu, Aug 3, 2017 at 6:49 PM, Yuya Nishiharawrote: > On Tue, 01 Aug 2017 16:37:42 +0530, Rishabh Madan wrote: > > # HG changeset patch > > # User Rishabh Madan > > # Date 1501585562 -19800 > > # Tue Aug 01 16:36:02 2017 +0530 > > # Node ID be3b6b414d443412d5df53ddbf3e80192b6311cc > > # Parent 1d79b04c402f3f431ca052b677b1021ddd93a10e > > releasenotes: add similarity check function to compare incoming notes > > The series seems getting better, thanks. > > > -# TODO perform similarity comparison and try to match > against > > -# existing. > > +incoming_str = converttitled([(title, paragraphs)])[0] > > > +if section == 'fix': > > +issue = getissuenum(incoming_str) > > +if issue: > > +if findissue(ui, existingnotes, issue): > > +continue > > + > > +if similar(ui, existingnotes, incoming_str): > > +continue > > > + > > self.addtitleditem(section, title, paragraphs) > > > > for paragraphs in other.nontitledforsection(section): > > if paragraphs in self.nontitledforsection(section): > > continue > > > > -# TODO perform similarily comparison and try to match > against > > -# existing. > > +incoming_str = convertnontitled([paragraphs])[0] > > > +if section == 'fix': > > +issue = getissuenum(incoming_str) > > +if issue: > > +if findissue(ui, existingnotes, issue): > > +continue > > + > > +if similar(ui, existingnotes, incoming_str): > > +continue > > Optionally these similarity comparison logic could be factored out to a > helper > function or method. > I think that rendering them to a helper function would lead us to the same problem of managing titled/non-titled notes. > > > +def converttitled(titledparagraphs): > > +""" > > +Convert titled paragraphs to strings > > +""" > > +string_list = [] > > +str = "" > > +for title, paragraphs in titledparagraphs: > > +for para in paragraphs: > > +str = str.join(para) > > +string_list.append(str) > > +return string_list > > str was initially a separator, but is overwritten by the result. Perhaps > this function needs to join a list of all lines by ' ' or '\n' ? > > lines = [] > for para in paragraphs: > lines.extend(para) > string_list.append(' '.join(lines)) > > Thanks for pointing out. I'll correct this thing. > > +def convertnontitled(nontitledparagraphs): > > +""" > > +Convert non-titled bullets to strings > > +""" > > +string_list = [] > > +str = "" > > +for paragraphs in nontitledparagraphs: > > +for para in paragraphs: > > +str = str.join(para) > > +string_list.append(str) > > +return string_list > > Same here. ᐧ ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
D127: phabricator: add phabupdate command to update status in batch
quark updated this revision to Diff 572. REPOSITORY rHG Mercurial CHANGES SINCE LAST UPDATE https://phab.mercurial-scm.org/D127?vs=557=572 REVISION DETAIL https://phab.mercurial-scm.org/D127 AFFECTED FILES contrib/phabricator.py CHANGE DETAILS diff --git a/contrib/phabricator.py b/contrib/phabricator.py --- a/contrib/phabricator.py +++ b/contrib/phabricator.py @@ -9,7 +9,7 @@ This extension provides a ``phabsend`` command which sends a stack of changesets to Phabricator without amending commit messages, and a ``phabread`` command which prints a stack of revisions in a format suitable -for :hg:`import`. +for :hg:`import`, and a ``phabupdate`` command to update statuses in batch. By default, Phabricator requires ``Test Plan`` which might prevent some changeset from being sent. The requirement could be disabled by changing @@ -799,3 +799,32 @@ spec = ':(%s)' % spec drevs = querydrev(repo, spec) readpatch(repo, drevs, ui.write) + +@command('phabupdate', + [('', 'accept', False, _('accept revisions')), + ('', 'reject', False, _('reject revisions')), + ('', 'abandon', False, _('abandon revisions')), + ('', 'reclaim', False, _('reclaim revisions')), + ('m', 'comment', '', _('comment on the last revision')), + ], _('DREVSPEC [OPTIONS]')) +def phabupdate(ui, repo, spec, **opts): +"""update Differential Revision in batch + +DREVSPEC selects revisions. See :hg:`help phabread` for its usage. +""" +flags = [n for n in 'accept reject abandon reclaim'.split() if opts.get(n)] +if len(flags) > 1: +raise error.Abort(_('%s cannot be used together') % ', '.join(flags)) + +actions = [] +for f in flags: +actions.append({'type': f, 'value': 'true'}) + +drevs = querydrev(repo, spec) +for i, drev in enumerate(drevs): +if i + 1 == len(drevs) and opts.get('comment'): +actions.append({'type': 'comment', 'value': opts['comment']}) +if actions: +params = {'objectIdentifier': drev[r'phid'], + 'transactions': actions} +callconduit(repo, 'differential.revision.edit', params) To: quark, #hg-reviewers Cc: krbullock, mercurial-devel ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
D124: phabricator: change "readpatch" to be more flexible
quark updated this revision to Diff 569. REPOSITORY rHG Mercurial CHANGES SINCE LAST UPDATE https://phab.mercurial-scm.org/D124?vs=554=569 REVISION DETAIL https://phab.mercurial-scm.org/D124 AFFECTED FILES contrib/phabricator.py CHANGE DETAILS diff --git a/contrib/phabricator.py b/contrib/phabricator.py --- a/contrib/phabricator.py +++ b/contrib/phabricator.py @@ -636,15 +636,12 @@ meta[r'parent'] = commit[r'parents'][0] return meta or {} -def readpatch(repo, params, write, stack=False): +def readpatch(repo, drevs, write): """generate plain-text patch readable by 'hg import' -write is usually ui.write. params is passed to "differential.query". If -stack is True, also write dependent patches. +write is usually ui.write. drevs is what "querydrev" returns, results of +"differential.query". """ -# Differential Revisions -drevs = querydrev(repo, params, stack) - # Prefetch hg:meta property for all diffs diffids = sorted(set(max(int(v) for v in drev[r'diffs']) for drev in drevs)) diffs = callconduit(repo, 'differential.querydiffs', {'ids': diffids}) @@ -684,4 +681,5 @@ revid = int(revid.split('/')[-1].replace('D', '')) except ValueError: raise error.Abort(_('invalid Revision ID: %s') % revid) -readpatch(repo, {'ids': [revid]}, ui.write, opts.get('stack')) +drevs = querydrev(repo, {'ids': [revid]}, opts.get('stack')) +readpatch(repo, drevs, ui.write) To: quark, #hg-reviewers, mitrandir Cc: mercurial-devel ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
D126: phabricator: add status to revision query language
quark updated this revision to Diff 571. REPOSITORY rHG Mercurial CHANGES SINCE LAST UPDATE https://phab.mercurial-scm.org/D126?vs=556=571 REVISION DETAIL https://phab.mercurial-scm.org/D126 AFFECTED FILES contrib/phabricator.py CHANGE DETAILS diff --git a/contrib/phabricator.py b/contrib/phabricator.py --- a/contrib/phabricator.py +++ b/contrib/phabricator.py @@ -489,6 +489,13 @@ return True +_knownstatusnames = {'accepted', 'needsreview', 'needsrevision', 'closed', + 'abandoned'} + +def _getstatusname(drev): +"""get normalized status name from a Differential Revision""" +return drev[r'statusName'].replace(' ', '').lower() + # Small language to specify differential revisions. Support symbols: (), :X, # +, and -. @@ -505,19 +512,19 @@ } def _tokenize(text): -text = text.replace(' ', '') # remove space view = memoryview(text) # zero-copy slice -special = '():+-&' +special = '():+-& ' pos = 0 length = len(text) while pos < length: symbol = ''.join(itertools.takewhile(lambda ch: ch not in special, view[pos:])) if symbol: yield ('symbol', symbol, pos) pos += len(symbol) -else: # special char -yield (text[pos], None, pos) +else: # special char, ignore space +if text[pos] != ' ': +yield (text[pos], None, pos) pos += 1 yield ('end', None, pos) @@ -645,15 +652,19 @@ tofetch.update(range(max(1, r - batchsize), r + 1)) if drevs: fetch({r'ids': list(tofetch)}) -getstack(list(ancestordrevs)) +validids = sorted(set(getstack(list(ancestordrevs))) | set(drevs)) # Walk through the tree, return smartsets def walk(tree): op = tree[0] if op == 'symbol': drev = _parsedrev(tree[1]) if drev: return smartset.baseset([drev]) +elif tree[1] in _knownstatusnames: +drevs = [r for r in validids + if _getstatusname(prefetched[r]) == tree[1]] +return smartset.baseset(drevs) else: raise error.Abort(_('unknown symbol: %s') % tree[1]) elif op in {'and_', 'add', 'sub'}: @@ -773,8 +784,13 @@ ``&``, ``(``, ``)`` for complex queries. Prefix ``:`` could be used to select a stack. +``abandoned``, ``accepted``, ``closed``, ``needsreview``, ``needsrevision`` +could be used to filter patches by status. For performance reason, they +only represent a subset of non-status selections and cannot be used alone. + For example, ``:D6+8-(2+D4)`` selects a stack up to D6, plus D8 and exclude -D2 and D4. +D2 and D4. ``:D9 & needsreview`` selects "Needs Review" revisions in a +stack up to D9. If --stack is given, follow dependencies information and read all patches. It is equivalent to the ``:`` operator. To: quark, #hg-reviewers Cc: mercurial-devel ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
D122: phabricator: add --amend option to phabsend
quark updated this revision to Diff 568. REPOSITORY rHG Mercurial CHANGES SINCE LAST UPDATE https://phab.mercurial-scm.org/D122?vs=553=568 REVISION DETAIL https://phab.mercurial-scm.org/D122 AFFECTED FILES contrib/phabricator.py CHANGE DETAILS diff --git a/contrib/phabricator.py b/contrib/phabricator.py --- a/contrib/phabricator.py +++ b/contrib/phabricator.py @@ -38,6 +38,8 @@ from mercurial.node import bin, nullid from mercurial.i18n import _ from mercurial import ( +cmdutil, +context, encoding, error, mdiff, @@ -316,7 +318,7 @@ if not revision: raise error.Abort(_('cannot create revision for %s') % ctx) -return revision +return revision, diff def userphids(repo, names): """convert user names to PHIDs""" @@ -334,6 +336,7 @@ @command('phabsend', [('r', 'rev', [], _('revisions to send'), _('REV')), + ('', 'amend', False, _('update commit messages')), ('', 'reviewer', [], _('specify reviewers')), ('', 'confirm', None, _('ask for confirmation before sending'))], _('REV [OPTIONS]')) @@ -349,18 +352,28 @@ obsstore and tags information so it can figure out whether to update an existing Differential Revision, or create a new one. +If --amend is set, update commit messages so they have the +``Differential Revision`` URL, remove related tags. This is similar to what +arcanist will do, and is more desired in author-push workflows. Otherwise, +use local tags to record the ``Differential Revision`` association. + The --confirm option lets you confirm changesets before sending them. You can also add following to your configuration file to make it default behaviour. [phabsend] confirm = true + +phabsend will check obsstore and the above association to decide whether to +update an existing Differential Revision, or create a new one. """ revs = list(revs) + opts.get('rev', []) revs = scmutil.revrange(repo, revs) if not revs: raise error.Abort(_('phabsend requires at least one changeset')) +if opts.get('amend'): +cmdutil.checkunfinished(repo) confirm = ui.configbool('phabsend', 'confirm') confirm |= bool(opts.get('confirm')) @@ -378,6 +391,9 @@ # {newnode: (oldnode, olddiff, olddrev} oldmap = getoldnodedrevmap(repo, [repo[r].node() for r in revs]) +drevids = [] # [int] +diffmap = {} # {newnode: diff} + # Send patches one by one so we know their Differential Revision IDs and # can provide dependency relationship lastrevid = None @@ -389,28 +405,67 @@ oldnode, olddiff, revid = oldmap.get(ctx.node(), (None, None, None)) if oldnode != ctx.node(): # Create or update Differential Revision -revision = createdifferentialrevision(ctx, revid, lastrevid, - oldnode, olddiff, actions) +revision, diff = createdifferentialrevision( +ctx, revid, lastrevid, oldnode, olddiff, actions) +diffmap[ctx.node()] = diff newrevid = int(revision[r'object'][r'id']) if revid: action = _('updated') else: action = _('created') -# Create a local tag to note the association -tagname = 'D%d' % newrevid -tags.tag(repo, tagname, ctx.node(), message=None, user=None, - date=None, local=True) +# Create a local tag to note the association, if commit message +# does not have it already +m = _differentialrevisiondescre.search(ctx.description()) +if not m or int(m.group(1)) != newrevid: +tagname = 'D%d' % newrevid +tags.tag(repo, tagname, ctx.node(), message=None, user=None, + date=None, local=True) else: # Nothing changed. But still set "newrevid" so the next revision # could depend on this one. newrevid = revid action = _('skipped') ui.write(_('D%s: %s - %s: %s\n') % (newrevid, action, ctx, ctx.description().split('\n')[0])) +drevids.append(newrevid) lastrevid = newrevid +# Update commit messages and remove tags +if opts.get('amend'): +unfi = repo.unfiltered() +drevs = callconduit(repo, 'differential.query', {'ids': drevids}) +with repo.wlock(), repo.lock(), repo.transaction('phabsend'): +wnode = unfi['.'].node() +mapping = {} # {oldnode: [newnode]} +for i, rev in enumerate(revs): +old = unfi[rev] +drevid = drevids[i] +drev = [d for d in drevs if int(d[r'id']) == drevid][0] +newdesc = getdescfromdrev(drev) +# Make sure commit message contain
D125: phabricator: add a small language to query Differential Revisions
quark updated this revision to Diff 570. REPOSITORY rHG Mercurial CHANGES SINCE LAST UPDATE https://phab.mercurial-scm.org/D125?vs=555=570 REVISION DETAIL https://phab.mercurial-scm.org/D125 AFFECTED FILES contrib/phabricator.py CHANGE DETAILS diff --git a/contrib/phabricator.py b/contrib/phabricator.py --- a/contrib/phabricator.py +++ b/contrib/phabricator.py @@ -32,7 +32,9 @@ from __future__ import absolute_import +import itertools import json +import operator import re from mercurial.node import bin, nullid @@ -44,9 +46,11 @@ error, mdiff, obsolete, +parser, patch, registrar, scmutil, +smartset, tags, url as urlmod, util, @@ -485,11 +489,77 @@ return True -def querydrev(repo, params, stack=False): +# Small language to specify differential revisions. Support symbols: (), :X, +# +, and -. + +_elements = { +# token-type: binding-strength, primary, prefix, infix, suffix +'(': (12, None, ('group', 1, ')'), None, None), +':': (8, None, ('ancestors', 8), None, None), +'&': (5, None, None, ('and_', 5), None), +'+': (4, None, None, ('add', 4), None), +'-': (4, None, None, ('sub', 4), None), +')': (0, None, None, None, None), +'symbol': (0, 'symbol', None, None, None), +'end':(0, None, None, None, None), +} + +def _tokenize(text): +text = text.replace(' ', '') # remove space +view = memoryview(text) # zero-copy slice +special = '():+-&' +pos = 0 +length = len(text) +while pos < length: +symbol = ''.join(itertools.takewhile(lambda ch: ch not in special, + view[pos:])) +if symbol: +yield ('symbol', symbol, pos) +pos += len(symbol) +else: # special char +yield (text[pos], None, pos) +pos += 1 +yield ('end', None, pos) + +def _parse(text): +tree, pos = parser.parser(_elements).parse(_tokenize(text)) +if pos != len(text): +raise error.ParseError('invalid token', pos) +return tree + +def _parsedrev(symbol): +"""str -> int or None, ex. 'D45' -> 45; '12' -> 12; 'x' -> None""" +if symbol.startswith('D') and symbol[1:].isdigit(): +return int(symbol[1:]) +if symbol.isdigit(): +return int(symbol) + +def _prefetchdrevs(tree): +"""return ({single-drev-id}, {ancestor-drev-id}) to prefetch""" +drevs = set() +ancestordrevs = set() +op = tree[0] +if op == 'symbol': +r = _parsedrev(tree[1]) +if r: +drevs.add(r) +elif op == 'ancestors': +r, a = _prefetchdrevs(tree[1]) +drevs.update(r) +ancestordrevs.update(r) +ancestordrevs.update(a) +else: +for t in tree[1:]: +r, a = _prefetchdrevs(t) +drevs.update(r) +ancestordrevs.update(a) +return drevs, ancestordrevs + +def querydrev(repo, spec): """return a list of "Differential Revision" dicts -params is the input of "differential.query" API, and is expected to match -just a single Differential Revision. +spec is a string using a simple query language, see docstring in phabread +for details. A "Differential Revision dict" looks like: @@ -526,51 +596,77 @@ "repositoryPHID": "PHID-REPO-hub2hx62ieuqeheznasv", "sourcePath": null } - -If stack is True, return a list of "Differential Revision dict"s in an -order that the latter ones depend on the former ones. Otherwise, return a -list of a unique "Differential Revision dict". """ -prefetched = {} # {id or phid: drev} def fetch(params): """params -> single drev or None""" key = (params.get(r'ids') or params.get(r'phids') or [None])[0] if key in prefetched: return prefetched[key] -# Otherwise, send the request. If we're fetching a stack, be smarter -# and fetch more ids in one batch, even if it could be unnecessary. -batchparams = params -if stack and len(params.get(r'ids', [])) == 1: -i = int(params[r'ids'][0]) -# developer config: phabricator.batchsize -batchsize = repo.ui.configint('phabricator', 'batchsize', 12) -batchparams = {'ids': range(max(1, i - batchsize), i + 1)} -drevs = callconduit(repo, 'differential.query', batchparams) +drevs = callconduit(repo, 'differential.query', params) # Fill prefetched with the result for drev in drevs: prefetched[drev[r'phid']] = drev prefetched[int(drev[r'id'])] = drev if key not in prefetched: raise error.Abort(_('cannot get Differential Revision %r') % params) return prefetched[key] -visited = set() -result = [] -queue = [params] -while queue: -params = queue.pop() -drev = fetch(params) -
D210: pushvars: move fb extension pushvars to core
This revision was automatically updated to reflect the committed changes. Closed by commit rHGdb3dc11356ed: pushvars: move fb extension pushvars to core (authored by pulkit). REPOSITORY rHG Mercurial CHANGES SINCE LAST UPDATE https://phab.mercurial-scm.org/D210?vs=514=567 REVISION DETAIL https://phab.mercurial-scm.org/D210 AFFECTED FILES mercurial/bundle2.py mercurial/commands.py mercurial/exchange.py tests/test-completion.t tests/test-pushvars.t CHANGE DETAILS diff --git a/tests/test-pushvars.t b/tests/test-pushvars.t new file mode 100644 --- /dev/null +++ b/tests/test-pushvars.t @@ -0,0 +1,71 @@ +Setup + + $ PYTHONPATH=$TESTDIR/..:$PYTHONPATH + $ export PYTHONPATH + + $ cat > $TESTTMP/pretxnchangegroup.sh << EOF + > #!/bin/sh + > env | egrep "^HG_USERVAR_(DEBUG|BYPASS_REVIEW)" | sort + > exit 0 + > EOF + $ chmod +x $TESTTMP/pretxnchangegroup.sh + $ cat >> $HGRCPATH << EOF + > [hooks] + > pretxnchangegroup = $TESTTMP/pretxnchangegroup.sh + > [experimental] + > bundle2-exp = true + > EOF + + $ hg init repo + $ hg clone -q repo child + $ cd child + +Test pushing vars to repo with pushvars.server not set + + $ echo b > a + $ hg commit -Aqm a + $ hg push --pushvars "DEBUG=1" --pushvars "BYPASS_REVIEW=true" + pushing to $TESTTMP/repo (glob) + searching for changes + adding changesets + adding manifests + adding file changes + added 1 changesets with 1 changes to 1 files + +Setting pushvars.sever = true and then pushing. + + $ echo [push] >> $HGRCPATH + $ echo "pushvars.server = true" >> $HGRCPATH + $ echo b >> a + $ hg commit -Aqm a + $ hg push --pushvars "DEBUG=1" --pushvars "BYPASS_REVIEW=true" + pushing to $TESTTMP/repo (glob) + searching for changes + adding changesets + adding manifests + adding file changes + added 1 changesets with 1 changes to 1 files + HG_USERVAR_BYPASS_REVIEW=true + HG_USERVAR_DEBUG=1 + +Test pushing var with empty right-hand side + + $ echo b >> a + $ hg commit -Aqm a + $ hg push --pushvars "DEBUG=" + pushing to $TESTTMP/repo (glob) + searching for changes + adding changesets + adding manifests + adding file changes + added 1 changesets with 1 changes to 1 files + HG_USERVAR_DEBUG= + +Test pushing bad vars + + $ echo b >> a + $ hg commit -Aqm b + $ hg push --pushvars "DEBUG" + pushing to $TESTTMP/repo (glob) + abort: unable to parse variable 'DEBUG', should follow 'KEY=VALUE' or 'KEY=' format + [255] diff --git a/tests/test-completion.t b/tests/test-completion.t --- a/tests/test-completion.t +++ b/tests/test-completion.t @@ -228,7 +228,7 @@ log: follow, follow-first, date, copies, keyword, rev, removed, only-merges, user, only-branch, branch, prune, patch, git, limit, no-merges, stat, graph, style, template, include, exclude merge: force, rev, preview, tool pull: update, force, rev, bookmark, branch, ssh, remotecmd, insecure - push: force, rev, bookmark, branch, new-branch, ssh, remotecmd, insecure + push: force, rev, bookmark, branch, new-branch, pushvars, ssh, remotecmd, insecure remove: after, force, subrepos, include, exclude serve: accesslog, daemon, daemon-postexec, errorlog, port, address, prefix, name, web-conf, webdir-conf, pid-file, stdio, cmdserver, templates, style, ipv6, certificate, subrepos status: all, modified, added, removed, deleted, clean, unknown, ignored, no-status, terse, copies, print0, rev, change, include, exclude, subrepos, template diff --git a/mercurial/exchange.py b/mercurial/exchange.py --- a/mercurial/exchange.py +++ b/mercurial/exchange.py @@ -893,6 +893,14 @@ pushop.bkresult = 1 return handlereply +@b2partsgenerator('pushvars', idx=0) +def _getbundlesendvars(pushop, bundler): +'''send shellvars via bundle2''' +if getattr(pushop.repo, '_shellvars', ()): +part = bundler.newpart('pushvars') + +for key, value in pushop.repo._shellvars.iteritems(): +part.addparam(key, value, mandatory=False) def _pushbundle2(pushop): """push data to the remote using bundle2 diff --git a/mercurial/commands.py b/mercurial/commands.py --- a/mercurial/commands.py +++ b/mercurial/commands.py @@ -3970,6 +3970,7 @@ ('b', 'branch', [], _('a specific branch you would like to push'), _('BRANCH')), ('', 'new-branch', False, _('allow pushing a new branch')), +('', 'pushvars', [], _('variables that can be sent to server (ADVANCED)')), ] + remoteopts, _('[-f] [-r REV]... [-e CMD] [--remotecmd CMD] [DEST]')) def push(ui, repo, dest=None, **opts): @@ -4007,6 +4008,25 @@ Please see :hg:`help urls` for important details about ``ssh://`` URLs. If DESTINATION is omitted, a default path will be used. +.. container:: verbose + +The --pushvars option sends strings to the server that become +environment variables prepended with ``HG_USERVAR_``. For example, +``--pushvars ENABLE_FEATURE=true``, provides the server side hooks with +
D229: phabricator: update diff property even if we choose not to create a new diff
This revision was automatically updated to reflect the committed changes. Closed by commit rHGf100354cce52: phabricator: update diff property even if we choose not to create a new diff (authored by quark). REPOSITORY rHG Mercurial CHANGES SINCE LAST UPDATE https://phab.mercurial-scm.org/D229?vs=552=566 REVISION DETAIL https://phab.mercurial-scm.org/D229 AFFECTED FILES contrib/phabricator.py CHANGE DETAILS diff --git a/contrib/phabricator.py b/contrib/phabricator.py --- a/contrib/phabricator.py +++ b/contrib/phabricator.py @@ -255,7 +255,7 @@ callconduit(ctx.repo(), 'differential.setdiffproperty', params) def createdifferentialrevision(ctx, revid=None, parentrevid=None, oldnode=None, - actions=None): + olddiff=None, actions=None): """create or update a Differential Revision If revid is None, create a new Differential Revision, otherwise update @@ -279,6 +279,13 @@ diff = creatediff(ctx) writediffproperties(ctx, diff) transactions.append({'type': 'update', 'value': diff[r'phid']}) +else: +# Even if we don't need to upload a new diff because the patch content +# does not change. We might still need to update its metadata so +# pushers could know the correct node metadata. +assert olddiff +diff = olddiff +writediffproperties(ctx, diff) # Use a temporary summary to set dependency. There might be better ways but # I cannot find them for now. But do not do that if we are updating an @@ -383,7 +390,7 @@ if oldnode != ctx.node(): # Create or update Differential Revision revision = createdifferentialrevision(ctx, revid, lastrevid, - oldnode, actions) + oldnode, olddiff, actions) newrevid = int(revision[r'object'][r'id']) if revid: action = _('updated') To: quark, #hg-reviewers, durin42 Cc: mercurial-devel ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
D121: phabricator: use Phabricator's last node information
This revision was automatically updated to reflect the committed changes. Closed by commit rHG1664406a44d9: phabricator: use Phabricator's last node information (authored by quark). REPOSITORY rHG Mercurial CHANGES SINCE LAST UPDATE https://phab.mercurial-scm.org/D121?vs=550=565 REVISION DETAIL https://phab.mercurial-scm.org/D121 AFFECTED FILES contrib/phabricator.py CHANGE DETAILS diff --git a/contrib/phabricator.py b/contrib/phabricator.py --- a/contrib/phabricator.py +++ b/contrib/phabricator.py @@ -138,28 +138,32 @@ _differentialrevisiontagre = re.compile('\AD([1-9][0-9]*)\Z') _differentialrevisiondescre = re.compile( -'^Differential Revision:\s*(.*)D([1-9][0-9]*)$', re.M) +'^Differential Revision:\s*(?:.*)D([1-9][0-9]*)$', re.M) def getoldnodedrevmap(repo, nodelist): """find previous nodes that has been sent to Phabricator -return {node: (oldnode or None, Differential Revision ID)} +return {node: (oldnode, Differential diff, Differential Revision ID)} for node in nodelist with known previous sent versions, or associated -Differential Revision IDs. +Differential Revision IDs. ``oldnode`` and ``Differential diff`` could +be ``None``. -Examines all precursors and their tags. Tags with format like "D1234" are -considered a match and the node with that tag, and the number after "D" -(ex. 1234) will be returned. +Examines commit messages like "Differential Revision:" to get the +association information. -If tags are not found, examine commit message. The "Differential Revision:" -line could associate this changeset to a Differential Revision. +If such commit message line is not found, examines all precursors and their +tags. Tags with format like "D1234" are considered a match and the node +with that tag, and the number after "D" (ex. 1234) will be returned. + +The ``old node``, if not None, is guaranteed to be the last diff of +corresponding Differential Revision, and exist in the repo. """ url, token = readurltoken(repo) unfi = repo.unfiltered() nodemap = unfi.changelog.nodemap -result = {} # {node: (oldnode or None, drev)} -toconfirm = {} # {node: (oldnode, {precnode}, drev)} +result = {} # {node: (oldnode?, lastdiff?, drev)} +toconfirm = {} # {node: (force, {precnode}, drev)} for node in nodelist: ctx = unfi[node] # For tags like "D123", put them into "toconfirm" to verify later @@ -169,39 +173,49 @@ for tag in unfi.nodetags(n): m = _differentialrevisiontagre.match(tag) if m: -toconfirm[node] = (n, set(precnodes), int(m.group(1))) +toconfirm[node] = (0, set(precnodes), int(m.group(1))) continue -# Check commit message (make sure URL matches) +# Check commit message m = _differentialrevisiondescre.search(ctx.description()) if m: -if m.group(1).rstrip('/') == url.rstrip('/'): -result[node] = (None, int(m.group(2))) -else: -unfi.ui.warn(_('%s: Differential Revision URL ignored - host ' - 'does not match config\n') % ctx) +toconfirm[node] = (1, set(precnodes), int(m.group(1))) # Double check if tags are genuine by collecting all old nodes from # Phabricator, and expect precursors overlap with it. if toconfirm: -confirmed = {} # {drev: {oldnode}} -drevs = [drev for n, precs, drev in toconfirm.values()] -diffs = callconduit(unfi, 'differential.querydiffs', -{'revisionIDs': drevs}) -for diff in diffs.values(): -drev = int(diff[r'revisionID']) -oldnode = bin(encoding.unitolocal(getdiffmeta(diff).get(r'node'))) -if node: -confirmed.setdefault(drev, set()).add(oldnode) -for newnode, (oldnode, precset, drev) in toconfirm.items(): -if bool(precset & confirmed.get(drev, set())): -result[newnode] = (oldnode, drev) -else: +drevs = [drev for force, precs, drev in toconfirm.values()] +alldiffs = callconduit(unfi, 'differential.querydiffs', + {'revisionIDs': drevs}) +getnode = lambda d: bin(encoding.unitolocal( +getdiffmeta(d).get(r'node', ''))) or None +for newnode, (force, precset, drev) in toconfirm.items(): +diffs = [d for d in alldiffs.values() + if int(d[r'revisionID']) == drev] + +# "precursors" as known by Phabricator +phprecset = set(getnode(d) for d in diffs) + +# Ignore if precursors (Phabricator and local repo) do not overlap, +# and force is not set (when commit message says nothing) +if not force and not bool(phprecset & precset):
D219: morestatus: move fb extension to core as '--repo-state' option to status
durin42 requested changes to this revision. durin42 added a comment. This revision now requires changes to proceed. In https://phab.mercurial-scm.org/D219#3755, @martinvonz wrote: > In https://phab.mercurial-scm.org/D219#3661, @quark wrote: > > > I'm thinking about the difference between the deprecated `[defaults]` and `[commands]` (and also `[alias]`) but don't quite get it. It seems people wanting the behavior might just set `alias.status = status -v`, or use `[defaults]`. What's the advantage of using a `[commands]` option? > > > Good point, there's probably no good reason to use [commands] for this. [defaults] has been discouraged, but I don't know if there's a good reason to discourage it (I think it's already ignored when HGPLAIN is in effect). The discouragement is twofold: we didn't used to have HGPLAIN, and it used to be there was no way to un-do the setting of a boolean flag in [defaults]. Both of those limitations are now fixed, so I'm less worried about it overall. That said, I would like a config knob for this, so it can be part of ui.tweakdefaults. > [commands] make sense when there's no command line flag for the behavior, but we do have that here. So if we agree on using --verbose for this, I don't think I see a reason to a special config for it and we can use [defaults] instead. > > Hmm, I just realized there is a somewhat good reason to avoid [defaults]: it applies to *all* options at once. Let me clarify with an example. Let's say your sysadmin has set "defaults.status = --relative" (hypothetical option -- it's currently a config in [commands]) and you want to keep that *and* get verbose status output, you now have to copy the default config from the system hgrc. I don't think I've heard that argument against [defaults] before, but that seems more relevant than the scripting argument (which, again, goes away with HGPLAIN). Or am I mistaken? That's another argument in favor of a config knob IMO. I'm not sure if --verbose should be (ab)used for this, given that we've got --terse. --verbose almost sounds like the opposite of --terse, so it might be confusing. Meditate on that, I guess. (Marking as "Request changes" for now, since we seem largely agreed that --verbose is a decent way to go, and if nobody else is worried about the conceptual overlap with --terse I'm fine with it, especially since I more or less expect this to be on in tweakdefaults soon.) REPOSITORY rHG Mercurial REVISION DETAIL https://phab.mercurial-scm.org/D219 To: pulkit, #hg-reviewers, durin42 Cc: durin42, quark, akushner, martinvonz, durham, mercurial-devel ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
D210: pushvars: move fb extension pushvars to core
durin42 accepted this revision. durin42 added a comment. This revision is now accepted and ready to land. I like this, it opens the doors to some things I've wanted to do for a while. REPOSITORY rHG Mercurial REVISION DETAIL https://phab.mercurial-scm.org/D210 To: pulkit, #hg-reviewers, durin42 Cc: quark, durin42, akushner, mercurial-devel ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
D216: evolution: rename bumped to phase-divergent
This revision was automatically updated to reflect the committed changes. Closed by commit rHG9c27a2891b75: evolution: rename bumped to phase-divergent (authored by lothiraldan). REPOSITORY rHG Mercurial CHANGES SINCE LAST UPDATE https://phab.mercurial-scm.org/D216?vs=499=561 REVISION DETAIL https://phab.mercurial-scm.org/D216 AFFECTED FILES mercurial/commands.py mercurial/context.py mercurial/exchange.py tests/test-obsolete.t CHANGE DETAILS diff --git a/tests/test-obsolete.t b/tests/test-obsolete.t --- a/tests/test-obsolete.t +++ b/tests/test-obsolete.t @@ -207,7 +207,7 @@ $ hg --hidden phase --public 2 $ hg log -G - @ 5:5601fb93a350 (draft bumped) [tip ] add new_3_c + @ 5:5601fb93a350 (draft phase-divergent) [tip ] add new_3_c | | o 2:245bde4270cd (public) [ ] add original_c |/ @@ -224,7 +224,7 @@ the public changeset $ hg log --hidden -r 'bumped()' - 5:5601fb93a350 (draft bumped) [tip ] add new_3_c + 5:5601fb93a350 (draft phase-divergent) [tip ] add new_3_c And that we can't push bumped changeset @@ -239,20 +239,20 @@ $ hg push ../tmpa pushing to ../tmpa searching for changes - abort: push includes bumped changeset: 5601fb93a350! + abort: push includes phase-divergent changeset: 5601fb93a350! [255] Fixing "bumped" situation We need to create a clone of 5 and add a special marker with a flag $ hg summary - parent: 5:5601fb93a350 tip (bumped) + parent: 5:5601fb93a350 tip (phase-divergent) add new_3_c branch: default commit: (clean) update: 1 new changesets, 2 branch heads (merge) phases: 1 draft - bumped: 1 changesets + phase-divergent: 1 changesets $ hg up '5^' 0 files updated, 0 files merged, 1 files removed, 0 files unresolved $ hg revert -ar 5 @@ -914,7 +914,7 @@ changeset: 7:50c51b361e60 user:test date:Thu Jan 01 00:00:00 1970 + - instability: orphan, bumped + instability: orphan, phase-divergent summary: add babar @@ -926,15 +926,15 @@ test the "troubles" templatekw $ hg log -r 'bumped() and unstable()' - 7:50c51b361e60 (draft orphan bumped) [ ] add babar + 7:50c51b361e60 (draft orphan phase-divergent) [ ] add babar test the default cmdline template $ hg log -T default -r 'bumped()' changeset: 7:50c51b361e60 user:test date:Thu Jan 01 00:00:00 1970 + - trouble: orphan, bumped + trouble: orphan, phase-divergent summary: add babar $ hg log -T default -r 'obsolete()' @@ -950,14 +950,14 @@ $ hg up -r 'bumped() and unstable()' 1 files updated, 0 files merged, 1 files removed, 0 files unresolved $ hg summary - parent: 7:50c51b361e60 (orphan, bumped) + parent: 7:50c51b361e60 (orphan, phase-divergent) add babar branch: default commit: (clean) update: 2 new changesets (update) phases: 4 draft orphan: 2 changesets - bumped: 1 changesets + phase-divergent: 1 changesets $ hg up -r 'obsolete()' 0 files updated, 0 files merged, 1 files removed, 0 files unresolved $ hg summary @@ -968,7 +968,7 @@ update: 3 new changesets (update) phases: 4 draft orphan: 2 changesets - bumped: 1 changesets + phase-divergent: 1 changesets Test incoming/outcoming with changesets obsoleted remotely, known locally === diff --git a/mercurial/exchange.py b/mercurial/exchange.py --- a/mercurial/exchange.py +++ b/mercurial/exchange.py @@ -677,9 +677,10 @@ if unfi.obsstore: # this message are here for 80 char limit reason mso = _("push includes obsolete changeset: %s!") +mspd = _("push includes phase-divergent changeset: %s!") mscd = _("push includes content-divergent changeset: %s!") mst = {"orphan": _("push includes orphan changeset: %s!"), - "bumped": _("push includes bumped changeset: %s!"), + "phase-divergent": mspd, "content-divergent": mscd} # If we are to push if there is at least one # obsolete or unstable changeset in missing, at diff --git a/mercurial/context.py b/mercurial/context.py --- a/mercurial/context.py +++ b/mercurial/context.py @@ -230,14 +230,14 @@ Troubles are returned as strings. possible values are: - orphan, -- bumped, +- phase-divergent, - content-divergent. """ troubles = [] if self.unstable(): troubles.append('orphan') if self.bumped(): -troubles.append('bumped') +troubles.append('phase-divergent') if self.divergent(): troubles.append('content-divergent') return troubles diff --git a/mercurial/commands.py b/mercurial/commands.py --- a/mercurial/commands.py +++ b/mercurial/commands.py @@ -4943,7 +4943,7 @@ troublemsg = { "unstable":
D215: evolution: rename divergent to content-divergent
This revision was automatically updated to reflect the committed changes. Closed by commit rHG2194a8723138: evolution: rename divergent to content-divergent (authored by lothiraldan). REPOSITORY rHG Mercurial CHANGES SINCE LAST UPDATE https://phab.mercurial-scm.org/D215?vs=498=560 REVISION DETAIL https://phab.mercurial-scm.org/D215 AFFECTED FILES mercurial/commands.py mercurial/context.py mercurial/exchange.py tests/test-obsmarker-template.t tests/test-obsolete-divergent.t tests/test-rebase-obsolete.t CHANGE DETAILS diff --git a/tests/test-rebase-obsolete.t b/tests/test-rebase-obsolete.t --- a/tests/test-rebase-obsolete.t +++ b/tests/test-rebase-obsolete.t @@ -855,7 +855,7 @@ commit: (clean) update: 1 new changesets, 2 branch heads (merge) phases: 8 draft - divergent: 2 changesets + content-divergent: 2 changesets rebase --continue + skipped rev because their successors are in destination we make a change in trunk and work on conflicting changes to make rebase abort. diff --git a/tests/test-obsolete-divergent.t b/tests/test-obsolete-divergent.t --- a/tests/test-obsolete-divergent.t +++ b/tests/test-obsolete-divergent.t @@ -107,7 +107,7 @@ $ hg push ../other pushing to ../other searching for changes - abort: push includes divergent changeset: 392fd25390da! + abort: push includes content-divergent changeset: 392fd25390da! [255] $ cd .. @@ -671,9 +671,9 @@ $ rm .hg/localtags $ hg cleanup --config extensions.t=$TESTTMP/scmutilcleanup.py $ hg log -G -T '{rev}:{node|short} {desc} {troubles}' -r 'sort(all(), topo)' - @ 5:1a2a9b5b0030 B2 divergent + @ 5:1a2a9b5b0030 B2 content-divergent | - | o 4:70d5a63ca112 B4 divergent + | o 4:70d5a63ca112 B4 content-divergent | | | o 1:48b9aae0607f Z | diff --git a/tests/test-obsmarker-template.t b/tests/test-obsmarker-template.t --- a/tests/test-obsmarker-template.t +++ b/tests/test-obsmarker-template.t @@ -442,14 +442,14 @@ | parent: 0:ea207398892e | user:test | date:Thu Jan 01 00:00:00 1970 + - | instability: divergent + | instability: content-divergent | summary: A2 | | o changeset: 2:fdf9bde5129a |/ parent: 0:ea207398892e |user:test |date:Thu Jan 01 00:00:00 1970 + - |instability: divergent + |instability: content-divergent |summary: A1 | | x changeset: 1:471f378eab4c @@ -469,7 +469,7 @@ | parent: 0:ea207398892e | user:test | date:Thu Jan 01 00:00:00 1970 + - | instability: divergent + | instability: content-divergent | summary: A3 | | x changeset: 3:65b757b745b9 @@ -482,7 +482,7 @@ |/ parent: 0:ea207398892e |user:test |date:Thu Jan 01 00:00:00 1970 + - |instability: divergent + |instability: content-divergent |summary: A1 | | x changeset: 1:471f378eab4c @@ -1086,20 +1086,20 @@ | parent: 5:dd800401bd8c | user:test | date:Thu Jan 01 00:00:00 1970 + - | instability: divergent + | instability: content-divergent | summary: Add B only | | o changeset: 8:b18bc8331526 |/ parent: 5:dd800401bd8c |user:test |date:Thu Jan 01 00:00:00 1970 + - |instability: divergent + |instability: content-divergent |summary: Add only B | | o changeset: 7:ba2ed02b0c9a | | user:test | | date:Thu Jan 01 00:00:00 1970 + - | | instability: orphan, divergent + | | instability: orphan, content-divergent | | summary: Add A,B,C | | | x changeset: 6:4a004186e638 @@ -,7 +,7 @@ | parent: 3:f897c6137566 | user:test | date:Thu Jan 01 00:00:00 1970 + - | instability: divergent + | instability: content-divergent | summary: Add A,B,C | o changeset: 3:f897c6137566 diff --git a/mercurial/exchange.py b/mercurial/exchange.py --- a/mercurial/exchange.py +++ b/mercurial/exchange.py @@ -677,9 +677,10 @@ if unfi.obsstore: # this message are here for 80 char limit reason mso = _("push includes obsolete changeset: %s!") +mscd = _("push includes content-divergent changeset: %s!") mst = {"orphan": _("push includes orphan changeset: %s!"), "bumped": _("push includes bumped changeset: %s!"), - "divergent": _("push includes divergent changeset: %s!")} + "content-divergent": mscd} # If we are to push if there is at least one # obsolete or unstable changeset in missing, at # least one of the missinghead will be obsolete or diff --git a/mercurial/context.py b/mercurial/context.py --- a/mercurial/context.py +++ b/mercurial/context.py @@ -231,15 +231,15 @@ Troubles are returned as
D218: phabricator: add --confirm option to phabsend command
This revision was automatically updated to reflect the committed changes. Closed by commit rHG40cfe3197bc1: phabricator: add --confirm option to phabsend command (authored by pulkit). REPOSITORY rHG Mercurial CHANGES SINCE LAST UPDATE https://phab.mercurial-scm.org/D218?vs=515=562 REVISION DETAIL https://phab.mercurial-scm.org/D218 AFFECTED FILES contrib/phabricator.py CHANGE DETAILS diff --git a/contrib/phabricator.py b/contrib/phabricator.py --- a/contrib/phabricator.py +++ b/contrib/phabricator.py @@ -313,7 +313,8 @@ @command('phabsend', [('r', 'rev', [], _('revisions to send'), _('REV')), - ('', 'reviewer', [], _('specify reviewers'))], + ('', 'reviewer', [], _('specify reviewers')), + ('', 'confirm', None, _('ask for confirmation before sending'))], _('REV [OPTIONS]')) def phabsend(ui, repo, *revs, **opts): """upload changesets to Phabricator @@ -326,13 +327,27 @@ maintain the association. After the first time, phabsend will check obsstore and tags information so it can figure out whether to update an existing Differential Revision, or create a new one. + +The --confirm option lets you confirm changesets before sending them. You +can also add following to your configuration file to make it default +behaviour. + +[phabsend] +confirm = true """ revs = list(revs) + opts.get('rev', []) revs = scmutil.revrange(repo, revs) if not revs: raise error.Abort(_('phabsend requires at least one changeset')) +confirm = ui.configbool('phabsend', 'confirm') +confirm |= bool(opts.get('confirm')) +if confirm: +confirmed = _confirmbeforesend(repo, revs) +if not confirmed: +raise error.Abort(_('phabsend cancelled')) + actions = [] reviewers = opts.get('reviewer', []) if reviewers: @@ -379,6 +394,20 @@ _metanamemap = util.sortdict([(r'user', 'User'), (r'date', 'Date'), (r'node', 'Node ID'), (r'parent', 'Parent ')]) +def _confirmbeforesend(repo, revs): +ui = repo.ui +for rev in revs: +ctx = repo[rev] +desc = ctx.description().splitlines()[0] +ui.write(('%d: ' % rev), label='phabsend.revnumber') +ui.write(('%s\n' % desc), label='phabsend.desc') + +if ui.promptchoice(_('Phabsend the above changes (yn)?' +'$$ $$ ')): +return False + +return True + def querydrev(repo, params, stack=False): """return a list of "Differential Revision" dicts To: pulkit, #hg-reviewers, durin42 Cc: durin42, mercurial-devel ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
D218: phabricator: add --confirm option to phabsend command
durin42 accepted this revision. durin42 added a comment. This revision is now accepted and ready to land. Sure. REPOSITORY rHG Mercurial REVISION DETAIL https://phab.mercurial-scm.org/D218 To: pulkit, #hg-reviewers, durin42 Cc: durin42, mercurial-devel ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
Re: [PATCH] py3: use bytes IO to write sample hgrc
On Thu, Aug 03, 2017 at 01:13:20AM +0900, Yuya Nishihara wrote: > # HG changeset patch > # User Yuya Nishihara> # Date 1501688702 -32400 > # Thu Aug 03 00:45:02 2017 +0900 > # Node ID 52bbc0a0dc7a3e946ed16bf547929252e95603d4 > # Parent 6a620fd39e4cac88e1a46f18aa7b852639e3b729 > py3: use bytes IO to write sample hgrc queued, thanks ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
Re: [PATCH 3 of 3 v4 sparse-ext] sparse: treat paths as cwd-relative
On Fri, Aug 04, 2017 at 05:45:59AM -0700, Kostia Balytskyi wrote: > # HG changeset patch > # User Kostia Balytskyi> # Date 1501850302 25200 > # Fri Aug 04 05:38:22 2017 -0700 > # Node ID fe26df0128eaefab8b79f7552da89c762014dab7 > # Parent c0136292871d85675ccb9f386f4ae1913da4eb53 > sparse: treat paths as cwd-relative queued, thanks > > This commit makes it so sparse treats passed paths as CWD-relative, > not repo-root-realive. This is a more intuitive behavior in my (and some > other FB people's) opinion. > > This is breaking change however. My hope here is that since sparse is > experimental, it's ok to introduce BCs. Yes, that's why we have experimental things. > > The reason (glob)s are needed in the test is this: in these two cases we > do not supply path together with slashes, but `os.path.join` adds them, which > means that under Windows they can be backslashes. To demonstrate this > behavior, > one could remove the (glob)s and run `./run-tests.py test-sparse.t` from > MinGW's terminal on Windows. > > diff --git a/hgext/sparse.py b/hgext/sparse.py [...] > elif exclude: > diff --git a/tests/test-sparse.t b/tests/test-sparse.t > --- a/tests/test-sparse.t > +++ b/tests/test-sparse.t > @@ -48,6 +48,31 @@ TODO: See if this can be made to fail th >[255] > #endif > > +Paths should be treated as cwd-relative, not repo-root-relative > + $ mkdir subdir && cd subdir > + $ hg debugsparse --include path > + $ hg debugsparse > + [include] > + $TESTTMP/myrepo/hide > + hide > + subdir/path (glob) > + > + $ cd .. > + $ echo hello > subdir/file2.ext > + $ cd subdir > + $ hg debugsparse --include '**.ext' # let us test globs > + $ hg debugsparse --include 'path:abspath' # and a path: pattern I'm a little weirded out that it becomes absolute magically, but I guess it matches `hg files` (h/t to Martin), so I'm fine with it. > + $ cd .. > + $ hg debugsparse > + [include] > + $TESTTMP/myrepo/hide > + hide > + path:abspath > + subdir/**.ext > + subdir/path (glob) > + > + $ rm -rf subdir > + > Verify commiting while sparse includes other files > >$ echo z > hide > ___ > Mercurial-devel mailing list > Mercurial-devel@mercurial-scm.org > https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
D231: httppeer: add support for httppostargs when we're sending a file
durin42 created this revision. Herald added a subscriber: mercurial-devel. Herald added a reviewer: hg-reviewers. REVISION SUMMARY This is probably only used in the 'unbundle' command, but the code ended up being cleaner to make it generic and treat *all* httppostargs with a non-args request body as though they were file-like in nature. It also means we get test coverage more or less for free. A previous version of this change didn't use io.BytesIO, and it was a lot more complicated. This also fixes a server-side bug, so anyone using httppostargs should update all of their servers to this revision or later *before* this gets to their clients, otherwise servers will hang trying to over-read the POST body. REPOSITORY rHG Mercurial REVISION DETAIL https://phab.mercurial-scm.org/D231 AFFECTED FILES mercurial/hgweb/protocol.py mercurial/httppeer.py CHANGE DETAILS diff --git a/mercurial/httppeer.py b/mercurial/httppeer.py --- a/mercurial/httppeer.py +++ b/mercurial/httppeer.py @@ -9,6 +9,7 @@ from __future__ import absolute_import import errno +import io import os import socket import struct @@ -86,6 +87,44 @@ resp.__class__ = readerproxy +class _multifile(object): +def __init__(self, *fileobjs): +for f in fileobjs: +if not util.safehasattr(f, 'length'): +raise ValueError( +'fileprepender only supports file objects that ' +'have a length but this one does not:', type(f), f) +self._fileobjs = fileobjs +self._index = 0 + +@property +def length(self): +return sum(f.length for f in self._fileobjs) + +def read(self, amt=None): +if not amt: +return ''.join(f.read() for f in self._fileobjs) +parts = [] +while amt and self._index < len(self._fileobjs): +parts.append(self._fileobjs[self._index].read(amt)) +got = len(parts[-1]) +if got < amt: +self._index += 1 +amt -= got +return ''.join(parts) + +def seek(self, offset, whence=os.SEEK_SET): +if whence != os.SEEK_SET: +raise NotImplementedError( +'fileprepender does not support anything other' +' than os.SEEK_SET for whence on seek()') +if offset != 0: +raise NotImplementedError( +'fileprepender only supports seeking to start, but that ' +'could be fixed if you need it') +for f in self._fileobjs: +f.seek(0) + class httppeer(wireproto.wirepeer): def __init__(self, ui, path): self.path = path @@ -149,16 +188,19 @@ # with infinite recursion when trying to look up capabilities # for the first time. postargsok = self.caps is not None and 'httppostargs' in self.caps -# TODO: support for httppostargs when data is a file-like -# object rather than a basestring -canmungedata = not data or isinstance(data, basestring) -if postargsok and canmungedata: +if postargsok: strargs = urlreq.urlencode(sorted(args.items())) if strargs: if not data: data = strargs -elif isinstance(data, basestring): -data = strargs + data +else: +if isinstance(data, basestring): +i = io.BytesIO(data) +i.length = len(data) +data = i +argsio = io.BytesIO(strargs) +argsio.length = len(strargs) +data = _multifile(argsio, data) headers['X-HgArgs-Post'] = len(strargs) else: if len(args) > 0: diff --git a/mercurial/hgweb/protocol.py b/mercurial/hgweb/protocol.py --- a/mercurial/hgweb/protocol.py +++ b/mercurial/hgweb/protocol.py @@ -75,6 +75,9 @@ return args def getfile(self, fp): length = int(self.req.env['CONTENT_LENGTH']) +# If httppostargs is used, we need to read Content-Length +# minus the amount that was consumed by args. +length -= int(self.req.env.get('HTTP_X_HGARGS_POST', 0)) for s in util.filechunkiter(self.req, limit=length): fp.write(s) def redirect(self): To: durin42, #hg-reviewers Cc: mercurial-devel ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
D230: http: add a test of actually pushing with httppostargs
durin42 created this revision. Herald added a subscriber: mercurial-devel. Herald added a reviewer: hg-reviewers. REVISION SUMMARY This was previously untested. Sigh. REPOSITORY rHG Mercurial REVISION DETAIL https://phab.mercurial-scm.org/D230 AFFECTED FILES tests/test-push-http.t CHANGE DETAILS diff --git a/tests/test-push-http.t b/tests/test-push-http.t --- a/tests/test-push-http.t +++ b/tests/test-push-http.t @@ -172,4 +172,20 @@ % serve errors [255] + $ cat > .hg/hgrc < [web] + > push_ssl = false + > allow_push = * + > [experimental] + > httppostargs=true + > EOF + $ req + pushing to http://localhost:$HGPORT/ + searching for changes + remote: adding changesets + remote: adding manifests + remote: adding file changes + remote: added 1 changesets with 1 changes to 1 files + % serve errors + $ cd .. To: durin42, #hg-reviewers Cc: mercurial-devel ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
D216: evolution: rename bumped to phase-divergent
durin42 accepted this revision as: durin42. durin42 added a comment. I'm fine with this as-is for now, with the caveat that we might want to fix the two -divergent names in the future if they lead to user confusion. (Someone should feel encouraged to land this, I'm in the middle of some unpleasant debugging and am reviewing while I wait for wireshark to install.) REPOSITORY rHG Mercurial REVISION DETAIL https://phab.mercurial-scm.org/D216 To: lothiraldan, #hg-reviewers, ryanmce, durin42 Cc: ryanmce, martinvonz, quark, durin42, mercurial-devel ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
D127: phabricator: add phabupdate command to update status in batch
quark updated this revision to Diff 557. REPOSITORY rHG Mercurial CHANGES SINCE LAST UPDATE https://phab.mercurial-scm.org/D127?vs=239=557 REVISION DETAIL https://phab.mercurial-scm.org/D127 AFFECTED FILES contrib/phabricator.py CHANGE DETAILS diff --git a/contrib/phabricator.py b/contrib/phabricator.py --- a/contrib/phabricator.py +++ b/contrib/phabricator.py @@ -9,7 +9,7 @@ This extension provides a ``phabsend`` command which sends a stack of changesets to Phabricator without amending commit messages, and a ``phabread`` command which prints a stack of revisions in a format suitable -for :hg:`import`. +for :hg:`import`, and a ``phabupdate`` command to update statuses in batch. By default, Phabricator requires ``Test Plan`` which might prevent some changeset from being sent. The requirement could be disabled by changing @@ -765,3 +765,32 @@ spec = ':(%s)' % spec drevs = querydrev(repo, spec) readpatch(repo, drevs, ui.write) + +@command('phabupdate', + [('', 'accept', False, _('accept revisions')), + ('', 'reject', False, _('reject revisions')), + ('', 'abandon', False, _('abandon revisions')), + ('', 'reclaim', False, _('reclaim revisions')), + ('m', 'comment', '', _('comment on the last revision')), + ], _('DREVSPEC [OPTIONS]')) +def phabupdate(ui, repo, spec, **opts): +"""update Differential Revision in batch + +DREVSPEC selects revisions. See :hg:`help phabread` for its usage. +""" +flags = [n for n in 'accept reject abandon reclaim'.split() if opts.get(n)] +if len(flags) > 1: +raise error.Abort(_('%s cannot be used together') % ', '.join(flags)) + +actions = [] +for f in flags: +actions.append({'type': f, 'value': 'true'}) + +drevs = querydrev(repo, spec) +for i, drev in enumerate(drevs): +if i + 1 == len(drevs) and opts.get('comment'): +actions.append({'type': 'comment', 'value': opts['comment']}) +if actions: +params = {'objectIdentifier': drev[r'phid'], + 'transactions': actions} +callconduit(repo, 'differential.revision.edit', params) To: quark, #hg-reviewers Cc: krbullock, mercurial-devel ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
D122: phabricator: add --amend option to phabsend
quark updated this revision to Diff 553. quark edited the test plan for this revision. REPOSITORY rHG Mercurial CHANGES SINCE LAST UPDATE https://phab.mercurial-scm.org/D122?vs=485=553 REVISION DETAIL https://phab.mercurial-scm.org/D122 AFFECTED FILES contrib/phabricator.py CHANGE DETAILS diff --git a/contrib/phabricator.py b/contrib/phabricator.py --- a/contrib/phabricator.py +++ b/contrib/phabricator.py @@ -38,6 +38,8 @@ from mercurial.node import bin, nullid from mercurial.i18n import _ from mercurial import ( +cmdutil, +context, encoding, error, mdiff, @@ -316,7 +318,7 @@ if not revision: raise error.Abort(_('cannot create revision for %s') % ctx) -return revision +return revision, diff def userphids(repo, names): """convert user names to PHIDs""" @@ -334,6 +336,7 @@ @command('phabsend', [('r', 'rev', [], _('revisions to send'), _('REV')), + ('', 'amend', False, _('update commit messages')), ('', 'reviewer', [], _('specify reviewers'))], _('REV [OPTIONS]')) def phabsend(ui, repo, *revs, **opts): @@ -343,16 +346,21 @@ with a linear dependencies relationship using the order specified by the revset. -For the first time uploading changesets, local tags will be created to -maintain the association. After the first time, phabsend will check -obsstore and tags information so it can figure out whether to update an -existing Differential Revision, or create a new one. +If --amend is set, update commit messages so they have the +``Differential Revision`` URL, remove related tags. This is similar to what +arcanist will do, and is more desired in author-push workflows. Otherwise, +use local tags to record the ``Differential Revision`` association. + +phabsend will check obsstore and the above association to decide whether to +update an existing Differential Revision, or create a new one. """ revs = list(revs) + opts.get('rev', []) revs = scmutil.revrange(repo, revs) if not revs: raise error.Abort(_('phabsend requires at least one changeset')) +if opts.get('amend'): +cmdutil.checkunfinished(repo) actions = [] reviewers = opts.get('reviewer', []) @@ -363,6 +371,9 @@ # {newnode: (oldnode, olddiff, olddrev} oldmap = getoldnodedrevmap(repo, [repo[r].node() for r in revs]) +drevids = [] # [int] +diffmap = {} # {newnode: diff} + # Send patches one by one so we know their Differential Revision IDs and # can provide dependency relationship lastrevid = None @@ -374,28 +385,67 @@ oldnode, olddiff, revid = oldmap.get(ctx.node(), (None, None, None)) if oldnode != ctx.node(): # Create or update Differential Revision -revision = createdifferentialrevision(ctx, revid, lastrevid, - oldnode, olddiff, actions) +revision, diff = createdifferentialrevision( +ctx, revid, lastrevid, oldnode, olddiff, actions) +diffmap[ctx.node()] = diff newrevid = int(revision[r'object'][r'id']) if revid: action = _('updated') else: action = _('created') -# Create a local tag to note the association -tagname = 'D%d' % newrevid -tags.tag(repo, tagname, ctx.node(), message=None, user=None, - date=None, local=True) +# Create a local tag to note the association, if commit message +# does not have it already +m = _differentialrevisiondescre.search(ctx.description()) +if not m or int(m.group(1)) != newrevid: +tagname = 'D%d' % newrevid +tags.tag(repo, tagname, ctx.node(), message=None, user=None, + date=None, local=True) else: # Nothing changed. But still set "newrevid" so the next revision # could depend on this one. newrevid = revid action = _('skipped') ui.write(_('D%s: %s - %s: %s\n') % (newrevid, action, ctx, ctx.description().split('\n')[0])) +drevids.append(newrevid) lastrevid = newrevid +# Update commit messages and remove tags +if opts.get('amend'): +unfi = repo.unfiltered() +drevs = callconduit(repo, 'differential.query', {'ids': drevids}) +with repo.wlock(), repo.lock(), repo.transaction('phabsend'): +wnode = unfi['.'].node() +mapping = {} # {oldnode: [newnode]} +for i, rev in enumerate(revs): +old = unfi[rev] +drevid = drevids[i] +drev = [d for d in drevs if int(d[r'id']) == drevid][0] +newdesc = getdescfromdrev(drev) +# Make sure commit message contain
D126: phabricator: add status to revision query language
quark updated this revision to Diff 556. REPOSITORY rHG Mercurial CHANGES SINCE LAST UPDATE https://phab.mercurial-scm.org/D126?vs=488=556 REVISION DETAIL https://phab.mercurial-scm.org/D126 AFFECTED FILES contrib/phabricator.py CHANGE DETAILS diff --git a/contrib/phabricator.py b/contrib/phabricator.py --- a/contrib/phabricator.py +++ b/contrib/phabricator.py @@ -455,6 +455,13 @@ _metanamemap = util.sortdict([(r'user', 'User'), (r'date', 'Date'), (r'node', 'Node ID'), (r'parent', 'Parent ')]) +_knownstatusnames = {'accepted', 'needsreview', 'needsrevision', 'closed', + 'abandoned'} + +def _getstatusname(drev): +"""get normalized status name from a Differential Revision""" +return drev[r'statusName'].replace(' ', '').lower() + # Small language to specify differential revisions. Support symbols: (), :X, # +, and -. @@ -471,19 +478,19 @@ } def _tokenize(text): -text = text.replace(' ', '') # remove space view = memoryview(text) # zero-copy slice -special = '():+-&' +special = '():+-& ' pos = 0 length = len(text) while pos < length: symbol = ''.join(itertools.takewhile(lambda ch: ch not in special, view[pos:])) if symbol: yield ('symbol', symbol, pos) pos += len(symbol) -else: # special char -yield (text[pos], None, pos) +else: # special char, ignore space +if text[pos] != ' ': +yield (text[pos], None, pos) pos += 1 yield ('end', None, pos) @@ -611,15 +618,19 @@ tofetch.update(range(max(1, r - batchsize), r + 1)) if drevs: fetch({r'ids': list(tofetch)}) -getstack(list(ancestordrevs)) +validids = sorted(set(getstack(list(ancestordrevs))) | set(drevs)) # Walk through the tree, return smartsets def walk(tree): op = tree[0] if op == 'symbol': drev = _parsedrev(tree[1]) if drev: return smartset.baseset([drev]) +elif tree[1] in _knownstatusnames: +drevs = [r for r in validids + if _getstatusname(prefetched[r]) == tree[1]] +return smartset.baseset(drevs) else: raise error.Abort(_('unknown symbol: %s') % tree[1]) elif op in {'and_', 'add', 'sub'}: @@ -739,8 +750,13 @@ ``&``, ``(``, ``)`` for complex queries. Prefix ``:`` could be used to select a stack. +``abandoned``, ``accepted``, ``closed``, ``needsreview``, ``needsrevision`` +could be used to filter patches by status. For performance reason, they +only represent a subset of non-status selections and cannot be used alone. + For example, ``:D6+8-(2+D4)`` selects a stack up to D6, plus D8 and exclude -D2 and D4. +D2 and D4. ``:D9 & needsreview`` selects "Needs Review" revisions in a +stack up to D9. If --stack is given, follow dependencies information and read all patches. It is equivalent to the ``:`` operator. To: quark, #hg-reviewers Cc: mercurial-devel ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
D124: phabricator: change "readpatch" to be more flexible
quark updated this revision to Diff 554. REPOSITORY rHG Mercurial CHANGES SINCE LAST UPDATE https://phab.mercurial-scm.org/D124?vs=486=554 REVISION DETAIL https://phab.mercurial-scm.org/D124 AFFECTED FILES contrib/phabricator.py CHANGE DETAILS diff --git a/contrib/phabricator.py b/contrib/phabricator.py --- a/contrib/phabricator.py +++ b/contrib/phabricator.py @@ -602,15 +602,12 @@ meta[r'parent'] = commit[r'parents'][0] return meta or {} -def readpatch(repo, params, write, stack=False): +def readpatch(repo, drevs, write): """generate plain-text patch readable by 'hg import' -write is usually ui.write. params is passed to "differential.query". If -stack is True, also write dependent patches. +write is usually ui.write. drevs is what "querydrev" returns, results of +"differential.query". """ -# Differential Revisions -drevs = querydrev(repo, params, stack) - # Prefetch hg:meta property for all diffs diffids = sorted(set(max(int(v) for v in drev[r'diffs']) for drev in drevs)) diffs = callconduit(repo, 'differential.querydiffs', {'ids': diffids}) @@ -650,4 +647,5 @@ revid = int(revid.split('/')[-1].replace('D', '')) except ValueError: raise error.Abort(_('invalid Revision ID: %s') % revid) -readpatch(repo, {'ids': [revid]}, ui.write, opts.get('stack')) +drevs = querydrev(repo, {'ids': [revid]}, opts.get('stack')) +readpatch(repo, drevs, ui.write) To: quark, #hg-reviewers, mitrandir Cc: mercurial-devel ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
D229: phabricator: update diff property even if we choose not to create a new diff
quark created this revision. Herald added a subscriber: mercurial-devel. Herald added a reviewer: hg-reviewers. REVISION SUMMARY The diff property contains metadata like "HG Node". Previously we skip uploading a new diff if we are sure that the old patch and new patch have a same content. That has issues when a pusher adds an obsmarker using the old "HG Node" stored in the old diff. This patch adds logic to update the diff property so "HG Node" gets updated to prevent that issue. REPOSITORY rHG Mercurial REVISION DETAIL https://phab.mercurial-scm.org/D229 AFFECTED FILES contrib/phabricator.py CHANGE DETAILS diff --git a/contrib/phabricator.py b/contrib/phabricator.py --- a/contrib/phabricator.py +++ b/contrib/phabricator.py @@ -255,7 +255,7 @@ callconduit(ctx.repo(), 'differential.setdiffproperty', params) def createdifferentialrevision(ctx, revid=None, parentrevid=None, oldnode=None, - actions=None): + olddiff=None, actions=None): """create or update a Differential Revision If revid is None, create a new Differential Revision, otherwise update @@ -279,6 +279,13 @@ diff = creatediff(ctx) writediffproperties(ctx, diff) transactions.append({'type': 'update', 'value': diff[r'phid']}) +else: +# Even if we don't need to upload a new diff because the patch content +# does not change. We might still need to update its metadata so +# pushers could know the correct node metadata. +assert olddiff +diff = olddiff +writediffproperties(ctx, diff) # Use a temporary summary to set dependency. There might be better ways but # I cannot find them for now. But do not do that if we are updating an @@ -368,7 +375,7 @@ if oldnode != ctx.node(): # Create or update Differential Revision revision = createdifferentialrevision(ctx, revid, lastrevid, - oldnode, actions) + oldnode, olddiff, actions) newrevid = int(revision[r'object'][r'id']) if revid: action = _('updated') To: quark, #hg-reviewers Cc: mercurial-devel ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
Re: [PATCH STABLE] i18n: use actual filename, in which function is defined, for hg.pot
At Fri, 4 Aug 2017 00:36:28 +0900, Yuya Nishihara wrote: > > On Wed, 02 Aug 2017 22:36:45 +0900, FUJIWARA Katsunori wrote: > > # HG changeset patch > > # User FUJIWARA Katsunori> > # Date 1501599731 -32400 > > # Wed Aug 02 00:02:11 2017 +0900 > > # Branch stable > > # Node ID b6d0bcd19b4dffb2360f909f459c27104ad16565 > > # Parent 76b171209151fe41dbf8dbfec473cc533f3b40ca > > # Available At https://bitbucket.org/foozy/mercurial-wip > > # hg pull https://bitbucket.org/foozy/mercurial-wip -r > > b6d0bcd19b4d > > # EXP-Topic i18n-fix-update-pot-issues > > i18n: use actual filename, in which function is defined, for hg.pot > > > +funcmod = inspect.getmodule(func) > > +extra = '' > > +if funcmod.__package__ == funcmod.__name__: > > +extra = '/__init__' > > +actualpath = '%s%s.py' % (funcmod.__name__.replace('.', '/'), > > extra) > > + > > src = inspect.getsource(func) > > -name = "%s.%s" % (path, func.__name__) > > +name = "%s.%s" % (actualpath, func.__name__) > > lineno = inspect.getsourcelines(func)[1] > > Perhaps inspect.getsourcefile() can be used. > Ah, I overlooked it. I'll post follow up patch on default. Thanks! -- -- [FUJIWARA Katsunori] fo...@lares.dti.ne.jp ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
D216: evolution: rename bumped to phase-divergent
quark added a comment. In https://phab.mercurial-scm.org/D216#3674, @ryanmce wrote: > I disagree. `hg amend` --> `abort: cannot amend public changesets` The word "public" does not get associated with "phase" automatically. I think users can understand what "public" and "draft" without knowing what "phase" is. "divergent" also seems understandable without Googling. I'm not sure about "phase". Anyway, since we can always customize these (ex. `dialect.py`). From an internal UX point of view, I'm fine with whatever chosen. REPOSITORY rHG Mercurial REVISION DETAIL https://phab.mercurial-scm.org/D216 To: lothiraldan, #hg-reviewers, ryanmce Cc: ryanmce, martinvonz, quark, durin42, mercurial-devel ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
D224: build: Delaying version computation on macOS builds.
This revision was automatically updated to reflect the committed changes. Closed by commit rHGf22513c3717d: build: Delaying version computation on macOS builds. (authored by rdamazio). REPOSITORY rHG Mercurial CHANGES SINCE LAST UPDATE https://phab.mercurial-scm.org/D224?vs=530=547 REVISION DETAIL https://phab.mercurial-scm.org/D224 AFFECTED FILES Makefile CHANGE DETAILS diff --git a/Makefile b/Makefile --- a/Makefile +++ b/Makefile @@ -186,7 +186,7 @@ PREFIX=/usr/local \ clean install mkdir -p $${OUTPUTDIR:-dist} - HGVER=$(shell python contrib/genosxversion.py $(OSXVERSIONFLAGS) build/mercurial/Library/Python/2.7/site-packages/mercurial/__version__.py ) && \ + HGVER=$$(shell python contrib/genosxversion.py $(OSXVERSIONFLAGS) build/mercurial/Library/Python/2.7/site-packages/mercurial/__version__.py ) && \ OSXVER=$$(sw_vers -productVersion | cut -d. -f1,2) && \ pkgbuild --filter \\.DS_Store --root build/mercurial/ \ --identifier org.mercurial-scm.mercurial \ To: rdamazio, #hg-reviewers, martinvonz Cc: martinvonz, mercurial-devel ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
Evolution mini-sprint
Hi mercurial developers, This was in the air for a while and here it is! We are organizing an Evolve mini-sprint focused on documentation and usability bug-fixes. You're welcome to join us and share your thoughts, feedback and pain around Evolve and Mercurial, but also meets the people behind IRC pseudos and email addresses for real. The mini-sprint will start on August 28th and ends on August 30th 2017 and will be hosted in Paris. (Yes that's the end of the month!) The exact venue is not known yet. It will be published as soon as known. Please register in this pad here if you want to come: https://tinyurl.c om/evosprint17 If you have any sensitive information (food, health, transportation, ... related), please fill this form to contact us: https://framaforms.o rg/evolve-mini-sprint-organization-form-1501847916 If you are considering attending but travel cost is a blocker, get in touch with me. Cheers, Boris Feld ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
D223: color: remove warnings if term is not formatted (==dumb or !ui.formatted())
This revision was automatically updated to reflect the committed changes. Closed by commit rHGf9f28ee41cac: color: remove warnings if term is not formatted (==dumb or !ui.formatted()) (authored by spectral). REPOSITORY rHG Mercurial CHANGES SINCE LAST UPDATE https://phab.mercurial-scm.org/D223?vs=528=546 REVISION DETAIL https://phab.mercurial-scm.org/D223 AFFECTED FILES mercurial/color.py CHANGE DETAILS diff --git a/mercurial/color.py b/mercurial/color.py --- a/mercurial/color.py +++ b/mercurial/color.py @@ -130,7 +130,7 @@ def loadcolortable(ui, extname, colortable): _defaultstyles.update(colortable) -def _terminfosetup(ui, mode): +def _terminfosetup(ui, mode, formatted): '''Initialize terminfo data and the terminal if we're in terminfo mode.''' # If we failed to load curses, we go ahead and return. @@ -164,8 +164,8 @@ del ui._terminfoparams[key] if not curses.tigetstr('setaf') or not curses.tigetstr('setab'): # Only warn about missing terminfo entries if we explicitly asked for -# terminfo mode. -if mode == "terminfo": +# terminfo mode and we're in a formatted terminal. +if mode == "terminfo" and formatted: ui.warn(_("no terminfo entry for setab/setaf: reverting to " "ECMA-48 color\n")) ui._terminfoparams.clear() @@ -242,7 +242,7 @@ def modewarn(): # only warn if color.mode was explicitly set and we're in # a formatted terminal -if mode == realmode and ui.formatted(): +if mode == realmode and formatted: ui.warn(_('warning: failed to set color mode to %s\n') % mode) if realmode == 'win32': @@ -253,7 +253,7 @@ elif realmode == 'ansi': ui._terminfoparams.clear() elif realmode == 'terminfo': -_terminfosetup(ui, mode) +_terminfosetup(ui, mode, formatted) if not ui._terminfoparams: ## FIXME Shouldn't we return None in this case too? modewarn() To: spectral, #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
D223: color: remove warnings if term is not formatted (==dumb or !ui.formatted())
yuja accepted this revision as: yuja. yuja added a comment. Makes sense. REPOSITORY rHG Mercurial REVISION DETAIL https://phab.mercurial-scm.org/D223 To: spectral, #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
[PATCH 3 of 3 v4 sparse-ext] sparse: treat paths as cwd-relative
# HG changeset patch # User Kostia Balytskyi# Date 1501850302 25200 # Fri Aug 04 05:38:22 2017 -0700 # Node ID fe26df0128eaefab8b79f7552da89c762014dab7 # Parent c0136292871d85675ccb9f386f4ae1913da4eb53 sparse: treat paths as cwd-relative This commit makes it so sparse treats passed paths as CWD-relative, not repo-root-realive. This is a more intuitive behavior in my (and some other FB people's) opinion. This is breaking change however. My hope here is that since sparse is experimental, it's ok to introduce BCs. The reason (glob)s are needed in the test is this: in these two cases we do not supply path together with slashes, but `os.path.join` adds them, which means that under Windows they can be backslashes. To demonstrate this behavior, one could remove the (glob)s and run `./run-tests.py test-sparse.t` from MinGW's terminal on Windows. diff --git a/hgext/sparse.py b/hgext/sparse.py --- a/hgext/sparse.py +++ b/hgext/sparse.py @@ -155,7 +155,8 @@ def _clonesparsecmd(orig, ui, repo, *arg if include or exclude or enableprofile: def clonesparse(orig, self, node, overwrite, *args, **kwargs): sparse.updateconfig(self.unfiltered(), pat, {}, include=include, -exclude=exclude, enableprofile=enableprofile) +exclude=exclude, enableprofile=enableprofile, +usereporootpaths=True) return orig(self, node, overwrite, *args, **kwargs) extensions.wrapfunction(hg, 'updaterepo', clonesparse) return orig(ui, repo, *args, **opts) diff --git a/mercurial/sparse.py b/mercurial/sparse.py --- a/mercurial/sparse.py +++ b/mercurial/sparse.py @@ -17,6 +17,7 @@ from . import ( error, match as matchmod, merge as mergemod, +pathutil, pycompat, scmutil, util, @@ -616,7 +617,7 @@ def importfromfiles(repo, opts, paths, f def updateconfig(repo, pats, opts, include=False, exclude=False, reset=False, delete=False, enableprofile=False, disableprofile=False, - force=False): + force=False, usereporootpaths=False): """Perform a sparse config update. Only one of the actions may be performed. @@ -639,6 +640,20 @@ def updateconfig(repo, pats, opts, inclu if any(os.path.isabs(pat) for pat in pats): raise error.Abort(_('paths cannot be absolute')) +if not usereporootpaths: +# let's treat paths as relative to cwd +root, cwd = repo.root, repo.getcwd() +abspats = [] +for kindpat in pats: +kind, pat = matchmod._patsplit(kindpat, None) +if kind in matchmod.cwdrelativepatternkinds or kind is None: +ap = (kind + ':' if kind else '') +\ +pathutil.canonpath(root, cwd, pat) +abspats.append(ap) +else: +abspats.append(kindpat) +pats = abspats + if include: newinclude.update(pats) elif exclude: diff --git a/tests/test-sparse.t b/tests/test-sparse.t --- a/tests/test-sparse.t +++ b/tests/test-sparse.t @@ -48,6 +48,31 @@ TODO: See if this can be made to fail th [255] #endif +Paths should be treated as cwd-relative, not repo-root-relative + $ mkdir subdir && cd subdir + $ hg debugsparse --include path + $ hg debugsparse + [include] + $TESTTMP/myrepo/hide + hide + subdir/path (glob) + + $ cd .. + $ echo hello > subdir/file2.ext + $ cd subdir + $ hg debugsparse --include '**.ext' # let us test globs + $ hg debugsparse --include 'path:abspath' # and a path: pattern + $ cd .. + $ hg debugsparse + [include] + $TESTTMP/myrepo/hide + hide + path:abspath + subdir/**.ext + subdir/path (glob) + + $ rm -rf subdir + Verify commiting while sparse includes other files $ echo z > hide ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
[PATCH 1 of 3 v4 sparse-ext] sparse: properly error out when absolute paths are used
# HG changeset patch # User Kostia Balytskyi# Date 1501711521 25200 # Wed Aug 02 15:05:21 2017 -0700 # Node ID d24d6711aa2a5397d52f46ccffa64c2a638c088b # Parent 609606d217659e0a6c1cf6f907b6512be5340e57 sparse: properly error out when absolute paths are used Current logic is misleading (it says it drops only absolute paths, but it actually drops all of them), not cross-platform (does not support Windows) and IMO just wrong (as it should just error out if absolute paths are given). This commit fixes it. diff --git a/mercurial/sparse.py b/mercurial/sparse.py --- a/mercurial/sparse.py +++ b/mercurial/sparse.py @@ -636,10 +636,10 @@ def updateconfig(repo, pats, opts, inclu newexclude = set(oldexclude) newprofiles = set(oldprofiles) -if any(pat.startswith('/') for pat in pats): -repo.ui.warn(_('warning: paths cannot start with /, ignoring: %s\n') - % ([pat for pat in pats if pat.startswith('/')])) -elif include: +if any(os.path.isabs(pat) for pat in pats): +raise error.Abort(_('paths cannot be absolute')) + +if include: newinclude.update(pats) elif exclude: newexclude.update(pats) diff --git a/tests/test-sparse.t b/tests/test-sparse.t --- a/tests/test-sparse.t +++ b/tests/test-sparse.t @@ -29,20 +29,22 @@ Absolute paths outside the repo should j #if no-windows $ hg debugsparse --include /foo/bar - warning: paths cannot start with /, ignoring: ['/foo/bar'] + abort: paths cannot be absolute + [255] $ hg debugsparse --include '$TESTTMP/myrepo/hide' $ hg debugsparse --include '/root' - warning: paths cannot start with /, ignoring: ['/root'] + abort: paths cannot be absolute + [255] #else TODO: See if this can be made to fail the same way as on Unix $ hg debugsparse --include /c/foo/bar - abort: c:/foo/bar not under root '$TESTTMP/myrepo' (glob) + abort: paths cannot be absolute [255] $ hg debugsparse --include '$TESTTMP/myrepo/hide' $ hg debugsparse --include '/c/root' - abort: c:/root not under root '$TESTTMP/myrepo' (glob) + abort: paths cannot be absolute [255] #endif ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
[PATCH 2 of 3 v4 sparse-ext] match: expose some data and functionality to other modules
# HG changeset patch # User Kostia Balytskyi# Date 1501714137 25200 # Wed Aug 02 15:48:57 2017 -0700 # Node ID c0136292871d85675ccb9f386f4ae1913da4eb53 # Parent d24d6711aa2a5397d52f46ccffa64c2a638c088b match: expose some data and functionality to other modules This patch makes sure that other modules can check whether patterns are CWD-relative. diff --git a/mercurial/match.py b/mercurial/match.py --- a/mercurial/match.py +++ b/mercurial/match.py @@ -18,6 +18,11 @@ from . import ( util, ) +allpatternkinds = ('re', 'glob', 'path', 'relglob', 'relpath', 'relre', + 'listfile', 'listfile0', 'set', 'include', 'subinclude', + 'rootfilesin') +cwdrelativepatternkinds = ('relpath', 'glob') + propertycache = util.propertycache def _rematcher(regex): @@ -190,7 +195,7 @@ def _donormalize(patterns, default, root normalized and rooted patterns and with listfiles expanded.''' kindpats = [] for kind, pat in [_patsplit(p, default) for p in patterns]: -if kind in ('glob', 'relpath'): +if kind in cwdrelativepatternkinds: pat = pathutil.canonpath(root, cwd, pat, auditor) elif kind in ('relglob', 'path', 'rootfilesin'): pat = util.normpath(pat) @@ -691,9 +696,7 @@ def _patsplit(pattern, default): pattern.""" if ':' in pattern: kind, pat = pattern.split(':', 1) -if kind in ('re', 'glob', 'path', 'relglob', 'relpath', 'relre', -'listfile', 'listfile0', 'set', 'include', 'subinclude', -'rootfilesin'): +if kind in allpatternkinds: return kind, pat return default, pattern ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
D216: evolution: rename bumped to phase-divergent
ryanmce added a comment. In fact, right at the top of that CED page is an introduction that I think is pretty clear for such a powerful topic: Introduction to Instability --- Rewriting changesets may introduce **instability**. There are two main kinds of **unstable** changesets: **orphaned** changesets and **divergent** changesets. **Orphans** are changesets left behind when their ancestors are rewritten. **Divergence** has two variants: - **Content-divergence** occurs when independent rewrites of the same changeset lead to different results. - **Phase-divergence** occurs when the old (obsolete) version of a changeset becomes public. --- I'm probably biased because I helped write this (and I just cleaned it up and added emphasis), but I think it's pretty clear. REPOSITORY rHG Mercurial REVISION DETAIL https://phab.mercurial-scm.org/D216 To: lothiraldan, #hg-reviewers, ryanmce Cc: ryanmce, martinvonz, quark, durin42, mercurial-devel ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
Re: 4.3 freeze over, release delayed
Will the security fix be backported in a 4.2.3 release for people that are still on Python 2.6? Cheers, Boris On Tue, 2017-08-01 at 10:32 -0400, Augie Fackler wrote: > Howdy folks, > > We've got an upcoming security fix that needs to be coordinated with > other packages, so we're not releasing 4.3 today. We *are*, however, > unfreezing and you're welcome to send patches for default (which will > become 4.4) even as we're waiting for the all-clear to release 4.3. > > Thanks, > Augie > ___ > Mercurial-devel mailing list > Mercurial-devel@mercurial-scm.org > https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
D216: evolution: rename bumped to phase-divergent
ryanmce accepted this revision. ryanmce added a comment. A Dead Horse in Need of Kicking === I have no strong desire to drag this dead horse out of its grave to continue kicking it. However, since we are here, I will state for the record that I disagree that "overdue" is more clear. Imagine I'm a `git` user trying out `hg` due to hearing about some of its cool features. I'm hacking on some stuff with a friend and now I see that I have "1 overdue changeset". I have no idea what that means, to be honest. Is it out-of-date somehow? Will it expire soon? Will I be fined by the library? However, if I see that a changeset is "phase-divergent" I may also be confused, but I pretty quickly know two things: (1) I should understand what "phase" means, and that this changeset disagrees with another changeset somehow. So, I look up phases and (1) I've learned something important about hg and (2) now phase-divergence makes a lot more sense just by me knowing about phases and the meaning of "divergent": my changeset is draft, but a different version of it is public, so mine is phase-divergent. It's clear from then on because it builds on top of the terminology we already use elsewhere in hg. Moving on and responding to other comments here === > Do we /know/ that something that's phase-divergent is only divergent by phase? or could the content also be different? Is it possible to have a case in the tests that's both content-divergent and phase-divergent? I think that it's possible to be both at the same time. I'll spend some time coming up with the situation to explain it, but most of the time it's not the case as I recall. > I guess most users use source control are even aware of the "phase" concept so it might be nice to hide that word from UI. I disagree. `hg amend` --> `abort: cannot amend public changesets` We already expose phases in the UI and I argue that it's a good thing. Making users more aware of it and reusing the terminology I think is a good thing. > Maybe we can merge those two into divergent() to simplify the concept a user may face. This is kind of the direction we went. Instead of two separate concepts, "bumped" and "divergent", we now have two related concepts "content-divergent" and "phase-divergent". Both are "divergent", which means they need some similar kind of attention. The way it would be introduced in the docs is to explain the concept of divergence and then to explain the two types. However, I disagree with lumping all such types without exposing differences. I believe that will be more confusing since the way to arrive in the situation and the remedies are different. > We can think about alternative ways to display instability in the default log template. I'd love to hear what suggestions you have here (I lean towards "phase-divergent with f3967dc12" in the log so it's easy to figure out what the "other" version of you is). Conclusion == I feel that these decisions were made a long time ago. They were recorded on the wiki. We sent out emails about it for comments. We met up at the tail end of the last sprint both at the sprint venue and in a follow-up for anyone who cared enough at the time, up at the Atlassian office. No naming scheme will be perfect -- language is always a compromise -- but I think the names currently on the CEDVocabulary page are quite good, significant improvements over what we currently have, and have been discussed for hours by experts who care, and I think we should stick with them. Unless someone proposes a new name that pretty much everyone agrees is better -- and that hasn't happened here -- I think we should stick with the current naming on the Wiki. REPOSITORY rHG Mercurial REVISION DETAIL https://phab.mercurial-scm.org/D216 To: lothiraldan, #hg-reviewers, ryanmce Cc: ryanmce, martinvonz, quark, durin42, mercurial-devel ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel