Mercurial > hg
changeset 33736:86aca74a063b
merge with stable
author | Augie Fackler <augie@google.com> |
---|---|
date | Thu, 10 Aug 2017 14:23:41 -0400 |
parents | e6d8ee3c9ec3 (diff) 98e990bb7330 (current diff) |
children | 02a745c20121 |
files | hgext/rebase.py mercurial/cmdutil.py mercurial/ui.py mercurial/util.py tests/test-extension.t |
diffstat | 84 files changed, 1740 insertions(+), 696 deletions(-) [+] |
line wrap: on
line diff
--- a/Makefile Thu Aug 10 14:23:25 2017 -0400 +++ b/Makefile Thu Aug 10 14:23:41 2017 -0400 @@ -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 \
--- a/contrib/buildrpm Thu Aug 10 14:23:25 2017 -0400 +++ b/contrib/buildrpm Thu Aug 10 14:23:41 2017 -0400 @@ -11,6 +11,8 @@ BUILD=1 RPMBUILDDIR="$PWD/rpmbuild" +export HGPLAIN= + while [ "$1" ]; do case "$1" in --prepare )
--- a/contrib/mercurial.spec Thu Aug 10 14:23:25 2017 -0400 +++ b/contrib/mercurial.spec Thu Aug 10 14:23:41 2017 -0400 @@ -83,6 +83,7 @@ %endif make all +make -C contrib/chg %install rm -rf $RPM_BUILD_ROOT @@ -111,6 +112,7 @@ %endif +install -m 755 contrib/chg/chg $RPM_BUILD_ROOT%{_bindir}/ install -m 755 contrib/hgk $RPM_BUILD_ROOT%{_bindir}/ install -m 755 contrib/hg-ssh $RPM_BUILD_ROOT%{_bindir}/ @@ -143,6 +145,7 @@ %{_datadir}/emacs/site-lisp/mercurial.el %{_datadir}/emacs/site-lisp/mq.el %{_bindir}/hg +%{_bindir}/chg %{_bindir}/hgk %{_bindir}/hg-ssh %dir %{_sysconfdir}/bash_completion.d/
--- a/contrib/phabricator.py Thu Aug 10 14:23:25 2017 -0400 +++ b/contrib/phabricator.py Thu Aug 10 14:23:41 2017 -0400 @@ -41,7 +41,7 @@ encoding, error, mdiff, - obsolete, + obsutil, patch, registrar, scmutil, @@ -138,70 +138,84 @@ _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 - precnodes = list(obsolete.allprecursors(unfi.obsstore, [node])) + precnodes = list(obsutil.allpredecessors(unfi.obsstore, [node])) for n in precnodes: if n in nodemap: 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): tagname = 'D%d' % drev tags.tag(repo, tagname, nullid, message=None, user=None, date=None, local=True) unfi.ui.warn(_('D%s: local tag removed - does not match ' 'Differential history\n') % drev) + continue + + # Find the last node using Phabricator metadata, and make sure it + # exists in the repo + oldnode = lastdiff = None + if diffs: + lastdiff = max(diffs, key=lambda d: int(d[r'id'])) + oldnode = getnode(lastdiff) + if oldnode and oldnode not in nodemap: + oldnode = None + + result[newnode] = (oldnode, lastdiff, drev) return result @@ -241,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 @@ -265,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 @@ -313,7 +334,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,6 +348,13 @@ 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) @@ -333,13 +362,21 @@ 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: phids = userphids(repo, reviewers) actions.append({'type': 'reviewers.add', 'value': phids}) - oldnodedrev = getoldnodedrevmap(repo, [repo[r].node() for r in revs]) + # {newnode: (oldnode, olddiff, olddrev} + oldmap = getoldnodedrevmap(repo, [repo[r].node() for r in revs]) # Send patches one by one so we know their Differential Revision IDs and # can provide dependency relationship @@ -349,11 +386,11 @@ ctx = repo[rev] # Get Differential Revision ID - oldnode, revid = oldnodedrev.get(ctx.node(), (None, None)) + 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, actions) + oldnode, olddiff, actions) newrevid = int(revision[r'object'][r'id']) if revid: action = _('updated') @@ -379,6 +416,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)?' + '$$ &Yes $$ &No')): + return False + + return True + def querydrev(repo, params, stack=False): """return a list of "Differential Revision" dicts
--- a/hgext/rebase.py Thu Aug 10 14:23:25 2017 -0400 +++ b/hgext/rebase.py Thu Aug 10 14:23:41 2017 -0400 @@ -479,12 +479,17 @@ editopt = True editor = cmdutil.getcommiteditor(edit=editopt, editform=editform) revtoreuse = max(self.state) - newnode = concludenode(repo, revtoreuse, p1, self.external, - commitmsg=commitmsg, - extrafn=_makeextrafn(self.extrafns), - editor=editor, - keepbranches=self.keepbranchesf, - date=self.date) + + dsguard = None + if ui.configbool('rebase', 'singletransaction'): + dsguard = dirstateguard.dirstateguard(repo, 'rebase') + with util.acceptintervention(dsguard): + newnode = concludenode(repo, revtoreuse, p1, self.external, + commitmsg=commitmsg, + extrafn=_makeextrafn(self.extrafns), + editor=editor, + keepbranches=self.keepbranchesf, + date=self.date) if newnode is None: newrev = self.dest else: @@ -711,10 +716,16 @@ return retcode tr = None - if ui.configbool('rebase', 'singletransaction'): + dsguard = None + + singletr = ui.configbool('rebase', 'singletransaction') + if singletr: tr = repo.transaction('rebase') with util.acceptintervention(tr): - rbsrt._performrebase(tr) + if singletr: + dsguard = dirstateguard.dirstateguard(repo, 'rebase') + with util.acceptintervention(dsguard): + rbsrt._performrebase(tr) rbsrt._finishrebase() @@ -841,8 +852,10 @@ '''Commit the wd changes with parents p1 and p2. Reuse commit info from rev but also store useful information in extra. Return node of committed revision.''' - dsguard = dirstateguard.dirstateguard(repo, 'rebase') - try: + dsguard = util.nullcontextmanager() + if not repo.ui.configbool('rebase', 'singletransaction'): + dsguard = dirstateguard.dirstateguard(repo, 'rebase') + with dsguard: repo.setparents(repo[p1].node(), repo[p2].node()) ctx = repo[rev] if commitmsg is None: @@ -864,10 +877,7 @@ date=date, extra=extra, editor=editor) repo.dirstate.setbranch(repo[newnode].branch()) - dsguard.close() return newnode - finally: - release(dsguard) def rebasenode(repo, rev, p1, base, state, collapse, dest): 'Rebase a single revision rev on top of p1 using base as merge ancestor'
--- a/hgext/releasenotes.py Thu Aug 10 14:23:25 2017 -0400 +++ b/hgext/releasenotes.py Thu Aug 10 14:23:41 2017 -0400 @@ -46,6 +46,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 +93,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 +103,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 +155,77 @@ 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 exists in notes file; ignoring\n') + % incoming_str) + return True + else: + return False + else: + return False + +def similaritycheck(incoming_str, existingnotes): + """ + Returns true when note fragment can be merged to existing notes. + """ + import fuzzywuzzy.fuzz as fuzz + merge = True + for bullet in existingnotes: + score = fuzz.token_set_ratio(incoming_str, bullet) + if score > 75: + merge = False + break + return merge + def getcustomadmonitions(repo): ctx = repo['.'] p = config.config()
--- a/hgext/sparse.py Thu Aug 10 14:23:25 2017 -0400 +++ b/hgext/sparse.py Thu Aug 10 14:23:41 2017 -0400 @@ -155,7 +155,8 @@ 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)
--- a/i18n/check-translation.py Thu Aug 10 14:23:25 2017 -0400 +++ b/i18n/check-translation.py Thu Aug 10 14:23:41 2017 -0400 @@ -51,7 +51,7 @@ ... msgstr='prompt missing &sep$$missing amp$$followed by none&') >>> match(promptchoice, pe) True - >>> for e in promptchoice(pe): print e + >>> for e in promptchoice(pe): print(e) number of choices differs between msgid and msgstr msgstr has invalid choice missing '&' msgstr has invalid '&' followed by none @@ -88,19 +88,19 @@ ... msgstr= 'something (DEPRECATED)') >>> match(deprecated, pe) True - >>> for e in deprecated(pe): print e + >>> for e in deprecated(pe): print(e) >>> pe = polib.POEntry( ... msgid = 'Something (DEPRECATED)', ... msgstr= 'something (DETACERPED)') >>> match(deprecated, pe) True - >>> for e in deprecated(pe): print e + >>> for e in deprecated(pe): print(e) >>> pe = polib.POEntry( ... msgid = 'Something (DEPRECATED)', ... msgstr= 'something') >>> match(deprecated, pe) True - >>> for e in deprecated(pe): print e + >>> for e in deprecated(pe): print(e) msgstr inconsistently translated (DEPRECATED) >>> pe = polib.POEntry( ... msgid = 'Something (DEPRECATED, foo bar)', @@ -124,16 +124,16 @@ >>> pe = polib.POEntry( ... msgid ='ends with ::', ... msgstr='ends with ::') - >>> for e in taildoublecolons(pe): print e + >>> for e in taildoublecolons(pe): print(e) >>> pe = polib.POEntry( ... msgid ='ends with ::', ... msgstr='ends without double-colons') - >>> for e in taildoublecolons(pe): print e + >>> for e in taildoublecolons(pe): print(e) tail '::'-ness differs between msgid and msgstr >>> pe = polib.POEntry( ... msgid ='ends without double-colons', ... msgstr='ends with ::') - >>> for e in taildoublecolons(pe): print e + >>> for e in taildoublecolons(pe): print(e) tail '::'-ness differs between msgid and msgstr """ if pe.msgid.endswith('::') != pe.msgstr.endswith('::'): @@ -149,7 +149,7 @@ >>> pe = polib.POEntry( ... msgid =' indented text', ... msgstr=' narrowed indentation') - >>> for e in indentation(pe): print e + >>> for e in indentation(pe): print(e) initial indentation width differs betweeen msgid and msgstr """ idindent = len(pe.msgid) - len(pe.msgid.lstrip())
--- a/mercurial/bundle2.py Thu Aug 10 14:23:25 2017 -0400 +++ b/mercurial/bundle2.py Thu Aug 10 14:23:41 2017 -0400 @@ -145,7 +145,7 @@ preserve. """ -from __future__ import absolute_import +from __future__ import absolute_import, division import errno import re @@ -296,9 +296,32 @@ self.repo = repo self.ui = repo.ui self.records = unbundlerecords() - self.gettransaction = transactiongetter self.reply = None self.captureoutput = captureoutput + self.hookargs = {} + self._gettransaction = transactiongetter + + def gettransaction(self): + transaction = self._gettransaction() + + if self.hookargs is not None: + # the ones added to the transaction supercede those added + # to the operation. + self.hookargs.update(transaction.hookargs) + transaction.hookargs = self.hookargs + + # mark the hookargs as flushed. further attempts to add to + # hookargs will result in an abort. + self.hookargs = None + + return transaction + + def addhookargs(self, hookargs): + if self.hookargs is None: + raise error.Abort( + _('attempted to add hooks to operation after transaction ' + 'started')) + self.hookargs.update(hookargs) class TransactionUnavailable(RuntimeError): pass @@ -468,7 +491,8 @@ if output: outpart = op.reply.newpart('output', data=output, mandatory=False) - outpart.addparam('in-reply-to', str(part.id), mandatory=False) + outpart.addparam( + 'in-reply-to', pycompat.bytestr(part.id), mandatory=False) # If exiting or interrupted, do not attempt to seek the stream in the # finally block below. This makes abort faster. except (SystemExit, KeyboardInterrupt): @@ -976,7 +1000,7 @@ parttype = self.type.upper() else: parttype = self.type.lower() - outdebug(ui, 'part %s: "%s"' % (self.id, parttype)) + outdebug(ui, 'part %s: "%s"' % (pycompat.bytestr(self.id), parttype)) ## parttype header = [_pack(_fparttypesize, len(parttype)), parttype, _pack(_fpartid, self.id), @@ -994,7 +1018,7 @@ for key, value in advpar: parsizes.append(len(key)) parsizes.append(len(value)) - paramsizes = _pack(_makefpartparamsizes(len(parsizes) / 2), *parsizes) + paramsizes = _pack(_makefpartparamsizes(len(parsizes) // 2), *parsizes) header.append(paramsizes) # key, value for key, value in manpar: @@ -1021,11 +1045,12 @@ ui.debug('bundle2-generatorexit\n') raise except BaseException as exc: + bexc = util.forcebytestr(exc) # backup exception data for later ui.debug('bundle2-input-stream-interrupt: encoding exception %s' - % exc) + % bexc) tb = sys.exc_info()[2] - msg = 'unexpected error: %s' % exc + msg = 'unexpected error: %s' % bexc interpart = bundlepart('error:abort', [('message', msg)], mandatory=False) interpart.id = 0 @@ -1047,7 +1072,8 @@ Exists to handle the different methods to provide data to a part.""" # we only support fixed size data now. # This will be improved in the future. - if util.safehasattr(self.data, 'next'): + if (util.safehasattr(self.data, 'next') + or util.safehasattr(self.data, '__next__')): buff = util.chunkbuffer(self.data) chunk = buff.read(preferedchunksize) while chunk: @@ -1213,7 +1239,7 @@ self.type = self._fromheader(typesize) indebug(self.ui, 'part type: "%s"' % self.type) self.id = self._unpackheader(_fpartid)[0] - indebug(self.ui, 'part id: "%s"' % self.id) + indebug(self.ui, 'part id: "%s"' % pycompat.bytestr(self.id)) # extract mandatory bit from type self.mandatory = (self.type != self.type.lower()) self.type = self.type.lower() @@ -1225,7 +1251,7 @@ fparamsizes = _makefpartparamsizes(mancount + advcount) paramsizes = self._unpackheader(fparamsizes) # make it a list of couple again - paramsizes = zip(paramsizes[::2], paramsizes[1::2]) + paramsizes = list(zip(paramsizes[::2], paramsizes[1::2])) # split mandatory from advisory mansizes = paramsizes[:mancount] advsizes = paramsizes[mancount:] @@ -1554,7 +1580,8 @@ # This is definitely not the final form of this # return. But one need to start somewhere. part = op.reply.newpart('reply:changegroup', mandatory=False) - part.addparam('in-reply-to', str(inpart.id), mandatory=False) + part.addparam( + 'in-reply-to', pycompat.bytestr(inpart.id), mandatory=False) part.addparam('return', '%i' % ret, mandatory=False) assert not inpart.read() @@ -1617,7 +1644,8 @@ # This is definitely not the final form of this # return. But one need to start somewhere. part = op.reply.newpart('reply:changegroup') - part.addparam('in-reply-to', str(inpart.id), mandatory=False) + part.addparam( + 'in-reply-to', pycompat.bytestr(inpart.id), mandatory=False) part.addparam('return', '%i' % ret, mandatory=False) try: real_part.validate() @@ -1760,7 +1788,8 @@ op.records.add('pushkey', record) if op.reply is not None: rpart = op.reply.newpart('reply:pushkey') - rpart.addparam('in-reply-to', str(inpart.id), mandatory=False) + rpart.addparam( + 'in-reply-to', pycompat.bytestr(inpart.id), mandatory=False) rpart.addparam('return', '%i' % ret, mandatory=False) if inpart.mandatory and not ret: kwargs = {} @@ -1815,7 +1844,8 @@ op.records.add('obsmarkers', {'new': new}) if op.reply is not None: rpart = op.reply.newpart('reply:obsmarkers') - rpart.addparam('in-reply-to', str(inpart.id), mandatory=False) + rpart.addparam( + 'in-reply-to', pycompat.bytestr(inpart.id), mandatory=False) rpart.addparam('new', '%i' % new, mandatory=False) @@ -1849,3 +1879,17 @@ cache.write() op.ui.debug('applied %i hgtags fnodes cache entries\n' % count) + +@parthandler('pushvars') +def bundle2getvars(op, part): + '''unbundle a bundle2 containing shellvars on the server''' + # An option to disable unbundling on server-side for security reasons + if op.ui.configbool('push', 'pushvars.server', False): + hookargs = {} + for key, value in part.advisoryparams: + key = key.upper() + # We want pushed variables to have USERVAR_ prepended so we know + # they came from the --pushvar flag. + key = "USERVAR_" + key + hookargs[key] = value + op.addhookargs(hookargs)
--- a/mercurial/changegroup.py Thu Aug 10 14:23:25 2017 -0400 +++ b/mercurial/changegroup.py Thu Aug 10 14:23:41 2017 -0400 @@ -266,7 +266,8 @@ # in this function. srctype = tr.hookargs.setdefault('source', srctype) url = tr.hookargs.setdefault('url', url) - repo.hook('prechangegroup', throw=True, **tr.hookargs) + repo.hook('prechangegroup', + throw=True, **pycompat.strkwargs(tr.hookargs)) # write changelog data to temp files so concurrent readers # will not see an inconsistent view @@ -353,7 +354,8 @@ hookargs = dict(tr.hookargs) hookargs['node'] = hex(cl.node(clstart)) hookargs['node_last'] = hex(cl.node(clend - 1)) - repo.hook('pretxnchangegroup', throw=True, **hookargs) + repo.hook('pretxnchangegroup', + throw=True, **pycompat.strkwargs(hookargs)) added = [cl.node(r) for r in xrange(clstart, clend)] phaseall = None @@ -388,13 +390,13 @@ if clstart >= len(repo): return - repo.hook("changegroup", **hookargs) + repo.hook("changegroup", **pycompat.strkwargs(hookargs)) for n in added: args = hookargs.copy() args['node'] = hex(n) del args['node_last'] - repo.hook("incoming", **args) + repo.hook("incoming", **pycompat.strkwargs(args)) newheads = [h for h in repo.heads() if h not in oldheads]
--- a/mercurial/cmdutil.py Thu Aug 10 14:23:25 2017 -0400 +++ b/mercurial/cmdutil.py Thu Aug 10 14:23:41 2017 -0400 @@ -467,12 +467,12 @@ return True def isignoreddir(localpath): - """ - This function checks whether the directory contains only ignored files - and hence should the directory be considered ignored. Returns True, if - that should be ignored otherwise False. + """Return True if `localpath` directory is ignored or contains only + ignored files and should hence be considered ignored. """ dirpath = os.path.join(root, localpath) + if ignorefn(dirpath): + return True for f in os.listdir(dirpath): filepath = os.path.join(dirpath, f) if os.path.isdir(filepath): @@ -1465,10 +1465,10 @@ labels = ['log.changeset', 'changeset.%s' % ctx.phasestr()] if ctx.obsolete(): labels.append('changeset.obsolete') - if ctx.troubled(): + if ctx.isunstable(): labels.append('changeset.troubled') - for trouble in ctx.troubles(): - labels.append('trouble.%s' % trouble) + for instability in ctx.instabilities(): + labels.append('trouble.%s' % instability) return ' '.join(labels) class changeset_printer(object): @@ -1578,9 +1578,10 @@ self.ui.write(_("date: %s\n") % date, label='log.date') - if ctx.troubled(): + if ctx.isunstable(): # i18n: column positioning for "hg log" - self.ui.write(_("trouble: %s\n") % ', '.join(ctx.troubles()), + instabilities = ctx.instabilities() + self.ui.write(_("instability: %s\n") % ', '.join(instabilities), label='log.trouble') self._exthook(ctx) @@ -1913,7 +1914,7 @@ To be used by debug function.""" if index is not None: fm.write('index', '%i ', index) - fm.write('precnode', '%s ', hex(marker.precnode())) + fm.write('precnode', '%s ', hex(marker.prednode())) succs = marker.succnodes() fm.condwrite(succs, 'succnodes', '%s ', fm.formatlist(map(hex, succs), name='node'))
--- a/mercurial/color.py Thu Aug 10 14:23:25 2017 -0400 +++ b/mercurial/color.py Thu Aug 10 14:23:41 2017 -0400 @@ -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()
--- a/mercurial/commands.py Thu Aug 10 14:23:25 2017 -0400 +++ b/mercurial/commands.py Thu Aug 10 14:23:41 2017 -0400 @@ -1644,8 +1644,8 @@ samplehgrc = uimod.samplehgrcs['user'] f = paths[0] - fp = open(f, "w") - fp.write(samplehgrc) + fp = open(f, "wb") + fp.write(util.tonativeeol(samplehgrc)) fp.close() editor = ui.geteditor() @@ -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 + ``HG_USERVAR_ENABLE_FEATURE=true`` as part of their environment. + + pushvars can provide for user-overridable hooks as well as set debug + levels. One example is having a hook that blocks commits containing + conflict markers, but enables the user to override the hook if the file + is using conflict markers for testing purposes or the file format has + strings that look like conflict markers. + + By default, servers will ignore `--pushvars`. To enable it add the + following to your configuration file + + [push] + pushvars.server = true + Returns 0 if push was successful, 1 if nothing to push. """ @@ -4059,11 +4079,28 @@ return not result finally: del repo._subtoppath + + pushvars = opts.get('pushvars') + if pushvars: + shellvars = {} + for raw in pushvars: + if '=' not in raw: + msg = ("unable to parse variable '%s', should follow " + "'KEY=VALUE' or 'KEY=' format") + raise error.Abort(msg % raw) + k, v = raw.split('=', 1) + shellvars[k] = v + + repo._shellvars = shellvars + pushop = exchange.push(repo, other, opts.get('force'), revs=revs, newbranch=opts.get('new_branch'), bookmarks=opts.get('bookmark', ()), opargs=opts.get('opargs')) + if pushvars: + del repo._shellvars + result = not pushop.cgresult if pushop.bkresult is not None: @@ -4812,10 +4849,11 @@ ui.write(_(' (no revision checked out)')) if p.obsolete(): ui.write(_(' (obsolete)')) - if p.troubled(): + if p.isunstable(): + instabilities = (ui.label(instability, 'trouble.%s' % instability) + for instability in p.instabilities()) ui.write(' (' - + ', '.join(ui.label(trouble, 'trouble.%s' % trouble) - for trouble in p.troubles()) + + ', '.join(instabilities) + ')') ui.write('\n') if p.description(): @@ -4941,9 +4979,9 @@ numtrouble = len(repo.revs(trouble + "()")) # We write all the possibilities to ease translation troublemsg = { - "unstable": _("unstable: %d changesets"), - "divergent": _("divergent: %d changesets"), - "bumped": _("bumped: %d changesets"), + "unstable": _("orphan: %d changesets"), + "divergent": _("content-divergent: %d changesets"), + "bumped": _("phase-divergent: %d changesets"), } if numtrouble > 0: ui.status(troublemsg[trouble] % numtrouble + "\n")
--- a/mercurial/context.py Thu Aug 10 14:23:25 2017 -0400 +++ b/mercurial/context.py Thu Aug 10 14:23:41 2017 -0400 @@ -204,10 +204,22 @@ return self.rev() in obsmod.getrevs(self._repo, 'extinct') def unstable(self): + msg = ("'context.unstable' is deprecated, " + "use 'context.orphan'") + self._repo.ui.deprecwarn(msg, '4.4') + return self.orphan() + + def orphan(self): """True if the changeset is not obsolete but it's ancestor are""" return self.rev() in obsmod.getrevs(self._repo, 'unstable') def bumped(self): + msg = ("'context.bumped' is deprecated, " + "use 'context.phasedivergent'") + self._repo.ui.deprecwarn(msg, '4.4') + return self.phasedivergent() + + def phasedivergent(self): """True if the changeset try to be a successor of a public changeset Only non-public and non-obsolete changesets may be bumped. @@ -215,6 +227,12 @@ return self.rev() in obsmod.getrevs(self._repo, 'bumped') def divergent(self): + msg = ("'context.divergent' is deprecated, " + "use 'context.contentdivergent'") + self._repo.ui.deprecwarn(msg, '4.4') + return self.contentdivergent() + + def contentdivergent(self): """Is a successors of a changeset with multiple possible successors set Only non-public and non-obsolete changesets may be divergent. @@ -222,26 +240,49 @@ return self.rev() in obsmod.getrevs(self._repo, 'divergent') def troubled(self): + msg = ("'context.troubled' is deprecated, " + "use 'context.isunstable'") + self._repo.ui.deprecwarn(msg, '4.4') + return self.unstable() + + def isunstable(self): """True if the changeset is either unstable, bumped or divergent""" - return self.unstable() or self.bumped() or self.divergent() + return self.orphan() or self.phasedivergent() or self.contentdivergent() def troubles(self): - """return the list of troubles affecting this changesets. - - Troubles are returned as strings. possible values are: - - unstable, - - bumped, - - divergent. + """Keep the old version around in order to avoid breaking extensions + about different return values. """ + msg = ("'context.troubles' is deprecated, " + "use 'context.instabilities'") + self._repo.ui.deprecwarn(msg, '4.4') + troubles = [] - if self.unstable(): - troubles.append('unstable') - if self.bumped(): + if self.orphan(): + troubles.append('orphan') + if self.phasedivergent(): troubles.append('bumped') - if self.divergent(): + if self.contentdivergent(): troubles.append('divergent') return troubles + def instabilities(self): + """return the list of instabilities affecting this changeset. + + Instabilities are returned as strings. possible values are: + - orphan, + - phase-divergent, + - content-divergent. + """ + instabilities = [] + if self.orphan(): + instabilities.append('orphan') + if self.phasedivergent(): + instabilities.append('phase-divergent') + if self.contentdivergent(): + instabilities.append('content-divergent') + return instabilities + def parents(self): """return contexts for each parent changeset""" return self._parents
--- a/mercurial/dagparser.py Thu Aug 10 14:23:25 2017 -0400 +++ b/mercurial/dagparser.py Thu Aug 10 14:23:41 2017 -0400 @@ -156,7 +156,7 @@ Error: >>> try: list(parsedag('+1 bad')) - ... except Exception, e: print e + ... except Exception, e: print(e) invalid character in dag description: bad... '''
--- a/mercurial/dirstate.py Thu Aug 10 14:23:25 2017 -0400 +++ b/mercurial/dirstate.py Thu Aug 10 14:23:41 2017 -0400 @@ -359,8 +359,7 @@ return key in self._map def __iter__(self): - for x in sorted(self._map): - yield x + return iter(sorted(self._map)) def items(self): return self._map.iteritems()
--- a/mercurial/dirstateguard.py Thu Aug 10 14:23:25 2017 -0400 +++ b/mercurial/dirstateguard.py Thu Aug 10 14:23:41 2017 -0400 @@ -43,6 +43,16 @@ # ``release(tr, ....)``. self._abort() + def __enter__(self): + return self + + def __exit__(self, exc_type, exc_val, exc_tb): + try: + if exc_type is None: + self.close() + finally: + self.release() + def close(self): if not self._active: # already inactivated msg = (_("can't close already inactivated backup: %s")
--- a/mercurial/exchange.py Thu Aug 10 14:23:25 2017 -0400 +++ b/mercurial/exchange.py Thu Aug 10 14:23:41 2017 -0400 @@ -433,16 +433,13 @@ " %s") % (', '.join(sorted(missing))) raise error.Abort(msg) - # there are two ways to push to remote repo: - # - # addchangegroup assumes local user can lock remote - # repo (local filesystem, old ssh servers). - # - # unbundle assumes local user cannot lock remote repo (new ssh - # servers, http servers). - if not pushop.remote.canpush(): raise error.Abort(_("destination does not support push")) + + if not pushop.remote.capable('unbundle'): + raise error.Abort(_('cannot push: destination does not support the ' + 'unbundle wire protocol command')) + # get local lock as we might write phase data localwlock = locallock = None try: @@ -468,21 +465,14 @@ 'push-response', pushop.remote.url()) pushop.repo.checkpush(pushop) - lock = None - unbundle = pushop.remote.capable('unbundle') - if not unbundle: - lock = pushop.remote.lock() - try: - _pushdiscovery(pushop) - if not _forcebundle1(pushop): - _pushbundle2(pushop) - _pushchangeset(pushop) - _pushsyncphase(pushop) - _pushobsolete(pushop) - _pushbookmark(pushop) - finally: - if lock is not None: - lock.release() + _pushdiscovery(pushop) + if not _forcebundle1(pushop): + _pushbundle2(pushop) + _pushchangeset(pushop) + _pushsyncphase(pushop) + _pushobsolete(pushop) + _pushbookmark(pushop) + if pushop.trmanager: pushop.trmanager.close() finally: @@ -677,9 +667,11 @@ if unfi.obsstore: # this message are here for 80 char limit reason mso = _("push includes obsolete changeset: %s!") - mst = {"unstable": _("push includes unstable changeset: %s!"), - "bumped": _("push includes bumped changeset: %s!"), - "divergent": _("push includes divergent changeset: %s!")} + mspd = _("push includes phase-divergent changeset: %s!") + mscd = _("push includes content-divergent changeset: %s!") + mst = {"orphan": _("push includes orphan 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 # least one of the missinghead will be obsolete or @@ -688,8 +680,10 @@ ctx = unfi[node] if ctx.obsolete(): raise error.Abort(mso % ctx) - elif ctx.troubled(): - raise error.Abort(mst[ctx.troubles()[0]] % ctx) + elif ctx.isunstable(): + # TODO print more than one instability in the abort + # message + raise error.Abort(mst[ctx.instabilities()[0]] % ctx) discovery.checkheads(pushop) return True @@ -891,6 +885,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 @@ -948,9 +950,12 @@ pushop.stepsdone.add('changesets') if not _pushcheckoutgoing(pushop): return + + # Should have verified this in push(). + assert pushop.remote.capable('unbundle') + pushop.repo.prepushoutgoinghooks(pushop) outgoing = pushop.outgoing - unbundle = pushop.remote.capable('unbundle') # TODO: get bundlecaps from remote bundlecaps = None # create a changegroup from local @@ -969,24 +974,18 @@ bundlecaps=bundlecaps) # apply changegroup to remote - if unbundle: - # local repo finds heads on server, finds out what - # revs it must push. once revs transferred, if server - # finds it has different heads (someone else won - # commit/push race), server aborts. - if pushop.force: - remoteheads = ['force'] - else: - remoteheads = pushop.remoteheads - # ssh: return remote's addchangegroup() - # http: return remote's addchangegroup() or 0 for error - pushop.cgresult = pushop.remote.unbundle(cg, remoteheads, - pushop.repo.url()) + # local repo finds heads on server, finds out what + # revs it must push. once revs transferred, if server + # finds it has different heads (someone else won + # commit/push race), server aborts. + if pushop.force: + remoteheads = ['force'] else: - # we return an integer indicating remote head count - # change - pushop.cgresult = pushop.remote.addchangegroup(cg, 'push', - pushop.repo.url()) + remoteheads = pushop.remoteheads + # ssh: return remote's addchangegroup() + # http: return remote's addchangegroup() or 0 for error + pushop.cgresult = pushop.remote.unbundle(cg, remoteheads, + pushop.repo.url()) def _pushsyncphase(pushop): """synchronise phase information locally and remotely""" @@ -1229,8 +1228,10 @@ opargs = {} pullop = pulloperation(repo, remote, heads, force, bookmarks=bookmarks, streamclonerequested=streamclonerequested, **opargs) - if pullop.remote.local(): - missing = set(pullop.remote.requirements) - pullop.repo.supported + + peerlocal = pullop.remote.local() + if peerlocal: + missing = set(peerlocal.requirements) - pullop.repo.supported if missing: msg = _("required features are not" " supported in the destination:"
--- a/mercurial/extensions.py Thu Aug 10 14:23:25 2017 -0400 +++ b/mercurial/extensions.py Thu Aug 10 14:23:41 2017 -0400 @@ -19,7 +19,6 @@ from . import ( cmdutil, configitems, - encoding, error, pycompat, util, @@ -114,16 +113,11 @@ mod = _importh(name) return mod -def _forbytes(inst): - """Portably format an import error into a form suitable for - %-formatting into bytestrings.""" - return encoding.strtolocal(str(inst)) - def _reportimporterror(ui, err, failed, next): # note: this ui.debug happens before --debug is processed, # Use --config ui.debug=1 to see them. ui.debug('could not import %s (%s): trying %s\n' - % (failed, _forbytes(err), next)) + % (failed, util.forcebytestr(err), next)) if ui.debugflag: ui.traceback() @@ -180,7 +174,7 @@ uisetup(ui) except Exception as inst: ui.traceback() - msg = _forbytes(inst) + msg = util.forcebytestr(inst) ui.warn(_("*** failed to set up extension %s: %s\n") % (name, msg)) return False return True @@ -192,12 +186,16 @@ try: extsetup(ui) except TypeError: - if inspect.getargspec(extsetup).args: + # Try to use getfullargspec (Python 3) first, and fall + # back to getargspec only if it doesn't exist so as to + # avoid warnings. + if getattr(inspect, 'getfullargspec', + getattr(inspect, 'getargspec'))(extsetup).args: raise extsetup() # old extsetup with no ui argument except Exception as inst: ui.traceback() - msg = _forbytes(inst) + msg = util.forcebytestr(inst) ui.warn(_("*** failed to set up extension %s: %s\n") % (name, msg)) return False return True @@ -215,7 +213,7 @@ try: load(ui, name, path) except Exception as inst: - msg = _forbytes(inst) + msg = util.forcebytestr(inst) if path: ui.warn(_("*** failed to import extension %s from %s: %s\n") % (name, path, msg)) @@ -256,6 +254,7 @@ from . import ( color, commands, + filemerge, fileset, revset, templatefilters, @@ -274,6 +273,7 @@ ('colortable', color, 'loadcolortable'), ('configtable', configitems, 'loadconfigtable'), ('filesetpredicate', fileset, 'loadpredicate'), + ('internalmerge', filemerge, 'loadinternalmerge'), ('revsetpredicate', revset, 'loadpredicate'), ('templatefilter', templatefilters, 'loadfilter'), ('templatefunc', templater, 'loadfunction'),
--- a/mercurial/filemerge.py Thu Aug 10 14:23:25 2017 -0400 +++ b/mercurial/filemerge.py Thu Aug 10 14:23:41 2017 -0400 @@ -21,6 +21,7 @@ formatter, match, pycompat, + registrar, scmutil, simplemerge, tagmerge, @@ -44,10 +45,12 @@ # Merge tools to document. internalsdoc = {} +internaltool = registrar.internalmerge() + # internal tool merge types -nomerge = None -mergeonly = 'mergeonly' # just the full merge, no premerge -fullmerge = 'fullmerge' # both premerge and merge +nomerge = internaltool.nomerge +mergeonly = internaltool.mergeonly # just the full merge, no premerge +fullmerge = internaltool.fullmerge # both premerge and merge _localchangedotherdeletedmsg = _( "local%(l)s changed %(fd)s which other%(o)s deleted\n" @@ -104,21 +107,6 @@ def isabsent(self): return True -def internaltool(name, mergetype, onfailure=None, precheck=None): - '''return a decorator for populating internal merge tool table''' - def decorator(func): - fullname = ':' + name - func.__doc__ = (pycompat.sysstr("``%s``\n" % fullname) - + func.__doc__.strip()) - internals[fullname] = func - internals['internal:' + name] = func - internalsdoc[fullname] = func - func.mergetype = mergetype - func.onfailure = onfailure - func.precheck = precheck - return func - return decorator - def _findtool(ui, tool): if tool in internals: return tool @@ -743,5 +731,17 @@ def filemerge(repo, mynode, orig, fcd, fco, fca, labels=None): return _filemerge(False, repo, mynode, orig, fcd, fco, fca, labels=labels) +def loadinternalmerge(ui, extname, registrarobj): + """Load internal merge tool from specified registrarobj + """ + for name, func in registrarobj._table.iteritems(): + fullname = ':' + name + internals[fullname] = func + internals['internal:' + name] = func + internalsdoc[fullname] = func + +# load built-in merge tools explicitly to setup internalsdoc +loadinternalmerge(None, None, internaltool) + # tell hggettext to extract docstrings from these functions: i18nfunctions = internals.values()
--- a/mercurial/hg.py Thu Aug 10 14:23:25 2017 -0400 +++ b/mercurial/hg.py Thu Aug 10 14:23:41 2017 -0400 @@ -641,11 +641,11 @@ destrepo = destpeer.local() if destrepo: template = uimod.samplehgrcs['cloned'] - fp = destrepo.vfs("hgrc", "w", text=True) + fp = destrepo.vfs("hgrc", "wb") u = util.url(abspath) u.passwd = None - defaulturl = str(u) - fp.write(template % defaulturl) + defaulturl = bytes(u) + fp.write(util.tonativeeol(template % defaulturl)) fp.close() destrepo.ui.setconfig('paths', 'default', defaulturl, 'clone')
--- a/mercurial/httppeer.py Thu Aug 10 14:23:25 2017 -0400 +++ b/mercurial/httppeer.py Thu Aug 10 14:23:41 2017 -0400 @@ -88,11 +88,10 @@ class httppeer(wireproto.wirepeer): def __init__(self, ui, path): - self.path = path - self.caps = None - self.handler = None - self.urlopener = None - self.requestbuilder = None + self._path = path + self._caps = None + self._urlopener = None + self._requestbuilder = None u = util.url(path) if u.query or u.fragment: raise error.Abort(_('unsupported URL component: "%s"') % @@ -104,36 +103,33 @@ self.ui = ui self.ui.debug('using %s\n' % self._url) - self.urlopener = url.opener(ui, authinfo) - self.requestbuilder = urlreq.request + self._urlopener = url.opener(ui, authinfo) + self._requestbuilder = urlreq.request def __del__(self): - urlopener = getattr(self, 'urlopener', None) + urlopener = getattr(self, '_urlopener', None) if urlopener: for h in urlopener.handlers: h.close() getattr(h, "close_all", lambda : None)() def url(self): - return self.path + return self._path # look up capabilities only when needed def _fetchcaps(self): - self.caps = set(self._call('capabilities').split()) + self._caps = set(self._call('capabilities').split()) def _capabilities(self): - if self.caps is None: + if self._caps is None: try: self._fetchcaps() except error.RepoError: - self.caps = set() + self._caps = set() self.ui.debug('capabilities: %s\n' % - (' '.join(self.caps or ['none']))) - return self.caps - - def lock(self): - raise error.Abort(_('operation not supported over http')) + (' '.join(self._caps or ['none']))) + return self._caps def _callstream(self, cmd, _compressible=False, **args): if cmd == 'pushkey': @@ -148,7 +144,7 @@ # Important: don't use self.capable() here or else you end up # with infinite recursion when trying to look up capabilities # for the first time. - postargsok = self.caps is not None and 'httppostargs' in self.caps + 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) @@ -193,7 +189,7 @@ protoparams = [] mediatypes = set() - if self.caps is not None: + if self._caps is not None: mt = self.capable('httpmediatype') if mt: protoparams.append('0.1') @@ -221,13 +217,13 @@ if varyheaders: headers['Vary'] = ','.join(varyheaders) - req = self.requestbuilder(cu, data, headers) + req = self._requestbuilder(cu, data, headers) if data is not None: self.ui.debug("sending %s bytes\n" % size) req.add_unredirected_header('Content-Length', '%d' % size) try: - resp = self.urlopener.open(req) + resp = self._urlopener.open(req) except urlerr.httperror as inst: if inst.code == 401: raise error.Abort(_('authorization failed'))
--- a/mercurial/localrepo.py Thu Aug 10 14:23:25 2017 -0400 +++ b/mercurial/localrepo.py Thu Aug 10 14:23:41 2017 -0400 @@ -154,8 +154,6 @@ self._repo = repo.filtered('served') self.ui = repo.ui self._caps = repo._restrictcapabilities(caps) - self.requirements = repo.requirements - self.supportedformats = repo.supportedformats def close(self): self._repo.close() @@ -237,9 +235,6 @@ except error.PushRaced as exc: raise error.ResponseError(_('push failed:'), str(exc)) - def lock(self): - return self._repo.lock() - def pushkey(self, namespace, key, old, new): return self._repo.pushkey(namespace, key, old, new) @@ -1466,6 +1461,13 @@ # dirstate is invalidated separately in invalidatedirstate() if k == 'dirstate': continue + if (k == 'changelog' and + self.currenttransaction() and + self.changelog._delayed): + # The changelog object may store unwritten revisions. We don't + # want to lose them. + # TODO: Solve the problem instead of working around it. + continue if clearfilecache: del self._filecache[k]
--- a/mercurial/match.py Thu Aug 10 14:23:25 2017 -0400 +++ b/mercurial/match.py Thu Aug 10 14:23:41 2017 -0400 @@ -18,6 +18,11 @@ 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 @@ 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 @@ 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
--- a/mercurial/obsolete.py Thu Aug 10 14:23:25 2017 -0400 +++ b/mercurial/obsolete.py Thu Aug 10 14:23:41 2017 -0400 @@ -20,12 +20,12 @@ besides old and news changeset identifiers, such as creation date or author name. -The old obsoleted changeset is called a "precursor" and possible +The old obsoleted changeset is called a "predecessor" and possible replacements are called "successors". Markers that used changeset X as -a precursor are called "successor markers of X" because they hold +a predecessor are called "successor markers of X" because they hold information about the successors of X. Markers that use changeset Y as -a successors are call "precursor markers of Y" because they hold -information about the precursors of Y. +a successors are call "predecessor markers of Y" because they hold +information about the predecessors of Y. Examples: @@ -294,11 +294,11 @@ # # - uint8: number of metadata entries M # -# - 20 or 32 bytes: precursor changeset identifier. +# - 20 or 32 bytes: predecessor changeset identifier. # # - N*(20 or 32) bytes: successors changesets identifiers. # -# - P*(20 or 32) bytes: parents of the precursors changesets. +# - P*(20 or 32) bytes: parents of the predecessors changesets. # # - M*(uint8, uint8): size of all metadata entries (key and value) # @@ -314,7 +314,7 @@ _fm1parentshift = 14 _fm1parentmask = (_fm1parentnone << _fm1parentshift) _fm1metapair = 'BB' -_fm1metapairsize = _calcsize('BB') +_fm1metapairsize = _calcsize(_fm1metapair) def _fm1purereadmarkers(data, off, stop): # make some global constants local for performance @@ -470,11 +470,18 @@ for mark in markers: successors.setdefault(mark[0], set()).add(mark) +def _addprecursors(*args, **kwargs): + msg = ("'obsolete._addprecursors' is deprecated, " + "use 'obsolete._addpredecessors'") + util.nouideprecwarn(msg, '4.4') + + return _addpredecessors(*args, **kwargs) + @util.nogc -def _addprecursors(precursors, markers): +def _addpredecessors(predecessors, markers): for mark in markers: for suc in mark[1]: - precursors.setdefault(suc, set()).add(mark) + predecessors.setdefault(suc, set()).add(mark) @util.nogc def _addchildren(children, markers): @@ -499,18 +506,18 @@ """Store obsolete markers Markers can be accessed with two mappings: - - precursors[x] -> set(markers on precursors edges of x) + - predecessors[x] -> set(markers on predecessors edges of x) - successors[x] -> set(markers on successors edges of x) - - children[x] -> set(markers on precursors edges of children(x) + - children[x] -> set(markers on predecessors edges of children(x) """ fields = ('prec', 'succs', 'flag', 'meta', 'date', 'parents') - # prec: nodeid, precursor changesets + # prec: nodeid, predecessors changesets # succs: tuple of nodeid, successor changesets (0-N length) # flag: integer, flag field carrying modifier for the markers (see doc) # meta: binary blob, encoded metadata dictionary # date: (float, int) tuple, date of marker creation - # parents: (tuple of nodeid) or None, parents of precursors + # parents: (tuple of nodeid) or None, parents of predecessors # None is used when no data has been recorded def __init__(self, svfs, defaultformat=_fm1version, readonly=False): @@ -583,7 +590,7 @@ metadata = tuple(sorted(metadata.iteritems())) - marker = (str(prec), tuple(succs), int(flag), metadata, date, parents) + marker = (bytes(prec), tuple(succs), int(flag), metadata, date, parents) return bool(self.add(transaction, [marker])) def add(self, transaction, markers): @@ -658,11 +665,19 @@ _addsuccessors(successors, self._all) return successors - @propertycache + @property def precursors(self): - precursors = {} - _addprecursors(precursors, self._all) - return precursors + msg = ("'obsstore.precursors' is deprecated, " + "use 'obsstore.predecessors'") + util.nouideprecwarn(msg, '4.4') + + return self.predecessors + + @propertycache + def predecessors(self): + predecessors = {} + _addpredecessors(predecessors, self._all) + return predecessors @propertycache def children(self): @@ -679,8 +694,8 @@ self._all.extend(markers) if self._cached('successors'): _addsuccessors(self.successors, markers) - if self._cached('precursors'): - _addprecursors(self.precursors, markers) + if self._cached('predecessors'): + _addpredecessors(self.predecessors, markers) if self._cached('children'): _addchildren(self.children, markers) _checkinvalidmarkers(markers) @@ -692,14 +707,15 @@ - marker that use this changeset as successor - prune marker of direct children on this changeset - - recursive application of the two rules on precursors of these markers + - recursive application of the two rules on predecessors of these + markers It is a set so you cannot rely on order.""" pendingnodes = set(nodes) seenmarkers = set() seennodes = set(pendingnodes) - precursorsmarkers = self.precursors + precursorsmarkers = self.predecessors succsmarkers = self.successors children = self.children while pendingnodes: @@ -932,12 +948,12 @@ rev = ctx.rev() # We only evaluate mutable, non-obsolete revision node = ctx.node() - # (future) A cache of precursors may worth if split is very common - for pnode in obsutil.allprecursors(repo.obsstore, [node], + # (future) A cache of predecessors may worth if split is very common + for pnode in obsutil.allpredecessors(repo.obsstore, [node], ignoreflags=bumpedfix): prev = torev(pnode) # unfiltered! but so is phasecache if (prev is not None) and (phase(repo, prev) <= public): - # we have a public precursor + # we have a public predecessor bumped.add(rev) break # Next draft! return bumped @@ -950,7 +966,7 @@ obsstore = repo.obsstore newermap = {} for ctx in repo.set('(not public()) - obsolete()'): - mark = obsstore.precursors.get(ctx.node(), ()) + mark = obsstore.predecessors.get(ctx.node(), ()) toprocess = set(mark) seen = set() while toprocess: @@ -964,7 +980,7 @@ if len(newer) > 1: divergent.add(ctx.rev()) break - toprocess.update(obsstore.precursors.get(prec, ())) + toprocess.update(obsstore.predecessors.get(prec, ())) return divergent
--- a/mercurial/obsutil.py Thu Aug 10 14:23:25 2017 -0400 +++ b/mercurial/obsutil.py Thu Aug 10 14:23:41 2017 -0400 @@ -9,6 +9,7 @@ from . import ( phases, + util ) class marker(object): @@ -29,7 +30,13 @@ return self._data == other._data def precnode(self): - """Precursor changeset node identifier""" + msg = ("'marker.precnode' is deprecated, " + "use 'marker.precnode'") + util.nouideprecwarn(msg, '4.4') + return self.prednode() + + def prednode(self): + """Predecessor changeset node identifier""" return self._data[0] def succnodes(self): @@ -37,7 +44,7 @@ return self._data[1] def parentnodes(self): - """Parents of the precursors (None if not recorded)""" + """Parents of the predecessors (None if not recorded)""" return self._data[5] def metadata(self): @@ -74,7 +81,7 @@ considered missing. """ - precursors = repo.obsstore.precursors + precursors = repo.obsstore.predecessors stack = [nodeid] seen = set(stack) @@ -95,7 +102,16 @@ else: stack.append(precnodeid) -def allprecursors(obsstore, nodes, ignoreflags=0): +def allprecursors(*args, **kwargs): + """ (DEPRECATED) + """ + msg = ("'obsutil.allprecursors' is deprecated, " + "use 'obsutil.allpredecessors'") + util.nouideprecwarn(msg, '4.4') + + return allpredecessors(*args, **kwargs) + +def allpredecessors(obsstore, nodes, ignoreflags=0): """Yield node for every precursors of <nodes>. Some precursors may be unknown locally. @@ -108,7 +124,7 @@ while remaining: current = remaining.pop() yield current - for mark in obsstore.precursors.get(current, ()): + for mark in obsstore.predecessors.get(current, ()): # ignore marker flagged with specified flag if mark[2] & ignoreflags: continue @@ -200,7 +216,7 @@ # shortcut to various useful item nm = unfi.changelog.nodemap - precursorsmarkers = unfi.obsstore.precursors + precursorsmarkers = unfi.obsstore.predecessors successormarkers = unfi.obsstore.successors childrenmarkers = unfi.obsstore.children @@ -307,7 +323,7 @@ seenrevs.add(rev) if phase(repo, rev) == public: continue - if set(succsmarkers(node)).issubset(addedmarkers): + if set(succsmarkers(node) or []).issubset(addedmarkers): obsoleted.add(rev) return obsoleted
--- a/mercurial/registrar.py Thu Aug 10 14:23:25 2017 -0400 +++ b/mercurial/registrar.py Thu Aug 10 14:23:41 2017 -0400 @@ -308,3 +308,64 @@ def _extrasetup(self, name, func, argspec=None): func._argspec = argspec + +class internalmerge(_funcregistrarbase): + """Decorator to register in-process merge tool + + Usage:: + + internalmerge = registrar.internalmerge() + + @internalmerge('mymerge', internalmerge.mergeonly, + onfailure=None, precheck=None): + def mymergefunc(repo, mynode, orig, fcd, fco, fca, + toolconf, files, labels=None): + '''Explanation of this internal merge tool .... + ''' + return 1, False # means "conflicted", "no deletion needed" + + The first string argument is used to compose actual merge tool name, + ":name" and "internal:name" (the latter is historical one). + + The second argument is one of merge types below: + + ========== ======== ======== ========= + merge type precheck premerge fullmerge + ========== ======== ======== ========= + nomerge x x x + mergeonly o x o + fullmerge o o o + ========== ======== ======== ========= + + Optional argument 'onfalure' is the format of warning message + to be used at failure of merging (target filename is specified + at formatting). Or, None or so, if warning message should be + suppressed. + + Optional argument 'precheck' is the function to be used + before actual invocation of internal merge tool itself. + It takes as same arguments as internal merge tool does, other than + 'files' and 'labels'. If it returns false value, merging is aborted + immediately (and file is marked as "unresolved"). + + 'internalmerge' instance in example above can be used to + decorate multiple functions. + + Decorated functions are registered automatically at loading + extension, if an instance named as 'internalmerge' is used for + decorating in extension. + + Otherwise, explicit 'filemerge.loadinternalmerge()' is needed. + """ + _docformat = "``:%s``\n %s" + + # merge type definitions: + nomerge = None + mergeonly = 'mergeonly' # just the full merge, no premerge + fullmerge = 'fullmerge' # both premerge and merge + + def _extrasetup(self, name, func, mergetype, + onfailure=None, precheck=None): + func.mergetype = mergetype + func.onfailure = onfailure + func.precheck = precheck
--- a/mercurial/repair.py Thu Aug 10 14:23:25 2017 -0400 +++ b/mercurial/repair.py Thu Aug 10 14:23:41 2017 -0400 @@ -67,16 +67,20 @@ return sorted(files) +def _collectrevlog(revlog, striprev): + _, brokenset = revlog.getstrippoint(striprev) + return [revlog.linkrev(r) for r in brokenset] + +def _collectmanifest(repo, striprev): + return _collectrevlog(repo.manifestlog._revlog, striprev) + def _collectbrokencsets(repo, files, striprev): """return the changesets which will be broken by the truncation""" s = set() - def collectone(revlog): - _, brokenset = revlog.getstrippoint(striprev) - s.update([revlog.linkrev(r) for r in brokenset]) - collectone(repo.manifestlog._revlog) + s.update(_collectmanifest(repo, striprev)) for fname in files: - collectone(repo.file(fname)) + s.update(_collectrevlog(repo.file(fname), striprev)) return s @@ -174,16 +178,13 @@ tmpbundlefile = _bundle(repo, savebases, saveheads, node, 'temp', compress=False, obsolescence=False) - mfst = repo.manifestlog._revlog - try: with repo.transaction("strip") as tr: offset = len(tr.entries) tr.startgroup() cl.strip(striprev, tr) - mfst.strip(striprev, tr) - striptrees(repo, tr, striprev, files) + stripmanifest(repo, striprev, tr, files) for fn in files: repo.file(fn).strip(striprev, tr) @@ -310,6 +311,11 @@ callback.topic = topic callback.addnodes(nodelist) +def stripmanifest(repo, striprev, tr, files): + revlog = repo.manifestlog._revlog + revlog.strip(striprev, tr) + striptrees(repo, tr, striprev, files) + def striptrees(repo, tr, striprev, files): if 'treemanifest' in repo.requirements: # safe but unnecessary # otherwise
--- a/mercurial/sparse.py Thu Aug 10 14:23:25 2017 -0400 +++ b/mercurial/sparse.py Thu Aug 10 14:23:41 2017 -0400 @@ -17,6 +17,7 @@ error, match as matchmod, merge as mergemod, + pathutil, pycompat, scmutil, util, @@ -616,7 +617,7 @@ 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. @@ -636,10 +637,24 @@ 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 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: newexclude.update(pats)
--- a/mercurial/sshpeer.py Thu Aug 10 14:23:25 2017 -0400 +++ b/mercurial/sshpeer.py Thu Aug 10 14:23:41 2017 -0400 @@ -17,21 +17,6 @@ wireproto, ) -class remotelock(object): - def __init__(self, repo): - self.repo = repo - def release(self): - self.repo.unlock() - self.repo = None - def __enter__(self): - return self - def __exit__(self, exc_type, exc_val, exc_tb): - if self.repo: - self.release() - def __del__(self): - if self.repo: - self.release() - def _serverquote(s): if not s: return s @@ -337,33 +322,4 @@ self.pipeo.flush() self.readerr() - def lock(self): - self._call("lock") - return remotelock(self) - - def unlock(self): - self._call("unlock") - - def addchangegroup(self, cg, source, url, lock=None): - '''Send a changegroup to the remote server. Return an integer - similar to unbundle(). DEPRECATED, since it requires locking the - remote.''' - d = self._call("addchangegroup") - if d: - self._abort(error.RepoError(_("push refused: %s") % d)) - for d in iter(lambda: cg.read(4096), ''): - self.pipeo.write(d) - self.readerr() - - self.pipeo.flush() - - self.readerr() - r = self._recv() - if not r: - return 1 - try: - return int(r) - except ValueError: - self._abort(error.ResponseError(_("unexpected response:"), r)) - instance = sshpeer
--- a/mercurial/templatekw.py Thu Aug 10 14:23:25 2017 -0400 +++ b/mercurial/templatekw.py Thu Aug 10 14:23:41 2017 -0400 @@ -765,13 +765,25 @@ return repo.ui.termwidth() @templatekeyword('troubles') -def showtroubles(**args): +def showtroubles(repo, **args): """List of strings. Evolution troubles affecting the changeset. + (DEPRECATED) + """ + msg = ("'troubles' is deprecated, " + "use 'instabilities'") + repo.ui.deprecwarn(msg, '4.4') + + return showinstabilities(repo=repo, **args) + +@templatekeyword('instabilities') +def showinstabilities(**args): + """List of strings. Evolution instabilities affecting the changeset. + (EXPERIMENTAL) """ args = pycompat.byteskwargs(args) - return showlist('trouble', args['ctx'].troubles(), args) + return showlist('trouble', args['ctx'].instabilities(), args) # tell hggettext to extract docstrings from these functions: i18nfunctions = keywords.values()
--- a/mercurial/templates/map-cmdline.default Thu Aug 10 14:23:25 2017 -0400 +++ b/mercurial/templates/map-cmdline.default Thu Aug 10 14:23:41 2017 -0400 @@ -29,7 +29,7 @@ # General templates _trouble_label = 'trouble.{trouble}' -_troubles_labels = '{if(troubles, "changeset.troubled {troubles%_trouble_label}")}' +_troubles_labels = '{if(instabilities, "changeset.troubled {instabilities%_trouble_label}")}' _obsolete_label = '{if(obsolete, "changeset.obsolete")}' _cset_labels = '{separate(" ", "log.changeset", "changeset.{phase}", "{_obsolete_label}", "{_troubles_labels}")}' cset = '{label("{_cset_labels}", @@ -68,8 +68,8 @@ ldate = '{label("log.date", "date: {date|date}")}\n' -ltroubles = '{if(troubles, "{label('log.trouble', - 'trouble: {join(troubles, ", ")}')}\n")}' +ltroubles = '{if(instabilities, "{label('log.trouble', + 'instability: {join(instabilities, ", ")}')}\n")}' extra = '{label("ui.debug log.extra", "extra: {key}={value|stringescape}")}\n'
--- a/mercurial/ui.py Thu Aug 10 14:23:25 2017 -0400 +++ b/mercurial/ui.py Thu Aug 10 14:23:41 2017 -0400 @@ -60,7 +60,7 @@ samplehgrcs = { 'user': -"""# example user config (see 'hg help config' for more info) +b"""# example user config (see 'hg help config' for more info) [ui] # name and email, e.g. # username = Jane Doe <jdoe@example.com> @@ -82,7 +82,7 @@ """, 'cloned': -"""# example repository config (see 'hg help config' for more info) +b"""# example repository config (see 'hg help config' for more info) [paths] default = %s @@ -99,7 +99,7 @@ """, 'local': -"""# example repository config (see 'hg help config' for more info) +b"""# example repository config (see 'hg help config' for more info) [paths] # path aliases to other clones of this repo in URLs or filesystem paths # (see 'hg help config.paths' for more info) @@ -115,7 +115,7 @@ """, 'global': -"""# example system-wide hg config (see 'hg help config' for more info) +b"""# example system-wide hg config (see 'hg help config' for more info) [ui] # uncomment to disable color in command output @@ -1276,9 +1276,10 @@ m = re.match(br'(?s)(.+?)\$\$([^\$]*&[^ \$].*)', prompt) msg = m.group(1) choices = [p.strip(' ') for p in m.group(2).split('$$')] - return (msg, - [(s[s.index('&') + 1].lower(), s.replace('&', '', 1)) - for s in choices]) + def choicetuple(s): + ampidx = s.index('&') + return s[ampidx + 1:ampidx + 2].lower(), s.replace('&', '', 1) + return (msg, [choicetuple(s) for s in choices]) def promptchoice(self, prompt, default=0): """Prompt user with a message, read response, and ensure it matches
--- a/mercurial/util.py Thu Aug 10 14:23:25 2017 -0400 +++ b/mercurial/util.py Thu Aug 10 14:23:41 2017 -0400 @@ -610,6 +610,10 @@ finally: tr.release() +@contextlib.contextmanager +def nullcontextmanager(): + yield + class _lrucachenode(object): """A node in a doubly linked list. @@ -2272,6 +2276,15 @@ def unescapestr(s): return codecs.escape_decode(s)[0] +def forcebytestr(obj): + """Portably format an arbitrary object (e.g. exception) into a byte + string.""" + try: + return pycompat.bytestr(obj) + except UnicodeEncodeError: + # non-ascii string, may be lossy + return pycompat.bytestr(encoding.strtolocal(str(obj))) + def uirepr(s): # Avoid double backslash in Windows path repr() return repr(s).replace('\\\\', '\\')
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tests/bruterebase.py Thu Aug 10 14:23:41 2017 -0400 @@ -0,0 +1,69 @@ +# bruterebase.py - brute force rebase testing +# +# Copyright 2017 Facebook, Inc. +# +# This software may be used and distributed according to the terms of the +# GNU General Public License version 2 or any later version. + +from __future__ import absolute_import + +from mercurial import ( + error, + registrar, + revsetlang, +) + +from hgext import rebase + +cmdtable = {} +command = registrar.command(cmdtable) + +@command('debugbruterebase') +def debugbruterebase(ui, repo, source, dest): + """for every non-empty subset of source, run rebase -r subset -d dest + + Print one line summary for each subset. Assume obsstore is enabled. + """ + srevs = list(repo.revs(source)) + + with repo.wlock(), repo.lock(): + repolen = len(repo) + cl = repo.changelog + + def getdesc(rev): + result = cl.changelogrevision(rev).description + if rev >= repolen: + result += "'" + return result + + for i in xrange(1, 2 ** len(srevs)): + subset = [rev for j, rev in enumerate(srevs) if i & (1 << j) != 0] + spec = revsetlang.formatspec('%ld', subset) + tr = repo.transaction('rebase') + tr.report = lambda x: 0 # hide "transaction abort" + + ui.pushbuffer() + try: + rebase.rebase(ui, repo, dest=dest, rev=[spec]) + except error.Abort as ex: + summary = 'ABORT: %s' % ex + except Exception as ex: + summary = 'CRASH: %s' % ex + else: + # short summary about new nodes + cl = repo.changelog + descs = [] + for rev in xrange(repolen, len(repo)): + desc = '%s:' % getdesc(rev) + for prev in cl.parentrevs(rev): + if prev > -1: + desc += getdesc(prev) + descs.append(desc) + descs.sort() + summary = ' '.join(descs) + ui.popbuffer() + repo.vfs.tryunlink('rebasestate') + + subsetdesc = ''.join(getdesc(rev) for rev in subset) + ui.write(('%s: %s\n') % (subsetdesc.rjust(len(srevs)), summary)) + tr.abort()
--- a/tests/hghave.py Thu Aug 10 14:23:25 2017 -0400 +++ b/tests/hghave.py Thu Aug 10 14:23:41 2017 -0400 @@ -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
--- a/tests/run-tests.py Thu Aug 10 14:23:25 2017 -0400 +++ b/tests/run-tests.py Thu Aug 10 14:23:41 2017 -0400 @@ -105,9 +105,13 @@ PYTHON3 = True xrange = range # we use xrange in one place, and we'd rather not use range def _bytespath(p): + if p is None: + return p return p.encode('utf-8') def _strpath(p): + if p is None: + return p return p.decode('utf-8') elif sys.version_info >= (3, 0, 0): @@ -1359,7 +1363,7 @@ while i < len(els): el = els[i] - r = TTest.linematch(el, lout) + r = self.linematch(el, lout) if isinstance(r, str): if r == '+glob': lout = el[:-1] + ' (glob)\n' @@ -1383,11 +1387,10 @@ else: m = optline.match(el) if m: - conditions = [c for c in m.group(2).split(' ')] - - if self._hghave(conditions)[0]: - lout = el - else: + conditions = [ + c for c in m.group(2).split(b' ')] + + if not self._hghave(conditions)[0]: optional.append(i) i += 1 @@ -1416,9 +1419,16 @@ while expected.get(pos, None): el = expected[pos].pop(0) if el: - if (not optline.match(el) - and not el.endswith(b" (?)\n")): - break + if not el.endswith(b" (?)\n"): + m = optline.match(el) + if m: + conditions = [c for c in m.group(2).split(' ')] + + if self._hghave(conditions)[0]: + # Don't append as optional line + continue + else: + continue postout.append(b' ' + el) if lcmd: @@ -1481,8 +1491,7 @@ res += re.escape(c) return TTest.rematch(res, l) - @staticmethod - def linematch(el, l): + def linematch(self, el, l): retry = False if el == l: # perfect match (fast) return True @@ -1493,8 +1502,11 @@ else: m = optline.match(el) if m: + conditions = [c for c in m.group(2).split(b' ')] + el = m.group(1) + b"\n" - retry = "retry" + if not self._hghave(conditions)[0]: + retry = "retry" # Not required by listed features if el.endswith(b" (esc)\n"): if PYTHON3:
--- a/tests/test-acl.t Thu Aug 10 14:23:25 2017 -0400 +++ b/tests/test-acl.t Thu Aug 10 14:23:41 2017 -0400 @@ -120,7 +120,7 @@ bundle2-output-bundle: "HG20", 2 parts total bundle2-output-part: "reply:changegroup" (advisory) (params: 0 advisory) empty payload bundle2-output-part: "reply:pushkey" (params: 0 advisory) empty payload - bundle2-input-bundle: no-transaction + bundle2-input-bundle: with-transaction bundle2-input-part: "reply:changegroup" (advisory) (params: 0 advisory) supported bundle2-input-part: "reply:pushkey" (params: 0 advisory) supported bundle2-input-bundle: 1 parts total @@ -184,7 +184,7 @@ bundle2-output-bundle: "HG20", 2 parts total bundle2-output-part: "reply:changegroup" (advisory) (params: 0 advisory) empty payload bundle2-output-part: "reply:pushkey" (params: 0 advisory) empty payload - bundle2-input-bundle: no-transaction + bundle2-input-bundle: with-transaction bundle2-input-part: "reply:changegroup" (advisory) (params: 0 advisory) supported bundle2-input-part: "reply:pushkey" (params: 0 advisory) supported bundle2-input-bundle: 1 parts total @@ -259,7 +259,7 @@ bundle2-output-bundle: "HG20", 2 parts total bundle2-output-part: "reply:changegroup" (advisory) (params: 0 advisory) empty payload bundle2-output-part: "reply:pushkey" (params: 0 advisory) empty payload - bundle2-input-bundle: no-transaction + bundle2-input-bundle: with-transaction bundle2-input-part: "reply:changegroup" (advisory) (params: 0 advisory) supported bundle2-input-part: "reply:pushkey" (params: 0 advisory) supported bundle2-input-bundle: 1 parts total @@ -742,7 +742,7 @@ bundle2-output-bundle: "HG20", 2 parts total bundle2-output-part: "reply:changegroup" (advisory) (params: 0 advisory) empty payload bundle2-output-part: "reply:pushkey" (params: 0 advisory) empty payload - bundle2-input-bundle: no-transaction + bundle2-input-bundle: with-transaction bundle2-input-part: "reply:changegroup" (advisory) (params: 0 advisory) supported bundle2-input-part: "reply:pushkey" (params: 0 advisory) supported bundle2-input-bundle: 1 parts total @@ -1056,7 +1056,7 @@ bundle2-output-bundle: "HG20", 2 parts total bundle2-output-part: "reply:changegroup" (advisory) (params: 0 advisory) empty payload bundle2-output-part: "reply:pushkey" (params: 0 advisory) empty payload - bundle2-input-bundle: no-transaction + bundle2-input-bundle: with-transaction bundle2-input-part: "reply:changegroup" (advisory) (params: 0 advisory) supported bundle2-input-part: "reply:pushkey" (params: 0 advisory) supported bundle2-input-bundle: 1 parts total @@ -1141,7 +1141,7 @@ bundle2-output-bundle: "HG20", 2 parts total bundle2-output-part: "reply:changegroup" (advisory) (params: 0 advisory) empty payload bundle2-output-part: "reply:pushkey" (params: 0 advisory) empty payload - bundle2-input-bundle: no-transaction + bundle2-input-bundle: with-transaction bundle2-input-part: "reply:changegroup" (advisory) (params: 0 advisory) supported bundle2-input-part: "reply:pushkey" (params: 0 advisory) supported bundle2-input-bundle: 1 parts total @@ -1298,7 +1298,7 @@ bundle2-output-bundle: "HG20", 2 parts total bundle2-output-part: "reply:changegroup" (advisory) (params: 0 advisory) empty payload bundle2-output-part: "reply:pushkey" (params: 0 advisory) empty payload - bundle2-input-bundle: no-transaction + bundle2-input-bundle: with-transaction bundle2-input-part: "reply:changegroup" (advisory) (params: 0 advisory) supported bundle2-input-part: "reply:pushkey" (params: 0 advisory) supported bundle2-input-bundle: 1 parts total @@ -1502,7 +1502,7 @@ bundle2-output-part: "reply:changegroup" (advisory) (params: 0 advisory) empty payload bundle2-output-part: "reply:pushkey" (params: 0 advisory) empty payload bundle2-output-part: "reply:pushkey" (params: 0 advisory) empty payload - bundle2-input-bundle: no-transaction + bundle2-input-bundle: with-transaction bundle2-input-part: "reply:changegroup" (advisory) (params: 0 advisory) supported bundle2-input-part: "reply:pushkey" (params: 0 advisory) supported bundle2-input-part: "reply:pushkey" (params: 0 advisory) supported @@ -1798,7 +1798,7 @@ bundle2-output-part: "reply:changegroup" (advisory) (params: 0 advisory) empty payload bundle2-output-part: "reply:pushkey" (params: 0 advisory) empty payload bundle2-output-part: "reply:pushkey" (params: 0 advisory) empty payload - bundle2-input-bundle: no-transaction + bundle2-input-bundle: with-transaction bundle2-input-part: "reply:changegroup" (advisory) (params: 0 advisory) supported bundle2-input-part: "reply:pushkey" (params: 0 advisory) supported bundle2-input-part: "reply:pushkey" (params: 0 advisory) supported @@ -1891,7 +1891,7 @@ bundle2-output-part: "reply:changegroup" (advisory) (params: 0 advisory) empty payload bundle2-output-part: "reply:pushkey" (params: 0 advisory) empty payload bundle2-output-part: "reply:pushkey" (params: 0 advisory) empty payload - bundle2-input-bundle: no-transaction + bundle2-input-bundle: with-transaction bundle2-input-part: "reply:changegroup" (advisory) (params: 0 advisory) supported bundle2-input-part: "reply:pushkey" (params: 0 advisory) supported bundle2-input-part: "reply:pushkey" (params: 0 advisory) supported @@ -2052,7 +2052,7 @@ bundle2-output-part: "reply:changegroup" (advisory) (params: 0 advisory) empty payload bundle2-output-part: "reply:pushkey" (params: 0 advisory) empty payload bundle2-output-part: "reply:pushkey" (params: 0 advisory) empty payload - bundle2-input-bundle: no-transaction + bundle2-input-bundle: with-transaction bundle2-input-part: "reply:changegroup" (advisory) (params: 0 advisory) supported bundle2-input-part: "reply:pushkey" (params: 0 advisory) supported bundle2-input-part: "reply:pushkey" (params: 0 advisory) supported
--- a/tests/test-commit-amend.t Thu Aug 10 14:23:25 2017 -0400 +++ b/tests/test-commit-amend.t Thu Aug 10 14:23:41 2017 -0400 @@ -610,7 +610,7 @@ parent: 11:3334b7925910 user: test date: Thu Jan 01 00:00:00 1970 +0000 - trouble: unstable + instability: orphan summary: babar
--- a/tests/test-commit-interactive-curses.t Thu Aug 10 14:23:25 2017 -0400 +++ b/tests/test-commit-interactive-curses.t Thu Aug 10 14:23:41 2017 -0400 @@ -345,7 +345,7 @@ > $PYTHON <<EOF > from mercurial import hg, ui;\ > repo = hg.repository(ui.ui.load(), ".");\ - > print repo.ui.interface("chunkselector") + > print(repo.ui.interface("chunkselector")) > EOF > } $ chunkselectorinterface
--- a/tests/test-commit-multiple.t Thu Aug 10 14:23:25 2017 -0400 +++ b/tests/test-commit-multiple.t Thu Aug 10 14:23:41 2017 -0400 @@ -90,7 +90,7 @@ > f.close() > > def printfiles(repo, rev): - > print "revision %s files: %s" % (rev, repo[rev].files()) + > print("revision %s files: %s" % (rev, repo[rev].files())) > > repo = hg.repository(ui.ui.load(), '.') > assert len(repo) == 6, \ @@ -99,14 +99,14 @@ > replacebyte("bugfix", "u") > sleep(2) > try: - > print "PRE: len(repo): %d" % len(repo) + > print("PRE: len(repo): %d" % len(repo)) > wlock = repo.wlock() > lock = repo.lock() > replacebyte("file1", "x") > repo.commit(text="x", user="test", date=(0, 0)) > replacebyte("file1", "y") > repo.commit(text="y", user="test", date=(0, 0)) - > print "POST: len(repo): %d" % len(repo) + > print("POST: len(repo): %d" % len(repo)) > finally: > lock.release() > wlock.release()
--- a/tests/test-completion.t Thu Aug 10 14:23:25 2017 -0400 +++ b/tests/test-completion.t Thu Aug 10 14:23:41 2017 -0400 @@ -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
--- a/tests/test-context.py Thu Aug 10 14:23:25 2017 -0400 +++ b/tests/test-context.py Thu Aug 10 14:23:41 2017 -0400 @@ -179,3 +179,14 @@ print('data mismatch') except Exception as ex: print('cannot read data: %r' % ex) + +with repo.wlock(), repo.lock(), repo.transaction('test'): + with open(b'4', 'wb') as f: + f.write(b'4') + repo.dirstate.normal('4') + repo.commit('4') + revsbefore = len(repo.changelog) + repo.invalidate(clearfilecache=True) + revsafter = len(repo.changelog) + if revsbefore != revsafter: + print('changeset lost by repo.invalidate()')
--- a/tests/test-contrib-check-code.t Thu Aug 10 14:23:25 2017 -0400 +++ b/tests/test-contrib-check-code.t Thu Aug 10 14:23:41 2017 -0400 @@ -213,32 +213,32 @@ [1] $ cat > ./map-inside-gettext.py <<EOF - > print _("map inside gettext %s" % v) + > print(_("map inside gettext %s" % v)) > - > print _("concatenating " " by " " space %s" % v) - > print _("concatenating " + " by " + " '+' %s" % v) + > print(_("concatenating " " by " " space %s" % v)) + > print(_("concatenating " + " by " + " '+' %s" % v)) > - > print _("mapping operation in different line %s" - > % v) + > print(_("mapping operation in different line %s" + > % v)) > - > print _( - > "leading spaces inside of '(' %s" % v) + > print(_( + > "leading spaces inside of '(' %s" % v)) > EOF $ "$check_code" ./map-inside-gettext.py ./map-inside-gettext.py:1: - > print _("map inside gettext %s" % v) + > print(_("map inside gettext %s" % v)) don't use % inside _() ./map-inside-gettext.py:3: - > print _("concatenating " " by " " space %s" % v) + > print(_("concatenating " " by " " space %s" % v)) don't use % inside _() ./map-inside-gettext.py:4: - > print _("concatenating " + " by " + " '+' %s" % v) + > print(_("concatenating " + " by " + " '+' %s" % v)) don't use % inside _() ./map-inside-gettext.py:6: - > print _("mapping operation in different line %s" + > print(_("mapping operation in different line %s" don't use % inside _() ./map-inside-gettext.py:9: - > print _( + > print(_( don't use % inside _() [1]
--- a/tests/test-convert-cvs.t Thu Aug 10 14:23:25 2017 -0400 +++ b/tests/test-convert-cvs.t Thu Aug 10 14:23:41 2017 -0400 @@ -12,10 +12,10 @@ $ echo "convert = " >> $HGRCPATH $ cat > cvshooks.py <<EOF > def cvslog(ui,repo,hooktype,log): - > print "%s hook: %d entries"%(hooktype,len(log)) + > print("%s hook: %d entries"%(hooktype,len(log))) > > def cvschangesets(ui,repo,hooktype,changesets): - > print "%s hook: %d changesets"%(hooktype,len(changesets)) + > print("%s hook: %d changesets"%(hooktype,len(changesets))) > EOF $ hookpath=`pwd` $ cat <<EOF >> $HGRCPATH
--- a/tests/test-duplicateoptions.py Thu Aug 10 14:23:25 2017 -0400 +++ b/tests/test-duplicateoptions.py Thu Aug 10 14:23:41 2017 -0400 @@ -6,18 +6,18 @@ ui as uimod, ) -ignore = {'highlight', 'win32text', 'factotum'} +ignore = {b'highlight', b'win32text', b'factotum'} if os.name != 'nt': - ignore.add('win32mbcs') + ignore.add(b'win32mbcs') disabled = [ext for ext in extensions.disabled().keys() if ext not in ignore] -hgrc = open(os.environ["HGRCPATH"], 'w') -hgrc.write('[extensions]\n') +hgrc = open(os.environ["HGRCPATH"], 'wb') +hgrc.write(b'[extensions]\n') for ext in disabled: - hgrc.write(ext + '=\n') + hgrc.write(ext + b'=\n') hgrc.close() @@ -30,7 +30,7 @@ option[0] and globalshort.add(option[0]) option[1] and globallong.add(option[1]) -for cmd, entry in commands.table.iteritems(): +for cmd, entry in commands.table.items(): seenshort = globalshort.copy() seenlong = globallong.copy() for option in entry[1]:
--- a/tests/test-eol.t Thu Aug 10 14:23:25 2017 -0400 +++ b/tests/test-eol.t Thu Aug 10 14:23:41 2017 -0400 @@ -16,7 +16,7 @@ > except ImportError: > pass > (old, new) = sys.argv[1] == 'LF' and ('\n', '\r\n') or ('\r\n', '\n') - > print "%% switching encoding from %r to %r" % (old, new) + > print("%% switching encoding from %r to %r" % (old, new)) > for path in sys.argv[2:]: > data = file(path, 'rb').read() > data = data.replace(old, new)
--- a/tests/test-extension.t Thu Aug 10 14:23:25 2017 -0400 +++ b/tests/test-extension.t Thu Aug 10 14:23:41 2017 -0400 @@ -75,13 +75,13 @@ $ cat > foo.py <<EOF > import os > name = os.path.basename(__file__).rsplit('.', 1)[0] - > print "1) %s imported" % name + > print("1) %s imported" % name) > def uisetup(ui): - > print "2) %s uisetup" % name + > print("2) %s uisetup" % name) > def extsetup(): - > print "3) %s extsetup" % name + > print("3) %s extsetup" % name) > def reposetup(ui, repo): - > print "4) %s reposetup" % name + > print("4) %s reposetup" % name) > > # custom predicate to check registration of functions at loading > from mercurial import ( @@ -172,7 +172,7 @@ $ cat > loadabs.py <<EOF > import mod.ambigabs as ambigabs > def extsetup(): - > print 'ambigabs.s=%s' % ambigabs.s + > print('ambigabs.s=%s' % ambigabs.s) > EOF $ (PYTHONPATH=${PYTHONPATH}${PATHSEP}${TESTTMP}/libroot; hg --config extensions.loadabs=loadabs.py root) ambigabs.s=libroot/ambig.py @@ -186,7 +186,7 @@ $ cat > loadrel.py <<EOF > import mod.ambigrel as ambigrel > def extsetup(): - > print 'ambigrel.s=%s' % ambigrel.s + > print('ambigrel.s=%s' % ambigrel.s) > EOF $ (PYTHONPATH=${PYTHONPATH}${PATHSEP}${TESTTMP}/libroot; hg --config extensions.loadrel=loadrel.py root) ambigrel.s=libroot/mod/ambig.py
--- a/tests/test-filebranch.t Thu Aug 10 14:23:25 2017 -0400 +++ b/tests/test-filebranch.t Thu Aug 10 14:23:41 2017 -0400 @@ -2,8 +2,9 @@ when we do a merge. $ cat <<EOF > merge + > from __future__ import print_function > import sys, os - > print "merging for", os.path.basename(sys.argv[1]) + > print("merging for", os.path.basename(sys.argv[1])) > EOF $ HGMERGE="$PYTHON ../merge"; export HGMERGE
--- a/tests/test-glog.t Thu Aug 10 14:23:25 2017 -0400 +++ b/tests/test-glog.t Thu Aug 10 14:23:41 2017 -0400 @@ -1633,7 +1633,7 @@ Test glob expansion of pats $ expandglobs=`$PYTHON -c "import mercurial.util; \ - > print mercurial.util.expandglobs and 'true' or 'false'"` + > print(mercurial.util.expandglobs and 'true' or 'false')"` $ if [ $expandglobs = "true" ]; then > testlog 'a*'; > else
--- a/tests/test-hardlinks.t Thu Aug 10 14:23:25 2017 -0400 +++ b/tests/test-hardlinks.t Thu Aug 10 14:23:41 2017 -0400 @@ -1,11 +1,12 @@ #require hardlink $ cat > nlinks.py <<EOF + > from __future__ import print_function > import sys > from mercurial import util > for f in sorted(sys.stdin.readlines()): > f = f[:-1] - > print util.nlinks(f), f + > print(util.nlinks(f), f) > EOF $ nlinksdir()
--- a/tests/test-help.t Thu Aug 10 14:23:25 2017 -0400 +++ b/tests/test-help.t Thu Aug 10 14:23:41 2017 -0400 @@ -1709,7 +1709,7 @@ $ $PYTHON <<EOF | sh > upper = "\x8bL\x98^" - > print "hg --encoding cp932 help -e ambiguous.%s" % upper + > print("hg --encoding cp932 help -e ambiguous.%s" % upper) > EOF \x8bL\x98^ (esc) ---- @@ -1719,7 +1719,7 @@ $ $PYTHON <<EOF | sh > lower = "\x8bl\x98^" - > print "hg --encoding cp932 help -e ambiguous.%s" % lower + > print("hg --encoding cp932 help -e ambiguous.%s" % lower) > EOF \x8bl\x98^ (esc) ----
--- a/tests/test-hgweb-no-path-info.t Thu Aug 10 14:23:25 2017 -0400 +++ b/tests/test-hgweb-no-path-info.t Thu Aug 10 14:23:41 2017 -0400 @@ -31,11 +31,11 @@ > input = stringio() > > def startrsp(status, headers): - > print '---- STATUS' - > print status - > print '---- HEADERS' - > print [i for i in headers if i[0] != 'ETag'] - > print '---- DATA' + > print('---- STATUS') + > print(status) + > print('---- HEADERS') + > print([i for i in headers if i[0] != 'ETag']) + > print('---- DATA') > return output.write > > env = { @@ -59,8 +59,8 @@ > sys.stdout.write(output.getvalue()) > sys.stdout.write(''.join(content)) > getattr(content, 'close', lambda : None)() - > print '---- ERRORS' - > print errors.getvalue() + > print('---- ERRORS') + > print(errors.getvalue()) > > output = stringio() > env['QUERY_STRING'] = 'style=atom'
--- a/tests/test-hgweb-no-request-uri.t Thu Aug 10 14:23:25 2017 -0400 +++ b/tests/test-hgweb-no-request-uri.t Thu Aug 10 14:23:41 2017 -0400 @@ -31,11 +31,11 @@ > input = stringio() > > def startrsp(status, headers): - > print '---- STATUS' - > print status - > print '---- HEADERS' - > print [i for i in headers if i[0] != 'ETag'] - > print '---- DATA' + > print('---- STATUS') + > print(status) + > print('---- HEADERS') + > print([i for i in headers if i[0] != 'ETag']) + > print('---- DATA') > return output.write > > env = { @@ -58,8 +58,8 @@ > sys.stdout.write(output.getvalue()) > sys.stdout.write(''.join(content)) > getattr(content, 'close', lambda : None)() - > print '---- ERRORS' - > print errors.getvalue() + > print('---- ERRORS') + > print(errors.getvalue()) > > output = stringio() > env['PATH_INFO'] = '/'
--- a/tests/test-hgweb-non-interactive.t Thu Aug 10 14:23:25 2017 -0400 +++ b/tests/test-hgweb-non-interactive.t Thu Aug 10 14:23:41 2017 -0400 @@ -41,11 +41,11 @@ > output = stringio() > > def startrsp(status, headers): - > print '---- STATUS' - > print status - > print '---- HEADERS' - > print [i for i in headers if i[0] != 'ETag'] - > print '---- DATA' + > print('---- STATUS') + > print(status) + > print('---- HEADERS') + > print([i for i in headers if i[0] != 'ETag']) + > print('---- DATA') > return output.write > > env = { @@ -68,13 +68,13 @@ > i = hgweb('.') > for c in i(env, startrsp): > pass - > print '---- ERRORS' - > print errors.getvalue() - > print '---- OS.ENVIRON wsgi variables' - > print sorted([x for x in os.environ if x.startswith('wsgi')]) - > print '---- request.ENVIRON wsgi variables' + > print('---- ERRORS') + > print(errors.getvalue()) + > print('---- OS.ENVIRON wsgi variables') + > print(sorted([x for x in os.environ if x.startswith('wsgi')])) + > print('---- request.ENVIRON wsgi variables') > with i._obtainrepo() as repo: - > print sorted([x for x in repo.ui.environ if x.startswith('wsgi')]) + > print(sorted([x for x in repo.ui.environ if x.startswith('wsgi')])) > EOF $ $PYTHON request.py ---- STATUS
--- a/tests/test-highlight.t Thu Aug 10 14:23:25 2017 -0400 +++ b/tests/test-highlight.t Thu Aug 10 14:23:41 2017 -0400 @@ -49,7 +49,7 @@ > except (ValueError, IndexError): > n = 10 > p = primes() - > print "The first %d primes: %s" % (n, list(islice(p, n))) + > print("The first %d primes: %s" % (n, list(islice(p, n)))) > EOF $ echo >> primes.py # to test html markup with an empty line just before EOF $ hg ci -Ama @@ -74,7 +74,7 @@ <script type="text/javascript" src="/static/mercurial.js"></script> <link rel="stylesheet" href="/highlightcss" type="text/css" /> - <title>test: 1af356141006 primes.py</title> + <title>test: f4fca47b67e6 primes.py</title> </head> <body> @@ -112,7 +112,7 @@ <div class="main"> <h2 class="breadcrumb"><a href="/">Mercurial</a> </h2> <h3> - view primes.py @ 0:<a href="/rev/1af356141006">1af356141006</a> + view primes.py @ 0:<a href="/rev/f4fca47b67e6">f4fca47b67e6</a> <span class="tag">tip</span> </h3> @@ -182,7 +182,7 @@ <span id="l27"> <span class="kn">except</span> <span class="p">(</span><span class="ne">ValueError</span><span class="p">,</span> <span class="ne">IndexError</span><span class="p">):</span></span><a href="#l27"></a> <span id="l28"> <span class="n">n</span> <span class="o">=</span> <span class="mi">10</span></span><a href="#l28"></a> <span id="l29"> <span class="n">p</span> <span class="o">=</span> <span class="n">primes</span><span class="p">()</span></span><a href="#l29"></a> - <span id="l30"> <span class="kn">print</span> <span class="s">"The first </span><span class="si">%d</span><span class="s"> primes: </span><span class="si">%s</span><span class="s">"</span> <span class="o">%</span> <span class="p">(</span><span class="n">n</span><span class="p">,</span> <span class="nb">list</span><span class="p">(</span><span class="n">islice</span><span class="p">(</span><span class="n">p</span><span class="p">,</span> <span class="n">n</span><span class="p">)))</span></span><a href="#l30"></a> + <span id="l30"> <span class="kn">print</span><span class="p">(</span><span class="s">"The first </span><span class="si">%d</span><span class="s"> primes: </span><span class="si">%s</span><span class="s">"</span> <span class="o">%</span> <span class="p">(</span><span class="n">n</span><span class="p">,</span> <span class="nb">list</span><span class="p">(</span><span class="n">islice</span><span class="p">(</span><span class="n">p</span><span class="p">,</span> <span class="n">n</span><span class="p">))))</span></span><a href="#l30"></a> <span id="l31"></span><a href="#l31"></a> </pre> </div> @@ -251,7 +251,7 @@ <div class="main"> <h2 class="breadcrumb"><a href="/">Mercurial</a> </h2> <h3> - annotate primes.py @ 0:<a href="/rev/1af356141006">1af356141006</a> + annotate primes.py @ 0:<a href="/rev/f4fca47b67e6">f4fca47b67e6</a> <span class="tag">tip</span> </h3> @@ -299,19 +299,19 @@ <tr id="l1" class="thisrev"> <td class="annotate parity0"> - <a href="/annotate/1af356141006/primes.py#l1"> + <a href="/annotate/f4fca47b67e6/primes.py#l1"> 0 </a> <div class="annotate-info"> <div> - <a href="/annotate/1af356141006/primes.py#l1"> - 1af356141006</a> + <a href="/annotate/f4fca47b67e6/primes.py#l1"> + f4fca47b67e6</a> a </div> <div><em>test</em></div> <div>parents: </div> - <a href="/diff/1af356141006/primes.py">diff</a> - <a href="/rev/1af356141006">changeset</a> + <a href="/diff/f4fca47b67e6/primes.py">diff</a> + <a href="/rev/f4fca47b67e6">changeset</a> </div> </td> <td class="source followlines-btn-parent"><a href="#l1"> 1</a> <span class="sd">"""Fun with generators. Corresponding Haskell implementation:</span></td> @@ -321,14 +321,14 @@ <div class="annotate-info"> <div> - <a href="/annotate/1af356141006/primes.py#l2"> - 1af356141006</a> + <a href="/annotate/f4fca47b67e6/primes.py#l2"> + f4fca47b67e6</a> a </div> <div><em>test</em></div> <div>parents: </div> - <a href="/diff/1af356141006/primes.py">diff</a> - <a href="/rev/1af356141006">changeset</a> + <a href="/diff/f4fca47b67e6/primes.py">diff</a> + <a href="/rev/f4fca47b67e6">changeset</a> </div> </td> <td class="source followlines-btn-parent"><a href="#l2"> 2</a> </td> @@ -338,14 +338,14 @@ <div class="annotate-info"> <div> - <a href="/annotate/1af356141006/primes.py#l3"> - 1af356141006</a> + <a href="/annotate/f4fca47b67e6/primes.py#l3"> + f4fca47b67e6</a> a </div> <div><em>test</em></div> <div>parents: </div> - <a href="/diff/1af356141006/primes.py">diff</a> - <a href="/rev/1af356141006">changeset</a> + <a href="/diff/f4fca47b67e6/primes.py">diff</a> + <a href="/rev/f4fca47b67e6">changeset</a> </div> </td> <td class="source followlines-btn-parent"><a href="#l3"> 3</a> <span class="sd">primes = 2 : sieve [3, 5..]</span></td> @@ -355,14 +355,14 @@ <div class="annotate-info"> <div> - <a href="/annotate/1af356141006/primes.py#l4"> - 1af356141006</a> + <a href="/annotate/f4fca47b67e6/primes.py#l4"> + f4fca47b67e6</a> a </div> <div><em>test</em></div> <div>parents: </div> - <a href="/diff/1af356141006/primes.py">diff</a> - <a href="/rev/1af356141006">changeset</a> + <a href="/diff/f4fca47b67e6/primes.py">diff</a> + <a href="/rev/f4fca47b67e6">changeset</a> </div> </td> <td class="source followlines-btn-parent"><a href="#l4"> 4</a> <span class="sd"> where sieve (p:ns) = p : sieve [n | n <- ns, mod n p /= 0]</span></td> @@ -372,14 +372,14 @@ <div class="annotate-info"> <div> - <a href="/annotate/1af356141006/primes.py#l5"> - 1af356141006</a> + <a href="/annotate/f4fca47b67e6/primes.py#l5"> + f4fca47b67e6</a> a </div> <div><em>test</em></div> <div>parents: </div> - <a href="/diff/1af356141006/primes.py">diff</a> - <a href="/rev/1af356141006">changeset</a> + <a href="/diff/f4fca47b67e6/primes.py">diff</a> + <a href="/rev/f4fca47b67e6">changeset</a> </div> </td> <td class="source followlines-btn-parent"><a href="#l5"> 5</a> <span class="sd">"""</span></td> @@ -389,14 +389,14 @@ <div class="annotate-info"> <div> - <a href="/annotate/1af356141006/primes.py#l6"> - 1af356141006</a> + <a href="/annotate/f4fca47b67e6/primes.py#l6"> + f4fca47b67e6</a> a </div> <div><em>test</em></div> <div>parents: </div> - <a href="/diff/1af356141006/primes.py">diff</a> - <a href="/rev/1af356141006">changeset</a> + <a href="/diff/f4fca47b67e6/primes.py">diff</a> + <a href="/rev/f4fca47b67e6">changeset</a> </div> </td> <td class="source followlines-btn-parent"><a href="#l6"> 6</a> </td> @@ -406,14 +406,14 @@ <div class="annotate-info"> <div> - <a href="/annotate/1af356141006/primes.py#l7"> - 1af356141006</a> + <a href="/annotate/f4fca47b67e6/primes.py#l7"> + f4fca47b67e6</a> a </div> <div><em>test</em></div> <div>parents: </div> - <a href="/diff/1af356141006/primes.py">diff</a> - <a href="/rev/1af356141006">changeset</a> + <a href="/diff/f4fca47b67e6/primes.py">diff</a> + <a href="/rev/f4fca47b67e6">changeset</a> </div> </td> <td class="source followlines-btn-parent"><a href="#l7"> 7</a> <span class="kn">from</span> <span class="nn">itertools</span> <span class="kn">import</span> <span class="n">dropwhile</span><span class="p">,</span> <span class="n">ifilter</span><span class="p">,</span> <span class="n">islice</span><span class="p">,</span> <span class="n">count</span><span class="p">,</span> <span class="n">chain</span></td> @@ -423,14 +423,14 @@ <div class="annotate-info"> <div> - <a href="/annotate/1af356141006/primes.py#l8"> - 1af356141006</a> + <a href="/annotate/f4fca47b67e6/primes.py#l8"> + f4fca47b67e6</a> a </div> <div><em>test</em></div> <div>parents: </div> - <a href="/diff/1af356141006/primes.py">diff</a> - <a href="/rev/1af356141006">changeset</a> + <a href="/diff/f4fca47b67e6/primes.py">diff</a> + <a href="/rev/f4fca47b67e6">changeset</a> </div> </td> <td class="source followlines-btn-parent"><a href="#l8"> 8</a> </td> @@ -440,14 +440,14 @@ <div class="annotate-info"> <div> - <a href="/annotate/1af356141006/primes.py#l9"> - 1af356141006</a> + <a href="/annotate/f4fca47b67e6/primes.py#l9"> + f4fca47b67e6</a> a </div> <div><em>test</em></div> <div>parents: </div> - <a href="/diff/1af356141006/primes.py">diff</a> - <a href="/rev/1af356141006">changeset</a> + <a href="/diff/f4fca47b67e6/primes.py">diff</a> + <a href="/rev/f4fca47b67e6">changeset</a> </div> </td> <td class="source followlines-btn-parent"><a href="#l9"> 9</a> <span class="kn">def</span> <span class="nf">primes</span><span class="p">():</span></td> @@ -457,14 +457,14 @@ <div class="annotate-info"> <div> - <a href="/annotate/1af356141006/primes.py#l10"> - 1af356141006</a> + <a href="/annotate/f4fca47b67e6/primes.py#l10"> + f4fca47b67e6</a> a </div> <div><em>test</em></div> <div>parents: </div> - <a href="/diff/1af356141006/primes.py">diff</a> - <a href="/rev/1af356141006">changeset</a> + <a href="/diff/f4fca47b67e6/primes.py">diff</a> + <a href="/rev/f4fca47b67e6">changeset</a> </div> </td> <td class="source followlines-btn-parent"><a href="#l10"> 10</a> <span class="sd">"""Generate all primes."""</span></td> @@ -474,14 +474,14 @@ <div class="annotate-info"> <div> - <a href="/annotate/1af356141006/primes.py#l11"> - 1af356141006</a> + <a href="/annotate/f4fca47b67e6/primes.py#l11"> + f4fca47b67e6</a> a </div> <div><em>test</em></div> <div>parents: </div> - <a href="/diff/1af356141006/primes.py">diff</a> - <a href="/rev/1af356141006">changeset</a> + <a href="/diff/f4fca47b67e6/primes.py">diff</a> + <a href="/rev/f4fca47b67e6">changeset</a> </div> </td> <td class="source followlines-btn-parent"><a href="#l11"> 11</a> <span class="kn">def</span> <span class="nf">sieve</span><span class="p">(</span><span class="n">ns</span><span class="p">):</span></td> @@ -491,14 +491,14 @@ <div class="annotate-info"> <div> - <a href="/annotate/1af356141006/primes.py#l12"> - 1af356141006</a> + <a href="/annotate/f4fca47b67e6/primes.py#l12"> + f4fca47b67e6</a> a </div> <div><em>test</em></div> <div>parents: </div> - <a href="/diff/1af356141006/primes.py">diff</a> - <a href="/rev/1af356141006">changeset</a> + <a href="/diff/f4fca47b67e6/primes.py">diff</a> + <a href="/rev/f4fca47b67e6">changeset</a> </div> </td> <td class="source followlines-btn-parent"><a href="#l12"> 12</a> <span class="n">p</span> <span class="o">=</span> <span class="n">ns</span><span class="o">.</span><span class="n">next</span><span class="p">()</span></td> @@ -508,14 +508,14 @@ <div class="annotate-info"> <div> - <a href="/annotate/1af356141006/primes.py#l13"> - 1af356141006</a> + <a href="/annotate/f4fca47b67e6/primes.py#l13"> + f4fca47b67e6</a> a </div> <div><em>test</em></div> <div>parents: </div> - <a href="/diff/1af356141006/primes.py">diff</a> - <a href="/rev/1af356141006">changeset</a> + <a href="/diff/f4fca47b67e6/primes.py">diff</a> + <a href="/rev/f4fca47b67e6">changeset</a> </div> </td> <td class="source followlines-btn-parent"><a href="#l13"> 13</a> <span class="c"># It is important to yield *here* in order to stop the</span></td> @@ -525,14 +525,14 @@ <div class="annotate-info"> <div> - <a href="/annotate/1af356141006/primes.py#l14"> - 1af356141006</a> + <a href="/annotate/f4fca47b67e6/primes.py#l14"> + f4fca47b67e6</a> a </div> <div><em>test</em></div> <div>parents: </div> - <a href="/diff/1af356141006/primes.py">diff</a> - <a href="/rev/1af356141006">changeset</a> + <a href="/diff/f4fca47b67e6/primes.py">diff</a> + <a href="/rev/f4fca47b67e6">changeset</a> </div> </td> <td class="source followlines-btn-parent"><a href="#l14"> 14</a> <span class="c"># infinite recursion.</span></td> @@ -542,14 +542,14 @@ <div class="annotate-info"> <div> - <a href="/annotate/1af356141006/primes.py#l15"> - 1af356141006</a> + <a href="/annotate/f4fca47b67e6/primes.py#l15"> + f4fca47b67e6</a> a </div> <div><em>test</em></div> <div>parents: </div> - <a href="/diff/1af356141006/primes.py">diff</a> - <a href="/rev/1af356141006">changeset</a> + <a href="/diff/f4fca47b67e6/primes.py">diff</a> + <a href="/rev/f4fca47b67e6">changeset</a> </div> </td> <td class="source followlines-btn-parent"><a href="#l15"> 15</a> <span class="kn">yield</span> <span class="n">p</span></td> @@ -559,14 +559,14 @@ <div class="annotate-info"> <div> - <a href="/annotate/1af356141006/primes.py#l16"> - 1af356141006</a> + <a href="/annotate/f4fca47b67e6/primes.py#l16"> + f4fca47b67e6</a> a </div> <div><em>test</em></div> <div>parents: </div> - <a href="/diff/1af356141006/primes.py">diff</a> - <a href="/rev/1af356141006">changeset</a> + <a href="/diff/f4fca47b67e6/primes.py">diff</a> + <a href="/rev/f4fca47b67e6">changeset</a> </div> </td> <td class="source followlines-btn-parent"><a href="#l16"> 16</a> <span class="n">ns</span> <span class="o">=</span> <span class="n">ifilter</span><span class="p">(</span><span class="kn">lambda</span> <span class="n">n</span><span class="p">:</span> <span class="n">n</span> <span class="o">%</span> <span class="n">p</span> <span class="o">!=</span> <span class="mi">0</span><span class="p">,</span> <span class="n">ns</span><span class="p">)</span></td> @@ -576,14 +576,14 @@ <div class="annotate-info"> <div> - <a href="/annotate/1af356141006/primes.py#l17"> - 1af356141006</a> + <a href="/annotate/f4fca47b67e6/primes.py#l17"> + f4fca47b67e6</a> a </div> <div><em>test</em></div> <div>parents: </div> - <a href="/diff/1af356141006/primes.py">diff</a> - <a href="/rev/1af356141006">changeset</a> + <a href="/diff/f4fca47b67e6/primes.py">diff</a> + <a href="/rev/f4fca47b67e6">changeset</a> </div> </td> <td class="source followlines-btn-parent"><a href="#l17"> 17</a> <span class="kn">for</span> <span class="n">n</span> <span class="ow">in</span> <span class="n">sieve</span><span class="p">(</span><span class="n">ns</span><span class="p">):</span></td> @@ -593,14 +593,14 @@ <div class="annotate-info"> <div> - <a href="/annotate/1af356141006/primes.py#l18"> - 1af356141006</a> + <a href="/annotate/f4fca47b67e6/primes.py#l18"> + f4fca47b67e6</a> a </div> <div><em>test</em></div> <div>parents: </div> - <a href="/diff/1af356141006/primes.py">diff</a> - <a href="/rev/1af356141006">changeset</a> + <a href="/diff/f4fca47b67e6/primes.py">diff</a> + <a href="/rev/f4fca47b67e6">changeset</a> </div> </td> <td class="source followlines-btn-parent"><a href="#l18"> 18</a> <span class="kn">yield</span> <span class="n">n</span></td> @@ -610,14 +610,14 @@ <div class="annotate-info"> <div> - <a href="/annotate/1af356141006/primes.py#l19"> - 1af356141006</a> + <a href="/annotate/f4fca47b67e6/primes.py#l19"> + f4fca47b67e6</a> a </div> <div><em>test</em></div> <div>parents: </div> - <a href="/diff/1af356141006/primes.py">diff</a> - <a href="/rev/1af356141006">changeset</a> + <a href="/diff/f4fca47b67e6/primes.py">diff</a> + <a href="/rev/f4fca47b67e6">changeset</a> </div> </td> <td class="source followlines-btn-parent"><a href="#l19"> 19</a> </td> @@ -627,14 +627,14 @@ <div class="annotate-info"> <div> - <a href="/annotate/1af356141006/primes.py#l20"> - 1af356141006</a> + <a href="/annotate/f4fca47b67e6/primes.py#l20"> + f4fca47b67e6</a> a </div> <div><em>test</em></div> <div>parents: </div> - <a href="/diff/1af356141006/primes.py">diff</a> - <a href="/rev/1af356141006">changeset</a> + <a href="/diff/f4fca47b67e6/primes.py">diff</a> + <a href="/rev/f4fca47b67e6">changeset</a> </div> </td> <td class="source followlines-btn-parent"><a href="#l20"> 20</a> <span class="n">odds</span> <span class="o">=</span> <span class="n">ifilter</span><span class="p">(</span><span class="kn">lambda</span> <span class="n">i</span><span class="p">:</span> <span class="n">i</span> <span class="o">%</span> <span class="mi">2</span> <span class="o">==</span> <span class="mi">1</span><span class="p">,</span> <span class="n">count</span><span class="p">())</span></td> @@ -644,14 +644,14 @@ <div class="annotate-info"> <div> - <a href="/annotate/1af356141006/primes.py#l21"> - 1af356141006</a> + <a href="/annotate/f4fca47b67e6/primes.py#l21"> + f4fca47b67e6</a> a </div> <div><em>test</em></div> <div>parents: </div> - <a href="/diff/1af356141006/primes.py">diff</a> - <a href="/rev/1af356141006">changeset</a> + <a href="/diff/f4fca47b67e6/primes.py">diff</a> + <a href="/rev/f4fca47b67e6">changeset</a> </div> </td> <td class="source followlines-btn-parent"><a href="#l21"> 21</a> <span class="kn">return</span> <span class="n">chain</span><span class="p">([</span><span class="mi">2</span><span class="p">],</span> <span class="n">sieve</span><span class="p">(</span><span class="n">dropwhile</span><span class="p">(</span><span class="kn">lambda</span> <span class="n">n</span><span class="p">:</span> <span class="n">n</span> <span class="o"><</span> <span class="mi">3</span><span class="p">,</span> <span class="n">odds</span><span class="p">)))</span></td> @@ -661,14 +661,14 @@ <div class="annotate-info"> <div> - <a href="/annotate/1af356141006/primes.py#l22"> - 1af356141006</a> + <a href="/annotate/f4fca47b67e6/primes.py#l22"> + f4fca47b67e6</a> a </div> <div><em>test</em></div> <div>parents: </div> - <a href="/diff/1af356141006/primes.py">diff</a> - <a href="/rev/1af356141006">changeset</a> + <a href="/diff/f4fca47b67e6/primes.py">diff</a> + <a href="/rev/f4fca47b67e6">changeset</a> </div> </td> <td class="source followlines-btn-parent"><a href="#l22"> 22</a> </td> @@ -678,14 +678,14 @@ <div class="annotate-info"> <div> - <a href="/annotate/1af356141006/primes.py#l23"> - 1af356141006</a> + <a href="/annotate/f4fca47b67e6/primes.py#l23"> + f4fca47b67e6</a> a </div> <div><em>test</em></div> <div>parents: </div> - <a href="/diff/1af356141006/primes.py">diff</a> - <a href="/rev/1af356141006">changeset</a> + <a href="/diff/f4fca47b67e6/primes.py">diff</a> + <a href="/rev/f4fca47b67e6">changeset</a> </div> </td> <td class="source followlines-btn-parent"><a href="#l23"> 23</a> <span class="kn">if</span> <span class="n">__name__</span> <span class="o">==</span> <span class="s">"__main__"</span><span class="p">:</span></td> @@ -695,14 +695,14 @@ <div class="annotate-info"> <div> - <a href="/annotate/1af356141006/primes.py#l24"> - 1af356141006</a> + <a href="/annotate/f4fca47b67e6/primes.py#l24"> + f4fca47b67e6</a> a </div> <div><em>test</em></div> <div>parents: </div> - <a href="/diff/1af356141006/primes.py">diff</a> - <a href="/rev/1af356141006">changeset</a> + <a href="/diff/f4fca47b67e6/primes.py">diff</a> + <a href="/rev/f4fca47b67e6">changeset</a> </div> </td> <td class="source followlines-btn-parent"><a href="#l24"> 24</a> <span class="kn">import</span> <span class="nn">sys</span></td> @@ -712,14 +712,14 @@ <div class="annotate-info"> <div> - <a href="/annotate/1af356141006/primes.py#l25"> - 1af356141006</a> + <a href="/annotate/f4fca47b67e6/primes.py#l25"> + f4fca47b67e6</a> a </div> <div><em>test</em></div> <div>parents: </div> - <a href="/diff/1af356141006/primes.py">diff</a> - <a href="/rev/1af356141006">changeset</a> + <a href="/diff/f4fca47b67e6/primes.py">diff</a> + <a href="/rev/f4fca47b67e6">changeset</a> </div> </td> <td class="source followlines-btn-parent"><a href="#l25"> 25</a> <span class="kn">try</span><span class="p">:</span></td> @@ -729,14 +729,14 @@ <div class="annotate-info"> <div> - <a href="/annotate/1af356141006/primes.py#l26"> - 1af356141006</a> + <a href="/annotate/f4fca47b67e6/primes.py#l26"> + f4fca47b67e6</a> a </div> <div><em>test</em></div> <div>parents: </div> - <a href="/diff/1af356141006/primes.py">diff</a> - <a href="/rev/1af356141006">changeset</a> + <a href="/diff/f4fca47b67e6/primes.py">diff</a> + <a href="/rev/f4fca47b67e6">changeset</a> </div> </td> <td class="source followlines-btn-parent"><a href="#l26"> 26</a> <span class="n">n</span> <span class="o">=</span> <span class="nb">int</span><span class="p">(</span><span class="n">sys</span><span class="o">.</span><span class="n">argv</span><span class="p">[</span><span class="mi">1</span><span class="p">])</span></td> @@ -746,14 +746,14 @@ <div class="annotate-info"> <div> - <a href="/annotate/1af356141006/primes.py#l27"> - 1af356141006</a> + <a href="/annotate/f4fca47b67e6/primes.py#l27"> + f4fca47b67e6</a> a </div> <div><em>test</em></div> <div>parents: </div> - <a href="/diff/1af356141006/primes.py">diff</a> - <a href="/rev/1af356141006">changeset</a> + <a href="/diff/f4fca47b67e6/primes.py">diff</a> + <a href="/rev/f4fca47b67e6">changeset</a> </div> </td> <td class="source followlines-btn-parent"><a href="#l27"> 27</a> <span class="kn">except</span> <span class="p">(</span><span class="ne">ValueError</span><span class="p">,</span> <span class="ne">IndexError</span><span class="p">):</span></td> @@ -763,14 +763,14 @@ <div class="annotate-info"> <div> - <a href="/annotate/1af356141006/primes.py#l28"> - 1af356141006</a> + <a href="/annotate/f4fca47b67e6/primes.py#l28"> + f4fca47b67e6</a> a </div> <div><em>test</em></div> <div>parents: </div> - <a href="/diff/1af356141006/primes.py">diff</a> - <a href="/rev/1af356141006">changeset</a> + <a href="/diff/f4fca47b67e6/primes.py">diff</a> + <a href="/rev/f4fca47b67e6">changeset</a> </div> </td> <td class="source followlines-btn-parent"><a href="#l28"> 28</a> <span class="n">n</span> <span class="o">=</span> <span class="mi">10</span></td> @@ -780,14 +780,14 @@ <div class="annotate-info"> <div> - <a href="/annotate/1af356141006/primes.py#l29"> - 1af356141006</a> + <a href="/annotate/f4fca47b67e6/primes.py#l29"> + f4fca47b67e6</a> a </div> <div><em>test</em></div> <div>parents: </div> - <a href="/diff/1af356141006/primes.py">diff</a> - <a href="/rev/1af356141006">changeset</a> + <a href="/diff/f4fca47b67e6/primes.py">diff</a> + <a href="/rev/f4fca47b67e6">changeset</a> </div> </td> <td class="source followlines-btn-parent"><a href="#l29"> 29</a> <span class="n">p</span> <span class="o">=</span> <span class="n">primes</span><span class="p">()</span></td> @@ -797,31 +797,31 @@ <div class="annotate-info"> <div> - <a href="/annotate/1af356141006/primes.py#l30"> - 1af356141006</a> + <a href="/annotate/f4fca47b67e6/primes.py#l30"> + f4fca47b67e6</a> a </div> <div><em>test</em></div> <div>parents: </div> - <a href="/diff/1af356141006/primes.py">diff</a> - <a href="/rev/1af356141006">changeset</a> + <a href="/diff/f4fca47b67e6/primes.py">diff</a> + <a href="/rev/f4fca47b67e6">changeset</a> </div> </td> - <td class="source followlines-btn-parent"><a href="#l30"> 30</a> <span class="kn">print</span> <span class="s">"The first </span><span class="si">%d</span><span class="s"> primes: </span><span class="si">%s</span><span class="s">"</span> <span class="o">%</span> <span class="p">(</span><span class="n">n</span><span class="p">,</span> <span class="nb">list</span><span class="p">(</span><span class="n">islice</span><span class="p">(</span><span class="n">p</span><span class="p">,</span> <span class="n">n</span><span class="p">)))</span></td> + <td class="source followlines-btn-parent"><a href="#l30"> 30</a> <span class="kn">print</span><span class="p">(</span><span class="s">"The first </span><span class="si">%d</span><span class="s"> primes: </span><span class="si">%s</span><span class="s">"</span> <span class="o">%</span> <span class="p">(</span><span class="n">n</span><span class="p">,</span> <span class="nb">list</span><span class="p">(</span><span class="n">islice</span><span class="p">(</span><span class="n">p</span><span class="p">,</span> <span class="n">n</span><span class="p">))))</span></td> </tr> <tr id="l31" class="thisrev"> <td class="annotate parity0"> <div class="annotate-info"> <div> - <a href="/annotate/1af356141006/primes.py#l31"> - 1af356141006</a> + <a href="/annotate/f4fca47b67e6/primes.py#l31"> + f4fca47b67e6</a> a </div> <div><em>test</em></div> <div>parents: </div> - <a href="/diff/1af356141006/primes.py">diff</a> - <a href="/rev/1af356141006">changeset</a> + <a href="/diff/f4fca47b67e6/primes.py">diff</a> + <a href="/rev/f4fca47b67e6">changeset</a> </div> </td> <td class="source followlines-btn-parent"><a href="#l31"> 31</a> </td>
--- a/tests/test-hook.t Thu Aug 10 14:23:25 2017 -0400 +++ b/tests/test-hook.t Thu Aug 10 14:23:41 2017 -0400 @@ -409,6 +409,7 @@ $ cd "$TESTTMP/b" $ cat > hooktests.py <<EOF + > from __future__ import print_function > from mercurial import error > > uncallable = 0 @@ -418,9 +419,9 @@ > args.pop('repo', None) > a = list(args.items()) > a.sort() - > print 'hook args:' + > print('hook args:') > for k, v in a: - > print ' ', k, v + > print(' ', k, v) > > def passhook(**args): > printargs(args) @@ -445,7 +446,7 @@ > ui.note('verbose output from hook\n') > > def printtags(ui, repo, **args): - > print sorted(repo.tags()) + > print(sorted(repo.tags())) > > class container: > unreachable = 1 @@ -630,7 +631,7 @@ $ cat > hookext.py <<EOF > def autohook(**args): - > print "Automatically installed hook" + > print("Automatically installed hook") > > def reposetup(ui, repo): > repo.ui.setconfig("hooks", "commit.auto", autohook) @@ -667,7 +668,7 @@ $ cd hooks $ cat > testhooks.py <<EOF > def testhook(**args): - > print 'hook works' + > print('hook works') > EOF $ echo '[hooks]' > ../repo/.hg/hgrc $ echo "pre-commit.test = python:`pwd`/testhooks.py:testhook" >> ../repo/.hg/hgrc
--- a/tests/test-https.t Thu Aug 10 14:23:25 2017 -0400 +++ b/tests/test-https.t Thu Aug 10 14:23:41 2017 -0400 @@ -624,7 +624,6 @@ $ P="$CERTSDIR" hg id https://localhost:$HGPORT/ warning: connecting to localhost using legacy security technology (TLS 1.0); see https://mercurial-scm.org/wiki/SecureConnections for more info (?) - (the full certificate chain may not be available locally; see "hg help debugssl") (windows !) abort: error: *handshake failure* (glob) [255]
--- a/tests/test-inherit-mode.t Thu Aug 10 14:23:25 2017 -0400 +++ b/tests/test-inherit-mode.t Thu Aug 10 14:23:41 2017 -0400 @@ -25,13 +25,13 @@ > allnames.sort() > for name in allnames: > suffix = name in isdir and '/' or '' - > print '%05o %s%s' % (os.lstat(name).st_mode & 07777, name, suffix) + > print('%05o %s%s' % (os.lstat(name).st_mode & 07777, name, suffix)) > EOF $ cat >mode.py <<EOF > import sys > import os - > print '%05o' % os.lstat(sys.argv[1]).st_mode + > print('%05o' % os.lstat(sys.argv[1]).st_mode) > EOF $ umask 077
--- a/tests/test-issue4074.t Thu Aug 10 14:23:25 2017 -0400 +++ b/tests/test-issue4074.t Thu Aug 10 14:23:41 2017 -0400 @@ -8,7 +8,7 @@ > print > if random.randint(0, 100) >= 50: > x += 1 - > print hex(x) + > print(hex(x)) > EOF $ hg init a
--- a/tests/test-largefiles-cache.t Thu Aug 10 14:23:25 2017 -0400 +++ b/tests/test-largefiles-cache.t Thu Aug 10 14:23:41 2017 -0400 @@ -96,7 +96,7 @@ > #!$PYTHON > import sys, os > path = sys.argv[1] - > print '%03o' % (os.lstat(path).st_mode & 0777) + > print('%03o' % (os.lstat(path).st_mode & 0777)) > EOF $ chmod +x ls-l.py
--- a/tests/test-log.t Thu Aug 10 14:23:25 2017 -0400 +++ b/tests/test-log.t Thu Aug 10 14:23:41 2017 -0400 @@ -1793,7 +1793,7 @@ $ cd problematicencoding $ $PYTHON > setup.sh <<EOF - > print u''' + > print(u''' > echo a > text > hg add text > hg --encoding utf-8 commit -u '\u30A2' -m none @@ -1803,13 +1803,13 @@ > hg --encoding utf-8 commit -u none -m '\u30A2' > echo d > text > hg --encoding utf-8 commit -u none -m '\u30C2' - > '''.encode('utf-8') + > '''.encode('utf-8')) > EOF $ sh < setup.sh test in problematic encoding $ $PYTHON > test.sh <<EOF - > print u''' + > print(u''' > hg --encoding cp932 log --template '{rev}\\n' -u '\u30A2' > echo ==== > hg --encoding cp932 log --template '{rev}\\n' -u '\u30C2' @@ -1817,7 +1817,7 @@ > hg --encoding cp932 log --template '{rev}\\n' -k '\u30A2' > echo ==== > hg --encoding cp932 log --template '{rev}\\n' -k '\u30C2' - > '''.encode('cp932') + > '''.encode('cp932')) > EOF $ sh < test.sh 0
--- a/tests/test-merge-symlinks.t Thu Aug 10 14:23:25 2017 -0400 +++ b/tests/test-merge-symlinks.t Thu Aug 10 14:23:41 2017 -0400 @@ -1,5 +1,6 @@ $ cat > echo.py <<EOF > #!$PYTHON + > from __future__ import print_function > import os, sys > try: > import msvcrt @@ -9,7 +10,7 @@ > pass > > for k in ('HG_FILE', 'HG_MY_ISLINK', 'HG_OTHER_ISLINK', 'HG_BASE_ISLINK'): - > print k, os.environ[k] + > print(k, os.environ[k]) > EOF Create 2 heads containing the same file, once as
--- a/tests/test-merge1.t Thu Aug 10 14:23:25 2017 -0400 +++ b/tests/test-merge1.t Thu Aug 10 14:23:41 2017 -0400 @@ -1,4 +1,5 @@ $ cat <<EOF > merge + > from __future__ import print_function > import sys, os > > try: @@ -8,7 +9,7 @@ > except ImportError: > pass > - > print "merging for", os.path.basename(sys.argv[1]) + > print("merging for", os.path.basename(sys.argv[1])) > EOF $ HGMERGE="$PYTHON ../merge"; export HGMERGE
--- a/tests/test-merge6.t Thu Aug 10 14:23:25 2017 -0400 +++ b/tests/test-merge6.t Thu Aug 10 14:23:41 2017 -0400 @@ -1,6 +1,6 @@ $ cat <<EOF > merge > import sys, os - > print "merging for", os.path.basename(sys.argv[1]) + > print("merging for", os.path.basename(sys.argv[1])) > EOF $ HGMERGE="$PYTHON ../merge"; export HGMERGE
--- a/tests/test-mq-eol.t Thu Aug 10 14:23:25 2017 -0400 +++ b/tests/test-mq-eol.t Thu Aug 10 14:23:41 2017 -0400 @@ -33,7 +33,7 @@ > for line in file(sys.argv[1], 'rb'): > line = line.replace('\r', '<CR>') > line = line.replace('\n', '<LF>') - > print line + > print(line) > EOF $ hg init repo
--- a/tests/test-notify-changegroup.t Thu Aug 10 14:23:25 2017 -0400 +++ b/tests/test-notify-changegroup.t Thu Aug 10 14:23:41 2017 -0400 @@ -39,7 +39,7 @@ push $ hg --traceback --cwd b push ../a 2>&1 | - > $PYTHON -c 'import sys,re; print re.sub("\n\t", " ", sys.stdin.read()),' + > $PYTHON -c 'from __future__ import print_function ; import sys,re; print(re.sub("\n\t", " ", sys.stdin.read()), end="")' pushing to ../a searching for changes adding changesets @@ -92,7 +92,7 @@ unbundle with correct source $ hg --config notify.sources=unbundle --cwd a unbundle ../test.hg 2>&1 | - > $PYTHON -c 'import sys,re; print re.sub("\n\t", " ", sys.stdin.read()),' + > $PYTHON -c 'from __future__ import print_function ; import sys,re; print(re.sub("\n\t", " ", sys.stdin.read()), end="")' adding changesets adding manifests adding file changes @@ -167,7 +167,7 @@ push $ hg --traceback --cwd b --config notify.fromauthor=True push ../a 2>&1 | - > $PYTHON -c 'import sys,re; print re.sub("\n\t", " ", sys.stdin.read()),' + > $PYTHON -c 'from __future__ import print_function ; import sys,re; print(re.sub("\n\t", " ", sys.stdin.read()), end="")' pushing to ../a searching for changes adding changesets
--- a/tests/test-notify.t Thu Aug 10 14:23:25 2017 -0400 +++ b/tests/test-notify.t Thu Aug 10 14:23:41 2017 -0400 @@ -1,3 +1,8 @@ + $ cat > $TESTTMP/filter.py <<EOF + > from __future__ import print_function + > import sys, re + > print(re.sub("\n[ \t]", " ", sys.stdin.read()), end="") + > EOF $ cat <<EOF >> $HGRCPATH > [extensions] @@ -175,8 +180,7 @@ of the very long subject line pull (minimal config) - $ hg --traceback --cwd b pull ../a | \ - > $PYTHON -c 'import sys,re; print re.sub("\n[\t ]", " ", sys.stdin.read()),' + $ hg --traceback --cwd b pull ../a | $PYTHON $TESTTMP/filter.py pulling from ../a searching for changes adding changesets @@ -205,6 +209,7 @@ @@ -1,1 +1,2 @@ a +a (run 'hg update' to get a working copy) + $ cat <<EOF >> $HGRCPATH > [notify] > config = `pwd`/.notify.conf @@ -228,8 +233,7 @@ $ hg --cwd b rollback repository tip rolled back to revision 0 (undo pull) - $ hg --traceback --cwd b pull ../a | \ - > $PYTHON -c 'import sys,re; print re.sub("\n\t", " ", sys.stdin.read()),' + $ hg --traceback --cwd b pull ../a | $PYTHON $TESTTMP/filter.py pulling from ../a searching for changes adding changesets @@ -254,8 +258,7 @@ diff -r cb9a9f314b8b -r 0647d048b600 a --- a/a Thu Jan 01 00:00:00 1970 +0000 +++ b/a Thu Jan 01 00:00:01 1970 +0000 - @@ -1,1 +1,2 @@ - a + @@ -1,1 +1,2 @@ a +a (run 'hg update' to get a working copy) @@ -272,8 +275,7 @@ $ hg --cwd b rollback repository tip rolled back to revision 0 (undo pull) - $ hg --traceback --cwd b pull ../a | \ - > $PYTHON -c 'import sys,re; print re.sub("\n\t", " ", sys.stdin.read()),' + $ hg --traceback --cwd b pull ../a | $PYTHON $TESTTMP/filter.py pulling from ../a searching for changes adding changesets @@ -294,17 +296,14 @@ changeset 0647d048b600 in b description: b diffstat: - - a | 1 + - 1 files changed, 1 insertions(+), 0 deletions(-) + a | 1 + 1 files changed, 1 insertions(+), 0 deletions(-) diffs (6 lines): diff -r cb9a9f314b8b -r 0647d048b600 a --- a/a Thu Jan 01 00:00:00 1970 +0000 +++ b/a Thu Jan 01 00:00:01 1970 +0000 - @@ -1,1 +1,2 @@ - a + @@ -1,1 +1,2 @@ a +a (run 'hg update' to get a working copy) @@ -321,8 +320,7 @@ (branch merge, don't forget to commit) $ hg ci -m merge -d '3 0' $ cd .. - $ hg --traceback --cwd b pull ../a | \ - > $PYTHON -c 'import sys,re; print re.sub("\n\t", " ", sys.stdin.read()),' + $ hg --traceback --cwd b pull ../a | $PYTHON $TESTTMP/filter.py pulling from ../a searching for changes adding changesets @@ -343,17 +341,14 @@ changeset 0a184ce6067f in b description: adda2 diffstat: - - a | 1 + - 1 files changed, 1 insertions(+), 0 deletions(-) + a | 1 + 1 files changed, 1 insertions(+), 0 deletions(-) diffs (6 lines): diff -r cb9a9f314b8b -r 0a184ce6067f a --- a/a Thu Jan 01 00:00:00 1970 +0000 +++ b/a Thu Jan 01 00:00:02 1970 +0000 - @@ -1,1 +1,2 @@ - a + @@ -1,1 +1,2 @@ a +a Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 @@ -380,7 +375,7 @@ $ hg --cwd a --encoding utf-8 commit -A -d '0 0' \ > -m `$PYTHON -c 'print "\xc3\xa0\xc3\xa1\xc3\xa2\xc3\xa3\xc3\xa4"'` $ hg --traceback --cwd b --encoding utf-8 pull ../a | \ - > $PYTHON -c 'import sys,re; print re.sub("\n\t", " ", sys.stdin.read()),' + > $PYTHON $TESTTMP/filter.py pulling from ../a searching for changes adding changesets @@ -401,18 +396,14 @@ changeset 7ea05ad269dc in b description: \xc3\xa0\xc3\xa1\xc3\xa2\xc3\xa3\xc3\xa4 (esc) diffstat: - - a | 1 + - 1 files changed, 1 insertions(+), 0 deletions(-) + a | 1 + 1 files changed, 1 insertions(+), 0 deletions(-) diffs (7 lines): diff -r 6a0cf76b2701 -r 7ea05ad269dc a --- a/a Thu Jan 01 00:00:03 1970 +0000 +++ b/a Thu Jan 01 00:00:00 1970 +0000 - @@ -1,2 +1,3 @@ - a - a + @@ -1,2 +1,3 @@ a a +a (run 'hg update' to get a working copy) @@ -435,7 +426,7 @@ added 1 changesets with 1 changes to 1 files notify: sending 2 subscribers 1 changes (run 'hg update' to get a working copy) - $ $PYTHON -c 'import sys,re; print re.sub("\n\t", " ", file("b/mbox").read()),' + $ $PYTHON $TESTTMP/filter.py < b/mbox From test@test.com ... ... .. ..:..:.. .... (re) Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 @@ -451,19 +442,14 @@ changeset e0be44cf638b in b description: long line diffstat: - - a | 1 + - 1 files changed, 1 insertions(+), 0 deletions(-) + a | 1 + 1 files changed, 1 insertions(+), 0 deletions(-) diffs (8 lines): diff -r 7ea05ad269dc -r e0be44cf638b a --- a/a Thu Jan 01 00:00:00 1970 +0000 +++ b/a Thu Jan 01 00:00:00 1970 +0000 - @@ -1,3 +1,4 @@ - a - a - a + @@ -1,3 +1,4 @@ a a a +nonononononononononononononononononononononononononononononononononononono= nononononononononononononononononononononononononononononononononononononon= ononononononononononononononononononononononononononononononononononononono= @@ -500,8 +486,7 @@ (branches are permanent and global, did you want a bookmark?) $ echo a >> a/a $ hg --cwd a ci -m test -d '1 0' - $ hg --traceback --cwd b pull ../a | \ - > $PYTHON -c 'import sys,re; print re.sub("\n\t", " ", sys.stdin.read()),' + $ hg --traceback --cwd b pull ../a | $PYTHON $TESTTMP/filter.py pulling from ../a searching for changes adding changesets @@ -530,8 +515,7 @@ 1 files updated, 0 files merged, 0 files removed, 0 files unresolved $ echo a >> a/a $ hg --cwd a ci -m test -d '1 0' - $ hg --traceback --cwd b pull ../a | \ - > $PYTHON -c 'import sys,re; print re.sub("\n\t", " ", sys.stdin.read()),' + $ hg --traceback --cwd b pull ../a | $PYTHON $TESTTMP/filter.py pulling from ../a searching for changes adding changesets @@ -559,8 +543,7 @@ $ mv "$HGRCPATH.new" $HGRCPATH $ echo a >> a/a $ hg --cwd a commit -m 'default template' - $ hg --cwd b pull ../a -q | \ - > $PYTHON -c 'import sys,re; print re.sub("\n\t", " ", sys.stdin.read()),' + $ hg --cwd b pull ../a -q | $PYTHON $TESTTMP/filter.py Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit @@ -589,8 +572,7 @@ > EOF $ echo a >> a/a $ hg --cwd a commit -m 'with style' - $ hg --cwd b pull ../a -q | \ - > $PYTHON -c 'import sys,re; print re.sub("\n\t", " ", sys.stdin.read()),' + $ hg --cwd b pull ../a -q | $PYTHON $TESTTMP/filter.py Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit @@ -613,8 +595,7 @@ > EOF $ echo a >> a/a $ hg --cwd a commit -m 'with template' - $ hg --cwd b pull ../a -q | \ - > $PYTHON -c 'import sys,re; print re.sub("\n\t", " ", sys.stdin.read()),' + $ hg --cwd b pull ../a -q | $PYTHON $TESTTMP/filter.py Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit
--- a/tests/test-obsmarker-template.t Thu Aug 10 14:23:25 2017 -0400 +++ b/tests/test-obsmarker-template.t Thu Aug 10 14:23:41 2017 -0400 @@ -442,14 +442,14 @@ | parent: 0:ea207398892e | user: test | date: Thu Jan 01 00:00:00 1970 +0000 - | trouble: divergent + | instability: content-divergent | summary: A2 | | o changeset: 2:fdf9bde5129a |/ parent: 0:ea207398892e | user: test | date: Thu Jan 01 00:00:00 1970 +0000 - | trouble: 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 +0000 - | trouble: 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 +0000 - | trouble: 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 +0000 - | trouble: 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 +0000 - | trouble: divergent + | instability: content-divergent | summary: Add only B | | o changeset: 7:ba2ed02b0c9a | | user: test | | date: Thu Jan 01 00:00:00 1970 +0000 - | | trouble: unstable, divergent + | | instability: orphan, content-divergent | | summary: Add A,B,C | | | x changeset: 6:4a004186e638 @@ -1111,7 +1111,7 @@ | parent: 3:f897c6137566 | user: test | date: Thu Jan 01 00:00:00 1970 +0000 - | trouble: divergent + | instability: content-divergent | summary: Add A,B,C | o changeset: 3:f897c6137566
--- a/tests/test-obsolete-divergent.t Thu Aug 10 14:23:25 2017 -0400 +++ b/tests/test-obsolete-divergent.t Thu Aug 10 14:23:41 2017 -0400 @@ -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 .. @@ -670,10 +670,10 @@ $ 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 + $ hg log -G -T '{rev}:{node|short} {desc} {instabilities}' -r 'sort(all(), topo)' + @ 5:1a2a9b5b0030 B2 content-divergent | - | o 4:70d5a63ca112 B4 divergent + | o 4:70d5a63ca112 B4 content-divergent | | | o 1:48b9aae0607f Z |
--- a/tests/test-obsolete.t Thu Aug 10 14:23:25 2017 -0400 +++ b/tests/test-obsolete.t Thu Aug 10 14:23:41 2017 -0400 @@ -3,7 +3,7 @@ > # public changeset are not obsolete > publish=false > [ui] - > logtemplate="{rev}:{node|short} ({phase}{if(obsolete, ' *{obsolete}*')}{if(troubles, ' {troubles}')}) [{tags} {bookmarks}] {desc|firstline}\n" + > logtemplate="{rev}:{node|short} ({phase}{if(obsolete, ' *{obsolete}*')}{if(instabilities, ' {instabilities}')}) [{tags} {bookmarks}] {desc|firstline}\n" > EOF $ mkcommit() { > echo "$1" > "$1" @@ -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 @@ -520,15 +520,15 @@ $ hg log -r 'obsolete()' 4:94b33453f93b (draft *obsolete*) [ ] add original_d $ hg summary - parent: 5:cda648ca50f5 tip (unstable) + parent: 5:cda648ca50f5 tip (orphan) add original_e branch: default commit: (clean) update: 1 new changesets, 2 branch heads (merge) phases: 3 draft - unstable: 1 changesets + orphan: 1 changesets $ hg log -G -r '::unstable()' - @ 5:cda648ca50f5 (draft unstable) [tip ] add original_e + @ 5:cda648ca50f5 (draft orphan) [tip ] add original_e | x 4:94b33453f93b (draft *obsolete*) [ ] add original_d | @@ -552,7 +552,7 @@ $ hg push ../tmpc/ pushing to ../tmpc/ searching for changes - abort: push includes unstable changeset: cda648ca50f5! + abort: push includes orphan changeset: cda648ca50f5! [255] Test that extinct changeset are properly detected @@ -570,7 +570,7 @@ 2:245bde4270cd (public) [ ] add original_c 3:6f9641995072 (draft) [ ] add n3w_3_c 4:94b33453f93b (draft *obsolete*) [ ] add original_d - 5:cda648ca50f5 (draft unstable) [tip ] add original_e + 5:cda648ca50f5 (draft orphan) [tip ] add original_e $ hg push ../tmpf -f # -f because be push unstable too pushing to ../tmpf searching for changes @@ -591,7 +591,7 @@ Do not warn about new head when the new head is a successors of a remote one $ hg log -G - @ 5:cda648ca50f5 (draft unstable) [tip ] add original_e + @ 5:cda648ca50f5 (draft orphan) [tip ] add original_e | x 4:94b33453f93b (draft *obsolete*) [ ] add original_d | @@ -914,7 +914,7 @@ changeset: 7:50c51b361e60 user: test date: Thu Jan 01 00:00:00 1970 +0000 - trouble: unstable, bumped + instability: orphan, phase-divergent summary: add babar @@ -926,7 +926,7 @@ test the "troubles" templatekw $ hg log -r 'bumped() and unstable()' - 7:50c51b361e60 (draft unstable bumped) [ ] add babar + 7:50c51b361e60 (draft orphan phase-divergent) [ ] add babar test the default cmdline template @@ -934,7 +934,7 @@ changeset: 7:50c51b361e60 user: test date: Thu Jan 01 00:00:00 1970 +0000 - trouble: unstable, bumped + instability: 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 (unstable, bumped) + parent: 7:50c51b361e60 (orphan, phase-divergent) add babar branch: default commit: (clean) update: 2 new changesets (update) phases: 4 draft - unstable: 2 changesets - bumped: 1 changesets + orphan: 2 changesets + phase-divergent: 1 changesets $ hg up -r 'obsolete()' 0 files updated, 0 files merged, 1 files removed, 0 files unresolved $ hg summary @@ -967,8 +967,8 @@ commit: (clean) update: 3 new changesets (update) phases: 4 draft - unstable: 2 changesets - bumped: 1 changesets + orphan: 2 changesets + phase-divergent: 1 changesets Test incoming/outcoming with changesets obsoleted remotely, known locally ===============================================================================
--- a/tests/test-push-http.t Thu Aug 10 14:23:25 2017 -0400 +++ b/tests/test-push-http.t Thu Aug 10 14:23:41 2017 -0400 @@ -172,4 +172,20 @@ % serve errors [255] + $ cat > .hg/hgrc <<EOF + > [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 ..
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tests/test-pushvars.t Thu Aug 10 14:23:41 2017 -0400 @@ -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]
--- a/tests/test-rebase-base.t Thu Aug 10 14:23:25 2017 -0400 +++ b/tests/test-rebase-base.t Thu Aug 10 14:23:41 2017 -0400 @@ -379,3 +379,40 @@ / o 0: A +Rebasing using a single transaction + + $ hg init singletr && cd singletr + $ cat >> .hg/hgrc <<EOF + > [rebase] + > singletransaction=True + > EOF + $ hg debugdrawdag <<'EOF' + > Z + > | + > | D + > | | + > | C + > | | + > Y B + > |/ + > A + > EOF +- We should only see two status stored messages. One from the start, one from +- the end. + $ hg rebase --debug -b D -d Z | grep 'status stored' + rebase status stored + rebase status stored + $ hg tglog + o 5: D + | + o 4: C + | + o 3: B + | + o 2: Z + | + o 1: Y + | + o 0: A + + $ cd ..
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tests/test-rebase-brute-force.t Thu Aug 10 14:23:41 2017 -0400 @@ -0,0 +1,55 @@ + $ cat >> $HGRCPATH <<EOF + > [extensions] + > drawdag=$TESTDIR/drawdag.py + > bruterebase=$TESTDIR/bruterebase.py + > [experimental] + > evolution=createmarkers,allowunstable + > EOF + $ init() { + > N=`expr ${N:-0} + 1` + > cd $TESTTMP && hg init repo$N && cd repo$N + > hg debugdrawdag + > } + +Source looks like "N" + + $ init <<'EOS' + > C D + > |\| + > A B Z + > EOS + + $ hg debugbruterebase 'all()-Z' Z + A: A':Z + B: B':Z + AB: A':Z B':Z + C: ABORT: cannot use revision 3 as base, result would have 3 parents + AC: A':Z C':A'B + BC: B':Z C':B'A + ABC: A':Z B':Z C':A'B' + D: D':Z + AD: A':Z D':Z + BD: B':Z D':B' + ABD: A':Z B':Z D':B' + CD: CRASH: revlog index out of range + ACD: A':Z C':A'A' D':Z + BCD: B':Z C':B'A D':B' + ABCD: A':Z B':Z C':A'B' D':B' + +Moving backwards + + $ init <<'EOS' + > C + > |\ + > A B + > | + > Z + > EOS + $ hg debugbruterebase 'all()-Z' Z + B: B':Z + A: + BA: B':Z + C: ABORT: cannot use revision 3 as base, result would have 3 parents + BC: B':Z C':B'A + AC: + BAC: ABORT: nothing to merge
--- a/tests/test-rebase-obsolete.t Thu Aug 10 14:23:25 2017 -0400 +++ b/tests/test-rebase-obsolete.t Thu Aug 10 14:23:41 2017 -0400 @@ -13,6 +13,7 @@ > publish=False > [extensions] > rebase= + > drawdag=$TESTDIR/drawdag.py > EOF Setup rebase canonical repo @@ -472,6 +473,27 @@ $ cd .. +Detach both parents + + $ hg init double-detach + $ cd double-detach + + $ hg debugdrawdag <<EOF + > F + > /| + > C E + > | | + > B D G + > \|/ + > A + > EOF + +BROKEN: This raises an exception + $ hg rebase -d G -r 'B + D + F' 2>&1 | grep '^AssertionError' + AssertionError: no base found to rebase on (defineparents called wrong) + + $ cd .. + test on rebase dropping a merge (setup) @@ -793,13 +815,13 @@ o 0:4a2df7238c3b A $ hg summary - parent: 15:73568ab6879d tip (unstable) + parent: 15:73568ab6879d tip (orphan) bar foo branch: default commit: (clean) update: 2 new changesets, 3 branch heads (merge) phases: 8 draft - unstable: 1 changesets + orphan: 1 changesets $ hg rebase -s 10 -d 12 abort: this rebase will cause divergences from: 121d9e3bc4c6 (to force the rebase please set experimental.allowdivergence=True) @@ -833,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. @@ -896,55 +918,202 @@ rebasing 22:7bdc8a87673d "dummy change" (tip) $ cd .. -rebase source is obsoleted (issue5198) ---------------------------------- +Rebase merge where successor of one parent is equal to destination (issue5198) + + $ hg init p1-succ-is-dest + $ cd p1-succ-is-dest - $ hg clone base amended - updating to branch default - 3 files updated, 0 files merged, 0 files removed, 0 files unresolved - $ cd amended - $ hg up 9520eea781bc - 1 files updated, 0 files merged, 2 files removed, 0 files unresolved - $ echo 1 >> E - $ hg commit --amend -m "E'" -d "0 0" + $ hg debugdrawdag <<EOF + > F + > /| + > E D B # replace: D -> B + > \|/ + > A + > EOF + + $ hg rebase -d B -s D + note: not rebasing 2:b18e25de2cf5 "D" (D), already in destination as 1:112478962961 "B" + rebasing 4:66f1a38021c9 "F" (F tip) $ hg log -G - @ 9:69abe8906104 E' - | - | o 7:02de42196ebe H - | | - | | o 6:eea13746799a G + o 5:50e9d60b99c6 F + |\ + | | x 4:66f1a38021c9 F | |/| - | o | 5:24b6387c8c8c F - |/ / - | x 4:9520eea781bc E + | o | 3:7fb047a69f22 E + | | | + | | x 2:b18e25de2cf5 D + | |/ + o | 1:112478962961 B |/ - | o 3:32af7686d403 D + o 0:426bada5c675 A + + $ cd .. + +Rebase merge where successor of other parent is equal to destination + + $ hg init p2-succ-is-dest + $ cd p2-succ-is-dest + + $ hg debugdrawdag <<EOF + > F + > /| + > E D B # replace: E -> B + > \|/ + > A + > EOF + +BROKEN: Raises an exception + $ hg rebase -d B -s E 2>&1 | grep AssertionError: + AssertionError: no base found to rebase on (defineparents called wrong) + $ hg log -G + o 4:66f1a38021c9 F + |\ + | x 3:7fb047a69f22 E | | - | o 2:5fddd98957c8 C - | | - | o 1:42ccdea3bb16 B + o | 2:b18e25de2cf5 D |/ - o 0:cd010b8cd998 A + | o 1:112478962961 B + |/ + o 0:426bada5c675 A - $ hg rebase -d . -s 9520eea781bc - note: not rebasing 4:9520eea781bc "E", already in destination as 9:69abe8906104 "E'" - rebasing 6:eea13746799a "G" + $ cd .. + +Rebase merge where successor of one parent is ancestor of destination + + $ hg init p1-succ-in-dest + $ cd p1-succ-in-dest + + $ hg debugdrawdag <<EOF + > F C + > /| | + > E D B # replace: D -> B + > \|/ + > A + > EOF + + $ hg rebase -d C -s D + note: not rebasing 2:b18e25de2cf5 "D" (D), already in destination as 1:112478962961 "B" + rebasing 5:66f1a38021c9 "F" (F tip) +BROKEN: not rebased on top of requested destination (C) $ hg log -G - o 10:17be06e82e95 G + o 6:50e9d60b99c6 F + |\ + | | x 5:66f1a38021c9 F + | |/| + +-----o 4:26805aba1e60 C + | | | + | o | 3:7fb047a69f22 E + | | | + | | x 2:b18e25de2cf5 D + | |/ + o | 1:112478962961 B + |/ + o 0:426bada5c675 A + + $ cd .. + +Rebase merge where successor of other parent is ancestor of destination + + $ hg init p2-succ-in-dest + $ cd p2-succ-in-dest + + $ hg debugdrawdag <<EOF + > F C + > /| | + > E D B # replace: E -> B + > \|/ + > A + > EOF + +BROKEN: Raises an exception + $ hg rebase -d C -s E 2>&1 | grep AssertionError: + AssertionError: no base found to rebase on (defineparents called wrong) + $ hg log -G + o 5:66f1a38021c9 F |\ - | @ 9:69abe8906104 E' - | | - +---o 7:02de42196ebe H - | | - o | 5:24b6387c8c8c F + | | o 4:26805aba1e60 C + | | | + | x | 3:7fb047a69f22 E + | | | + o | | 2:b18e25de2cf5 D + |/ / + | o 1:112478962961 B |/ - | o 3:32af7686d403 D - | | - | o 2:5fddd98957c8 C - | | - | o 1:42ccdea3bb16 B + o 0:426bada5c675 A + + $ cd .. + +Rebase merge where successor of one parent is ancestor of destination + + $ hg init p1-succ-in-dest-b + $ cd p1-succ-in-dest-b + + $ hg debugdrawdag <<EOF + > F C + > /| | + > E D B # replace: E -> B + > \|/ + > A + > EOF + + $ hg rebase -d C -b F + rebasing 2:b18e25de2cf5 "D" (D) + note: not rebasing 3:7fb047a69f22 "E" (E), already in destination as 1:112478962961 "B" + rebasing 5:66f1a38021c9 "F" (F tip) + $ hg log -G + o 7:9ed45af61fa0 F + | + o 6:8f47515dda15 D + | + | x 5:66f1a38021c9 F + | |\ + o | | 4:26805aba1e60 C + | | | + | | x 3:7fb047a69f22 E + | | | + | x | 2:b18e25de2cf5 D + | |/ + o / 1:112478962961 B |/ - o 0:cd010b8cd998 A + o 0:426bada5c675 A + + $ cd .. + +Rebase merge where successor of other parent is ancestor of destination + + $ hg init p2-succ-in-dest-b + $ cd p2-succ-in-dest-b + + $ hg debugdrawdag <<EOF + > F C + > /| | + > E D B # replace: D -> B + > \|/ + > A + > EOF + + $ hg rebase -d C -b F + note: not rebasing 2:b18e25de2cf5 "D" (D), already in destination as 1:112478962961 "B" + rebasing 3:7fb047a69f22 "E" (E) + rebasing 5:66f1a38021c9 "F" (F tip) +BROKEN: This should have resulted in a rebased F with one parent, just like in +the test case above + $ hg log -G + o 7:c1e6f26e339d F + |\ + | o 6:533690786a86 E + |/ + | x 5:66f1a38021c9 F + | |\ + o | | 4:26805aba1e60 C + | | | + | | x 3:7fb047a69f22 E + | | | + | x | 2:b18e25de2cf5 D + | |/ + o / 1:112478962961 B + |/ + o 0:426bada5c675 A $ cd ..
--- a/tests/test-releasenotes-formatting.t Thu Aug 10 14:23:25 2017 -0400 +++ b/tests/test-releasenotes-formatting.t Thu Aug 10 14:23:41 2017 -0400 @@ -1,3 +1,5 @@ +#require fuzzywuzzy + $ cat >> $HGRCPATH << EOF > [extensions] > releasenotes=
--- a/tests/test-releasenotes-merging.t Thu Aug 10 14:23:25 2017 -0400 +++ b/tests/test-releasenotes-merging.t Thu Aug 10 14:23:41 2017 -0400 @@ -1,3 +1,5 @@ +#require fuzzywuzzy + $ cat >> $HGRCPATH << EOF > [extensions] > releasenotes= @@ -158,3 +160,122 @@ * this is fix3. + $ cd .. + +Ignores commit messages containing issueNNNN based on issue number. + + $ hg init simple-fuzzrepo + $ cd simple-fuzzrepo + $ touch fix1 + $ hg -q commit -A -l - << EOF + > commit 1 + > + > .. fix:: + > + > Resolved issue4567. + > EOF + + $ cat >> $TESTTMP/issue-number-notes << EOF + > Bug Fixes + > ========= + > + > * Fixed issue1234 related to XYZ. + > + > * Fixed issue4567 related to ABC. + > + > * Fixed issue3986 related to PQR. + > EOF + + $ hg releasenotes -r . $TESTTMP/issue-number-notes + "issue4567" already exists in notes; ignoring + + $ cat $TESTTMP/issue-number-notes + Bug Fixes + ========= + + * Fixed issue1234 related to XYZ. + + * Fixed issue4567 related to ABC. + + * Fixed issue3986 related to PQR. + + $ cd .. + +Adds short commit messages (words < 10) without +comparison unless there is an exact match. + + $ hg init tempdir + $ cd tempdir + $ touch feature1 + $ hg -q commit -A -l - << EOF + > commit 1 + > + > .. feature:: + > + > Adds a new feature 1. + > EOF + + $ hg releasenotes -r . $TESTTMP/short-sentence-notes + + $ touch feature2 + $ hg -q commit -A -l - << EOF + > commit 2 + > + > .. feature:: + > + > Adds a new feature 2. + > EOF + + $ hg releasenotes -r . $TESTTMP/short-sentence-notes + $ cat $TESTTMP/short-sentence-notes + New Features + ============ + + * Adds a new feature 1. + + * Adds a new feature 2. + + $ cd .. + +Ignores commit messages based on fuzzy comparison. + + $ hg init fuzznotes + $ cd fuzznotes + $ touch fix1 + $ hg -q commit -A -l - << EOF + > commit 1 + > + > .. fix:: + > + > This is a fix with another line. + > And it is a big one. + > EOF + + $ cat >> $TESTTMP/fuzz-ignore-notes << EOF + > Bug Fixes + > ========= + > + > * Fixed issue4567 by improving X. + > + > * This is the first line. This is next line with one newline. + > + > This is another line written after two newlines. This is going to be a big one. + > + > * This fixes another problem. + > EOF + + $ hg releasenotes -r . $TESTTMP/fuzz-ignore-notes + "This is a fix with another line. And it is a big one." already exists in notes file; ignoring + + $ cat $TESTTMP/fuzz-ignore-notes + Bug Fixes + ========= + + * Fixed issue4567 by improving X. + + * This is the first line. This is next line with one newline. + + This is another line written after two newlines. This is going to be a big + one. + + * This fixes another problem.
--- a/tests/test-releasenotes-parsing.t Thu Aug 10 14:23:25 2017 -0400 +++ b/tests/test-releasenotes-parsing.t Thu Aug 10 14:23:41 2017 -0400 @@ -1,3 +1,5 @@ +#require fuzzywuzzy + $ cat >> $HGRCPATH << EOF > [extensions] > releasenotes=
--- a/tests/test-repair-strip.t Thu Aug 10 14:23:25 2017 -0400 +++ b/tests/test-repair-strip.t Thu Aug 10 14:23:41 2017 -0400 @@ -4,7 +4,7 @@ > import sys > for entry in sys.stdin.read().split('\n'): > if entry: - > print entry.split('\x00')[0] + > print(entry.split('\x00')[0]) > EOF $ echo "[extensions]" >> $HGRCPATH
--- a/tests/test-run-tests.py Thu Aug 10 14:23:25 2017 -0400 +++ b/tests/test-run-tests.py Thu Aug 10 14:23:41 2017 -0400 @@ -39,7 +39,8 @@ and output.endswith(b'\n')), 'missing newline' assert not re.search(br'[^ \w\\/\r\n()*?]', expected + output), \ b'single backslash or unknown char' - match = run_tests.TTest.linematch(expected, output) + test = run_tests.TTest(b'test-run-test.t', b'.', b'.') + match = test.linematch(expected, output) if isinstance(match, str): return 'special: ' + match elif isinstance(match, bytes):
--- a/tests/test-run-tests.t Thu Aug 10 14:23:25 2017 -0400 +++ b/tests/test-run-tests.t Thu Aug 10 14:23:41 2017 -0400 @@ -158,6 +158,73 @@ python hash seed: * (glob) #endif + $ cat > test-failure.t << EOF + > $ true + > should go away (true !) + > $ true + > should stay (false !) + > + > Should remove first line, not second or third + > $ echo 'testing' + > baz*foo (glob) (true !) + > foobar*foo (glob) (false !) + > te*ting (glob) (true !) + > + > Should keep first two lines, remove third and last + > $ echo 'testing' + > test.ng (re) (true !) + > foo.ar (re) (false !) + > b.r (re) (true !) + > missing (?) + > awol (true !) + > + > The "missing" line should stay, even though awol is dropped + > $ echo 'testing' + > test.ng (re) (true !) + > foo.ar (?) + > awol + > missing (?) + > EOF + $ rt test-failure.t + + --- $TESTTMP/test-failure.t + +++ $TESTTMP/test-failure.t.err + @@ -1,11 +1,9 @@ + $ true + - should go away (true !) + $ true + should stay (false !) + + Should remove first line, not second or third + $ echo 'testing' + - baz*foo (glob) (true !) + foobar*foo (glob) (false !) + te*ting (glob) (true !) + + foo.ar (re) (false !) + missing (?) + @@ -13,13 +11,10 @@ + $ echo 'testing' + test.ng (re) (true !) + foo.ar (re) (false !) + - b.r (re) (true !) + missing (?) + - awol (true !) + + The "missing" line should stay, even though awol is dropped + $ echo 'testing' + test.ng (re) (true !) + foo.ar (?) + - awol + missing (?) + + ERROR: test-failure.t output changed + ! + Failed test-failure.t: output changed + # Ran 1 tests, 0 skipped, 1 failed. + python hash seed: * (glob) + [1] + basic failing test $ cat > test-failure.t << EOF > $ echo babar
--- a/tests/test-sparse.t Thu Aug 10 14:23:25 2017 -0400 +++ b/tests/test-sparse.t Thu Aug 10 14:23:41 2017 -0400 @@ -29,23 +29,50 @@ #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 +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
--- a/tests/test-template-engine.t Thu Aug 10 14:23:25 2017 -0400 +++ b/tests/test-template-engine.t Thu Aug 10 14:23:41 2017 -0400 @@ -10,7 +10,7 @@ > def process(self, t, map): > tmpl = self.loader(t) > for k, v in map.iteritems(): - > if k in ('templ', 'ctx', 'repo', 'revcache', 'cache'): + > if k in ('templ', 'ctx', 'repo', 'revcache', 'cache', 'troubles'): > continue > if hasattr(v, '__call__'): > v = v(**map)