Mercurial > hg
changeset 22102:fff8e1cec90f
merge with stable
author | Matt Mackall <mpm@selenic.com> |
---|---|
date | Mon, 11 Aug 2014 11:24:05 -0500 |
parents | 6fa40bd78bc8 (diff) f72b71ba756b (current diff) |
children | 70bdf59d27b6 |
files | mercurial/commands.py |
diffstat | 161 files changed, 1932 insertions(+), 1080 deletions(-) [+] |
line wrap: on
line diff
--- a/contrib/check-code.py Sun Aug 10 23:09:23 2014 -0500 +++ b/contrib/check-code.py Mon Aug 11 11:24:05 2014 -0500 @@ -94,7 +94,7 @@ (r'sed.*-i', "don't use 'sed -i', use a temporary file"), (r'\becho\b.*\\n', "don't use 'echo \\n', use printf"), (r'echo -n', "don't use 'echo -n', use printf"), - (r'(^| )wc[^|]*$\n(?!.*\(re\))', "filter wc output"), + (r'(^| )\bwc\b[^|]*$\n(?!.*\(re\))', "filter wc output"), (r'head -c', "don't use 'head -c', use 'dd'"), (r'tail -n', "don't use the '-n' option to tail, just use '-<num>'"), (r'sha1sum', "don't use sha1sum, use $TESTDIR/md5sum.py"), @@ -179,12 +179,14 @@ ] for i in [0, 1]: - for p, m in testpats[i]: + for tp in testpats[i]: + p = tp[0] + m = tp[1] if p.startswith(r'^'): p = r"^ [$>] (%s)" % p[1:] else: p = r"^ [$>] .*(%s)" % p - utestpats[i].append((p, m)) + utestpats[i].append((p, m) + tp[2:]) utestfilters = [ (r"<<(\S+)((.|\n)*?\n > \1)", rephere),
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/contrib/check-commit Mon Aug 11 11:24:05 2014 -0500 @@ -0,0 +1,55 @@ +#!/usr/bin/env python +# +# Copyright 2014 Matt Mackall <mpm@selenic.com> +# +# A tool/hook to run basic sanity checks on commits/patches for +# submission to Mercurial. Install by adding the following to your +# .hg/hgrc: +# +# [hooks] +# pretxncommit = contrib/check-commit +# +# The hook can be temporarily bypassed with: +# +# $ BYPASS= hg commit +# +# See also: http://mercurial.selenic.com/wiki/ContributingChanges + +import re, sys, os + +errors = [ + (r"[(]bc[)]", "(BC) needs to be uppercase"), + (r"[(]issue \d\d\d", "no space allowed between issue and number"), + (r"[(]bug", "use (issueDDDD) instead of bug"), + (r"^# User [^@\n]+$", "username is not an email address"), + (r"^# .*\n(?!merge with )[^#]\S+[^:] ", + "summary line doesn't start with 'topic: '"), + (r"^# .*\n[A-Z][a-z]\S+", "don't capitalize summary lines"), + (r"^# .*\n.*\.\s+$", "don't add trailing period on summary line"), + (r"^# .*\n.{78,}", "summary line too long"), + (r"^\+\n \n", "adds double empty line"), + (r"\+\s+def [a-z]+_[a-z]", "adds a function with foo_bar naming"), +] + +node = os.environ.get("HG_NODE") + +if node: + commit = os.popen("hg export %s" % node).read() +else: + commit = sys.stdin.read() + +exitcode = 0 +for exp, msg in errors: + m = re.search(exp, commit, re.MULTILINE) + if m: + pos = 0 + for n, l in enumerate(commit.splitlines(True)): + pos += len(l) + if pos >= m.end(): + print "%d: %s" % (n, msg) + print " %s" % l[:-1] + if "BYPASS" not in os.environ: + exitcode = 1 + break + +sys.exit(exitcode)
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/contrib/hg-test-mode.el Mon Aug 11 11:24:05 2014 -0500 @@ -0,0 +1,56 @@ +;; hg-test-mode.el - Major mode for editing Mercurial tests +;; +;; Copyright 2014 Matt Mackall <mpm@selenic.com> +;; "I have no idea what I'm doing" +;; +;; This software may be used and distributed according to the terms of the +;; GNU General Public License version 2 or any later version. +;; +;; To enable, add something like the following to your .emacs: +;; +;; (if (file-exists-p "~/hg/contrib/hg-test-mode.el") +;; (load "~/hg/contrib/hg-test-mode.el")) + +(defvar hg-test-mode-hook nil) + +(defvar hg-test-mode-map + (let ((map (make-keymap))) + (define-key map "\C-j" 'newline-and-indent) + map) + "Keymap for hg test major mode") + +(add-to-list 'auto-mode-alist '("\\.t\\'" . hg-test-mode)) + +(defconst hg-test-font-lock-keywords-1 + (list + '("^ \\(\\$\\|>>>\\) " 1 font-lock-builtin-face) + '("^ \\(>\\|\\.\\.\\.\\) " 1 font-lock-constant-face) + '("\\$?\\(HG\\|TEST\\)\\w+=?" . font-lock-variable-name-face) + '("^ \\([[][0-9]+[]]\\)$" 1 font-lock-warning-face) + '("^ \\(.*?\\)\\(\\( [(][-a-z]+[)]\\)+\\)$" 2 font-lock-type-face) + '("^ \\(.*?\\)\\(\\( [(][-a-z]+[)]\\)*\\)$" 1 font-lock-string-face) + '("^#.*" . font-lock-preprocessor-face) + '("^\\([^ ].*\\)$" 1 font-lock-comment-face) + ) + "Minimal highlighting expressions for hg-test mode") + +(defvar hg-test-font-lock-keywords hg-test-font-lock-keywords-1 + "Default highlighting expressions for hg-test mode") + +(defvar hg-test-mode-syntax-table + (let ((st (make-syntax-table))) + (modify-syntax-entry ?\" "w" st) ;; disable standard quoting + st) +"Syntax table for hg-test mode") + +(defun hg-test-mode () + (interactive) + (kill-all-local-variables) + (use-local-map hg-test-mode-map) + (set-syntax-table hg-test-mode-syntax-table) + (set (make-local-variable 'font-lock-defaults) '(hg-test-font-lock-keywords)) + (setq major-mode 'hg-test-mode) + (setq mode-name "hg-test") + (run-hooks 'hg-test-mode-hook)) + +(provide 'hg-test-mode)
--- a/contrib/revsetbenchmarks.py Sun Aug 10 23:09:23 2014 -0500 +++ b/contrib/revsetbenchmarks.py Mon Aug 11 11:24:05 2014 -0500 @@ -19,8 +19,6 @@ # cannot use argparse, python 2.7 only from optparse import OptionParser - - def check_output(*args, **kwargs): kwargs.setdefault('stderr', PIPE) kwargs.setdefault('stdout', PIPE)
--- a/contrib/simplemerge Sun Aug 10 23:09:23 2014 -0500 +++ b/contrib/simplemerge Mon Aug 11 11:24:05 2014 -0500 @@ -11,8 +11,7 @@ ('a', 'text', None, _('treat all files as text')), ('p', 'print', None, _('print results instead of overwriting LOCAL')), - ('', 'no-minimal', None, - _('do not try to minimize conflict regions')), + ('', 'no-minimal', None, _('no effect (DEPRECATED)')), ('h', 'help', None, _('display help and exit')), ('q', 'quiet', None, _('suppress output'))]
--- a/hgext/fetch.py Sun Aug 10 23:09:23 2014 -0500 +++ b/hgext/fetch.py Mon Aug 11 11:24:05 2014 -0500 @@ -143,8 +143,8 @@ ('Automated merge with %s' % util.removeauth(other.url()))) editopt = opts.get('edit') or opts.get('force_editor') - n = repo.commit(message, opts['user'], opts['date'], - editor=cmdutil.getcommiteditor(edit=editopt)) + editor = cmdutil.getcommiteditor(edit=editopt, editform='fetch') + n = repo.commit(message, opts['user'], opts['date'], editor=editor) ui.status(_('new changeset %d:%s merges remote changes ' 'with local\n') % (repo.changelog.rev(n), short(n)))
--- a/hgext/gpg.py Sun Aug 10 23:09:23 2014 -0500 +++ b/hgext/gpg.py Mon Aug 11 11:24:05 2014 -0500 @@ -277,8 +277,9 @@ % hgnode.short(n) for n in nodes]) try: + editor = cmdutil.getcommiteditor(editform='gpg.sign', **opts) repo.commit(message, opts['user'], opts['date'], match=msigs, - editor=cmdutil.getcommiteditor(**opts)) + editor=editor) except ValueError, inst: raise util.Abort(str(inst))
--- a/hgext/histedit.py Sun Aug 10 23:09:23 2014 -0500 +++ b/hgext/histedit.py Mon Aug 11 11:24:05 2014 -0500 @@ -208,8 +208,6 @@ repo.ui.restoreconfig(phasebackup) return commitfunc - - def applychanges(ui, repo, ctx, opts): """Merge changeset from ctx (only) in the current working directory""" wcpar = repo.dirstate.parents()[0] @@ -293,6 +291,7 @@ extra = commitopts.get('extra') parents = (first.p1().node(), first.p2().node()) + editor = cmdutil.getcommiteditor(edit=True, editform='histedit.fold') new = context.memctx(repo, parents=parents, text=message, @@ -301,7 +300,7 @@ user=user, date=date, extra=extra, - editor=cmdutil.getcommiteditor(edit=True)) + editor=editor) return repo.commitctx(new) def pick(ui, repo, ctx, ha, opts): @@ -405,9 +404,10 @@ _('Fix up the change and run hg histedit --continue')) message = oldctx.description() commit = commitfuncfor(repo, oldctx) + editor = cmdutil.getcommiteditor(edit=True, editform='histedit.mess') new = commit(text=message, user=oldctx.user(), date=oldctx.date(), extra=oldctx.extra(), - editor=cmdutil.getcommiteditor(edit=True)) + editor=editor) newctx = repo[new] if oldctx.node() != newctx.node(): return newctx, [(oldctx.node(), (new,))] @@ -684,7 +684,9 @@ else: message = ctx.description() editopt = action in ('e', 'edit', 'm', 'mess') - editor = cmdutil.getcommiteditor(edit=editopt) + canonaction = {'e': 'edit', 'm': 'mess', 'p': 'pick'} + editform = 'histedit.%s' % canonaction.get(action, action) + editor = cmdutil.getcommiteditor(edit=editopt, editform=editform) commit = commitfuncfor(repo, ctx) new = commit(text=message, user=ctx.user(), date=ctx.date(), extra=ctx.extra(),
--- a/hgext/keyword.py Sun Aug 10 23:09:23 2014 -0500 +++ b/hgext/keyword.py Mon Aug 11 11:24:05 2014 -0500 @@ -1,6 +1,6 @@ # keyword.py - $Keyword$ expansion for Mercurial # -# Copyright 2007-2012 Christian Ebert <blacktrash@gmx.net> +# Copyright 2007-2014 Christian Ebert <blacktrash@gmx.net> # # This software may be used and distributed according to the terms of the # GNU General Public License version 2 or any later version. @@ -87,7 +87,7 @@ from mercurial import scmutil, pathutil from mercurial.hgweb import webcommands from mercurial.i18n import _ -import os, re, shutil, tempfile +import os, re, tempfile cmdtable = {} command = cmdutil.command(cmdtable) @@ -450,7 +450,12 @@ repo.commit(text=msg) ui.status(_('\n\tkeywords expanded\n')) ui.write(repo.wread(fn)) - shutil.rmtree(tmpdir, ignore_errors=True) + for root, dirs, files in os.walk(tmpdir, topdown=False): + for f in files: + util.unlink(os.path.join(root, f)) + for d in dirs: + os.rmdir(os.path.join(root, d)) + os.rmdir(tmpdir) @command('kwexpand', commands.walkopts,
--- a/hgext/largefiles/lfcommands.py Sun Aug 10 23:09:23 2014 -0500 +++ b/hgext/largefiles/lfcommands.py Mon Aug 11 11:24:05 2014 -0500 @@ -510,26 +510,7 @@ updated += update1 - standin = lfutil.standin(lfile) - if standin in repo.dirstate: - stat = repo.dirstate._map[standin] - state, mtime = stat[0], stat[3] - else: - state, mtime = '?', -1 - if state == 'n': - if normallookup or mtime < 0: - # state 'n' doesn't ensure 'clean' in this case - lfdirstate.normallookup(lfile) - else: - lfdirstate.normal(lfile) - elif state == 'm': - lfdirstate.normallookup(lfile) - elif state == 'r': - lfdirstate.remove(lfile) - elif state == 'a': - lfdirstate.add(lfile) - elif state == '?': - lfdirstate.drop(lfile) + lfutil.synclfdirstate(repo, lfdirstate, lfile, normallookup) lfdirstate.write() if printmessage and lfiles:
--- a/hgext/largefiles/lfutil.py Sun Aug 10 23:09:23 2014 -0500 +++ b/hgext/largefiles/lfutil.py Mon Aug 11 11:24:05 2014 -0500 @@ -363,6 +363,28 @@ standins.append((lfile, hash)) return standins +def synclfdirstate(repo, lfdirstate, lfile, normallookup): + lfstandin = standin(lfile) + if lfstandin in repo.dirstate: + stat = repo.dirstate._map[lfstandin] + state, mtime = stat[0], stat[3] + else: + state, mtime = '?', -1 + if state == 'n': + if normallookup or mtime < 0: + # state 'n' doesn't ensure 'clean' in this case + lfdirstate.normallookup(lfile) + else: + lfdirstate.normal(lfile) + elif state == 'm': + lfdirstate.normallookup(lfile) + elif state == 'r': + lfdirstate.remove(lfile) + elif state == 'a': + lfdirstate.add(lfile) + elif state == '?': + lfdirstate.drop(lfile) + def getlfilestoupdate(oldstandins, newstandins): changedstandins = set(oldstandins).symmetric_difference(set(newstandins)) filelist = []
--- a/hgext/largefiles/overrides.py Sun Aug 10 23:09:23 2014 -0500 +++ b/hgext/largefiles/overrides.py Mon Aug 11 11:24:05 2014 -0500 @@ -1140,19 +1140,20 @@ repo.status = oldstatus def overriderollback(orig, ui, repo, **opts): - result = orig(ui, repo, **opts) - merge.update(repo, node=None, branchmerge=False, force=True, - partial=lfutil.isstandin) wlock = repo.wlock() try: + result = orig(ui, repo, **opts) + merge.update(repo, node=None, branchmerge=False, force=True, + partial=lfutil.isstandin) + lfdirstate = lfutil.openlfdirstate(ui, repo) + orphans = set(lfdirstate) lfiles = lfutil.listlfiles(repo) - oldlfiles = lfutil.listlfiles(repo, repo[None].parents()[0].rev()) for file in lfiles: - if file in oldlfiles: - lfdirstate.normallookup(file) - else: - lfdirstate.add(file) + lfutil.synclfdirstate(repo, lfdirstate, file, True) + orphans.discard(file) + for lfile in orphans: + lfdirstate.drop(lfile) lfdirstate.write() finally: wlock.release()
--- a/hgext/largefiles/reposetup.py Sun Aug 10 23:09:23 2014 -0500 +++ b/hgext/largefiles/reposetup.py Mon Aug 11 11:24:05 2014 -0500 @@ -285,6 +285,16 @@ printmessage=False) result = orig(text=text, user=user, date=date, match=match, force=force, editor=editor, extra=extra) + + if result: + lfdirstate = lfutil.openlfdirstate(ui, self) + for f in self[result].files(): + if lfutil.isstandin(f): + lfile = lfutil.splitstandin(f) + lfutil.synclfdirstate(self, lfdirstate, lfile, + False) + lfdirstate.write() + return result # Case 1: user calls commit with no specific files or # include/exclude patterns: refresh and commit all files that
--- a/hgext/mq.py Sun Aug 10 23:09:23 2014 -0500 +++ b/hgext/mq.py Mon Aug 11 11:24:05 2014 -0500 @@ -621,7 +621,7 @@ # apply failed, strip away that rev and merge. hg.clean(repo, head) - strip(self.ui, repo, [n], update=False, backup='strip') + strip(self.ui, repo, [n], update=False, backup=False) ctx = repo[rev] ret = hg.merge(repo, rev) @@ -930,7 +930,12 @@ oldqbase = repo[qfinished[0]] tphase = repo.ui.config('phases', 'new-commit', phases.draft) if oldqbase.phase() > tphase and oldqbase.p1().phase() <= tphase: - phases.advanceboundary(repo, tphase, qfinished) + tr = repo.transaction('qfinish') + try: + phases.advanceboundary(repo, tr, tphase, qfinished) + tr.close() + finally: + tr.release() def delete(self, repo, patches, opts): if not patches and not opts.get('rev'): @@ -1025,6 +1030,7 @@ """ msg = opts.get('msg') edit = opts.get('edit') + editform = opts.get('editform', 'mq.qnew') user = opts.get('user') date = opts.get('date') if date: @@ -1079,7 +1085,7 @@ p.write("# Date %s %s\n\n" % date) defaultmsg = "[mq]: %s" % patchfn - editor = cmdutil.getcommiteditor() + editor = cmdutil.getcommiteditor(editform=editform) if edit: def finishdesc(desc): if desc.rstrip(): @@ -1089,7 +1095,8 @@ # i18n: this message is shown in editor with "HG: " prefix extramsg = _('Leave message empty to use default message.') editor = cmdutil.getcommiteditor(finishdesc=finishdesc, - extramsg=extramsg) + extramsg=extramsg, + editform=editform) commitmsg = msg else: commitmsg = msg or defaultmsg @@ -1456,7 +1463,7 @@ for patch in reversed(self.applied[start:end]): self.ui.status(_("popping %s\n") % patch.name) del self.applied[start:end] - strip(self.ui, repo, [rev], update=False, backup='strip') + strip(self.ui, repo, [rev], update=False, backup=False) for s, state in repo['.'].substate.items(): repo['.'].sub(s).get(state) if self.applied: @@ -1485,6 +1492,7 @@ return 1 msg = opts.get('msg', '').rstrip() edit = opts.get('edit') + editform = opts.get('editform', 'mq.qrefresh') newuser = opts.get('user') newdate = opts.get('date') if newdate: @@ -1645,7 +1653,7 @@ repo.setparents(*cparents) self.applied.pop() self.applieddirty = True - strip(self.ui, repo, [top], update=False, backup='strip') + strip(self.ui, repo, [top], update=False, backup=False) except: # re-raises repo.dirstate.invalidate() raise @@ -1654,7 +1662,7 @@ # might be nice to attempt to roll back strip after this defaultmsg = "[mq]: %s" % patchfn - editor = cmdutil.getcommiteditor() + editor = cmdutil.getcommiteditor(editform=editform) if edit: def finishdesc(desc): if desc.rstrip(): @@ -1664,7 +1672,8 @@ # i18n: this message is shown in editor with "HG: " prefix extramsg = _('Leave message empty to use default message.') editor = cmdutil.getcommiteditor(finishdesc=finishdesc, - extramsg=extramsg) + extramsg=extramsg, + editform=editform) message = msg or "\n".join(ph.message) elif not msg: if not ph.message: @@ -1842,7 +1851,7 @@ update = True else: update = False - strip(self.ui, repo, [rev], update=update, backup='strip') + strip(self.ui, repo, [rev], update=update, backup=False) if qpp: self.ui.warn(_("saved queue repository parents: %s %s\n") % (short(qpp[0]), short(qpp[1]))) @@ -1966,41 +1975,49 @@ lastparent = None diffopts = self.diffopts({'git': git}) - for r in rev: - if not repo[r].mutable(): - raise util.Abort(_('revision %d is not mutable') % r, - hint=_('see "hg help phases" for details')) - p1, p2 = repo.changelog.parentrevs(r) - n = repo.changelog.node(r) - if p2 != nullrev: - raise util.Abort(_('cannot import merge revision %d') % r) - if lastparent and lastparent != r: - raise util.Abort(_('revision %d is not the parent of %d') - % (r, lastparent)) - lastparent = p1 - - if not patchname: - patchname = normname('%d.diff' % r) - checkseries(patchname) - self.checkpatchname(patchname, force) - self.fullseries.insert(0, patchname) - - patchf = self.opener(patchname, "w") - cmdutil.export(repo, [n], fp=patchf, opts=diffopts) - patchf.close() - - se = statusentry(n, patchname) - self.applied.insert(0, se) - - self.added.append(patchname) - imported.append(patchname) - patchname = None - if rev and repo.ui.configbool('mq', 'secret', False): - # if we added anything with --rev, move the secret root - phases.retractboundary(repo, phases.secret, [n]) - self.parseseries() - self.applieddirty = True - self.seriesdirty = True + tr = repo.transaction('qimport') + try: + for r in rev: + if not repo[r].mutable(): + raise util.Abort(_('revision %d is not mutable') % r, + hint=_('see "hg help phases" ' + 'for details')) + p1, p2 = repo.changelog.parentrevs(r) + n = repo.changelog.node(r) + if p2 != nullrev: + raise util.Abort(_('cannot import merge revision %d') + % r) + if lastparent and lastparent != r: + raise util.Abort(_('revision %d is not the parent of ' + '%d') + % (r, lastparent)) + lastparent = p1 + + if not patchname: + patchname = normname('%d.diff' % r) + checkseries(patchname) + self.checkpatchname(patchname, force) + self.fullseries.insert(0, patchname) + + patchf = self.opener(patchname, "w") + cmdutil.export(repo, [n], fp=patchf, opts=diffopts) + patchf.close() + + se = statusentry(n, patchname) + self.applied.insert(0, se) + + self.added.append(patchname) + imported.append(patchname) + patchname = None + if rev and repo.ui.configbool('mq', 'secret', False): + # if we added anything with --rev, move the secret root + phases.retractboundary(repo, tr, phases.secret, [n]) + self.parseseries() + self.applieddirty = True + self.seriesdirty = True + tr.close() + finally: + tr.release() for i, filename in enumerate(files): if existing: @@ -2585,7 +2602,8 @@ diffopts = q.patchopts(q.diffopts(), *patches) wlock = repo.wlock() try: - q.refresh(repo, msg=message, git=diffopts.git, edit=opts.get('edit')) + q.refresh(repo, msg=message, git=diffopts.git, edit=opts.get('edit'), + editform='mq.qfold') q.delete(repo, patches, opts) q.savedirty() finally:
--- a/hgext/purge.py Sun Aug 10 23:09:23 2014 -0500 +++ b/hgext/purge.py Mon Aug 11 11:24:05 2014 -0500 @@ -26,7 +26,7 @@ from mercurial import util, commands, cmdutil, scmutil from mercurial.i18n import _ -import os, stat +import os cmdtable = {} command = cmdutil.command(cmdtable) @@ -95,17 +95,6 @@ else: ui.write('%s%s' % (name, eol)) - def removefile(path): - try: - os.remove(path) - except OSError: - # read-only files cannot be unlinked under Windows - s = os.stat(path) - if (s.st_mode & stat.S_IWRITE) != 0: - raise - os.chmod(path, stat.S_IMODE(s.st_mode) | stat.S_IWRITE) - os.remove(path) - directories = [] match = scmutil.match(repo[None], dirs, opts) match.explicitdir = match.traversedir = directories.append @@ -115,7 +104,7 @@ for f in sorted(status[4] + status[5]): if act: ui.note(_('removing file %s\n') % f) - remove(removefile, f) + remove(util.unlink, f) if removedirs: for f in sorted(directories, reverse=True):
--- a/hgext/rebase.py Sun Aug 10 23:09:23 2014 -0500 +++ b/hgext/rebase.py Mon Aug 11 11:24:05 2014 -0500 @@ -138,7 +138,7 @@ skipped = set() targetancestors = set() - editor = cmdutil.getcommiteditor(**opts) + editor = cmdutil.getcommiteditor(editform='rebase.normal', **opts) lock = wlock = None try: @@ -383,7 +383,8 @@ for rebased in state: if rebased not in skipped and state[rebased] > nullmerge: commitmsg += '\n* %s' % repo[rebased].description() - editor = cmdutil.getcommiteditor(edit=True) + editform = 'rebase.collapse' + editor = cmdutil.getcommiteditor(edit=True, editform=editform) newrev = concludenode(repo, rev, p1, external, commitmsg=commitmsg, extrafn=extrafn, editor=editor) for oldrev in state.iterkeys(): @@ -468,15 +469,18 @@ extra = {'rebase_source': ctx.hex()} if extrafn: extrafn(ctx, extra) - # Commit might fail if unresolved files exist - newrev = repo.commit(text=commitmsg, user=ctx.user(), - date=ctx.date(), extra=extra, editor=editor) + + backup = repo.ui.backupconfig('phases', 'new-commit') + try: + targetphase = max(ctx.phase(), phases.draft) + repo.ui.setconfig('phases', 'new-commit', targetphase, 'rebase') + # Commit might fail if unresolved files exist + newrev = repo.commit(text=commitmsg, user=ctx.user(), + date=ctx.date(), extra=extra, editor=editor) + finally: + repo.ui.restoreconfig(backup) + repo.dirstate.setbranch(repo[newrev].branch()) - targetphase = max(ctx.phase(), phases.draft) - # retractboundary doesn't overwrite upper phase inherited from parent - newnode = repo[newrev].node() - if newnode: - phases.retractboundary(repo, targetphase, [newnode]) return newrev except util.Abort: # Invalidate the previous setparents
--- a/hgext/shelve.py Sun Aug 10 23:09:23 2014 -0500 +++ b/hgext/shelve.py Mon Aug 11 11:24:05 2014 -0500 @@ -73,7 +73,8 @@ try: gen = exchange.readbundle(self.repo.ui, fp, self.fname, self.vfs) changegroup.addchangegroup(self.repo, gen, 'unshelve', - 'bundle:' + self.vfs.join(self.fname)) + 'bundle:' + self.vfs.join(self.fname), + targetphase=phases.secret) finally: fp.close() @@ -177,10 +178,14 @@ hasmq = util.safehasattr(repo, 'mq') if hasmq: saved, repo.mq.checkapplied = repo.mq.checkapplied, False + backup = repo.ui.backupconfig('phases', 'new-commit') try: + repo.ui. setconfig('phases', 'new-commit', phases.secret) + editor = cmdutil.getcommiteditor(editform='shelve.shelve', **opts) return repo.commit(message, user, opts.get('date'), match, - editor=cmdutil.getcommiteditor(**opts)) + editor=editor) finally: + repo.ui.restoreconfig(backup) if hasmq: repo.mq.checkapplied = saved @@ -234,8 +239,6 @@ ui.status(_("nothing changed\n")) return 1 - phases.retractboundary(repo, phases.secret, [node]) - fp = shelvedfile(repo, name, 'files').opener('wb') fp.write('\0'.join(shelvedfiles)) @@ -388,7 +391,7 @@ mergefiles(ui, repo, state.wctx, state.pendingctx) - repair.strip(ui, repo, state.stripnodes, backup='none', topic='shelve') + repair.strip(ui, repo, state.stripnodes, backup=False, topic='shelve') shelvedstate.clear(repo) ui.warn(_("unshelve of '%s' aborted\n") % state.name) finally: @@ -457,7 +460,7 @@ mergefiles(ui, repo, state.wctx, shelvectx) state.stripnodes.append(shelvectx.node()) - repair.strip(ui, repo, state.stripnodes, backup='none', topic='shelve') + repair.strip(ui, repo, state.stripnodes, backup=False, topic='shelve') shelvedstate.clear(repo) unshelvecleanup(ui, repo, state.name, opts) ui.status(_("unshelve of '%s' complete\n") % state.name) @@ -558,10 +561,13 @@ if hasmq: saved, repo.mq.checkapplied = repo.mq.checkapplied, False + backup = repo.ui.backupconfig('phases', 'new-commit') try: + repo.ui. setconfig('phases', 'new-commit', phases.secret) return repo.commit(message, 'shelve@localhost', opts.get('date'), match) finally: + repo.ui.restoreconfig(backup) if hasmq: repo.mq.checkapplied = saved @@ -574,8 +580,6 @@ ui.quiet = True shelvedfile(repo, basename, 'hg').applybundle() - nodes = [ctx.node() for ctx in repo.set('%d:', oldtiprev)] - phases.retractboundary(repo, phases.secret, nodes) ui.quiet = oldquiet
--- a/hgext/strip.py Sun Aug 10 23:09:23 2014 -0500 +++ b/hgext/strip.py Mon Aug 11 11:24:05 2014 -0500 @@ -42,7 +42,7 @@ raise util.Abort(_("local changed subrepos found" + excsuffix)) return m, a, r, d -def strip(ui, repo, revs, update=True, backup="all", force=None, bookmark=None): +def strip(ui, repo, revs, update=True, backup=True, force=None, bookmark=None): wlock = lock = None try: wlock = repo.wlock() @@ -114,11 +114,9 @@ Return 0 on success. """ - backup = 'all' - if opts.get('backup'): - backup = 'strip' - elif opts.get('no_backup') or opts.get('nobackup'): - backup = 'none' + backup = True + if opts.get('no_backup') or opts.get('nobackup'): + backup = False cl = repo.changelog revs = list(revs) + opts.get('rev')
--- a/hgext/transplant.py Sun Aug 10 23:09:23 2014 -0500 +++ b/hgext/transplant.py Mon Aug 11 11:24:05 2014 -0500 @@ -86,7 +86,7 @@ self.opener = scmutil.opener(self.path) self.transplants = transplants(self.path, 'transplants', opener=self.opener) - self.editor = cmdutil.getcommiteditor(**opts) + self.editor = cmdutil.getcommiteditor(editform='transplant', **opts) def applied(self, repo, node, parent): '''returns True if a node is already an ancestor of parent
--- a/mercurial/branchmap.py Sun Aug 10 23:09:23 2014 -0500 +++ b/mercurial/branchmap.py Mon Aug 11 11:24:05 2014 -0500 @@ -62,8 +62,6 @@ partial = None return partial - - ### Nearest subset relation # Nearest subset of filter X is a filter Y so that: # * Y is included in X,
--- a/mercurial/changegroup.py Sun Aug 10 23:09:23 2014 -0500 +++ b/mercurial/changegroup.py Mon Aug 11 11:24:05 2014 -0500 @@ -569,7 +569,8 @@ return revisions, files -def addchangegroup(repo, source, srctype, url, emptyok=False): +def addchangegroup(repo, source, srctype, url, emptyok=False, + targetphase=phases.draft): """Add the changegroup returned by source.read() to this repo. srctype is a string like 'push', 'pull', or 'unbundle'. url is the URL of the repo where this changegroup is coming from. @@ -699,15 +700,18 @@ # We should not use added here but the list of all change in # the bundle if publishing: - phases.advanceboundary(repo, phases.public, srccontent) + phases.advanceboundary(repo, tr, phases.public, srccontent) else: - phases.advanceboundary(repo, phases.draft, srccontent) - phases.retractboundary(repo, phases.draft, added) + # Those changesets have been pushed from the outside, their + # phases are going to be pushed alongside. Therefor + # `targetphase` is ignored. + phases.advanceboundary(repo, tr, phases.draft, srccontent) + phases.retractboundary(repo, tr, phases.draft, added) elif srctype != 'strip': # publishing only alter behavior during push # # strip should not touch boundary at all - phases.retractboundary(repo, phases.draft, added) + phases.retractboundary(repo, tr, targetphase, added) # make changelog see real files again cl.finalize(trp)
--- a/mercurial/cmdutil.py Sun Aug 10 23:09:23 2014 -0500 +++ b/mercurial/cmdutil.py Mon Aug 11 11:24:05 2014 -0500 @@ -109,7 +109,8 @@ (logfile, inst.strerror)) return message -def getcommiteditor(edit=False, finishdesc=None, extramsg=None, **opts): +def getcommiteditor(edit=False, finishdesc=None, extramsg=None, + editform='', **opts): """get appropriate commit message editor according to '--edit' option 'finishdesc' is a function to be called with edited commit message @@ -122,6 +123,9 @@ 'Leave message empty to abort commit' line. 'HG: ' prefix and EOL is automatically added. + 'editform' is a dot-separated list of names, to distinguish + the purpose of commit text editing. + 'getcommiteditor' returns 'commitforceeditor' regardless of 'edit', if one of 'finishdesc' or 'extramsg' is specified, because they are specific for usage in MQ. @@ -129,7 +133,10 @@ if edit or finishdesc or extramsg: return lambda r, c, s: commitforceeditor(r, c, s, finishdesc=finishdesc, - extramsg=extramsg) + extramsg=extramsg, + editform=editform) + elif editform: + return lambda r, c, s: commiteditor(r, c, s, editform=editform) else: return commiteditor @@ -586,7 +593,7 @@ tmpname, message, user, date, branch, nodeid, p1, p2 = \ patch.extract(ui, hunk) - editor = getcommiteditor(**opts) + editor = getcommiteditor(editform='import.normal', **opts) update = not opts.get('bypass') strip = opts["strip"] sim = float(opts.get('similarity') or 0) @@ -680,12 +687,13 @@ files, eolmode=None) except patch.PatchError, e: raise util.Abort(str(e)) + editor = getcommiteditor(editform='import.bypass') memctx = context.makememctx(repo, (p1.node(), p2.node()), message, opts.get('user') or user, opts.get('date') or date, branch, files, store, - editor=getcommiteditor()) + editor=editor) n = memctx.commit() finally: store.close() @@ -1570,8 +1578,14 @@ if not slowpath: for f in match.files(): if follow and f not in pctx: - raise util.Abort(_('cannot follow file not in parent ' - 'revision: "%s"') % f) + # If the file exists, it may be a directory, so let it + # take the slow path. + if os.path.exists(repo.wjoin(f)): + slowpath = True + continue + else: + raise util.Abort(_('cannot follow file not in parent ' + 'revision: "%s"') % f) filelog = repo.file(f) if not filelog: # A zero count may be a directory or deleted file, so @@ -1595,9 +1609,6 @@ if slowpath: # See walkchangerevs() slow path. # - if follow: - raise util.Abort(_('can only follow copies/renames for explicit ' - 'filenames')) # pats/include/exclude cannot be represented as separate # revset expressions as their filtering logic applies at file # level. For instance "-I a -X a" matches a revision touching @@ -1629,7 +1640,10 @@ filematcher = None if opts.get('patch') or opts.get('stat'): - if follow and not match.always(): + # When following files, track renames via a special matcher. + # If we're forced to take the slowpath it means we're following + # at least one pattern/directory, so don't bother with rename tracking. + if follow and not match.always() and not slowpath: # _makelogfilematcher expects its files argument to be relative to # the repo root, so use match.files(), not pats. filematcher = _makelogfilematcher(repo, match.files(), followfirst) @@ -2093,9 +2107,10 @@ user = opts.get('user') or old.user() date = opts.get('date') or old.date() - editor = getcommiteditor(**opts) + editform = 'commit.amend' + editor = getcommiteditor(editform=editform, **opts) if not message: - editor = getcommiteditor(edit=True) + editor = getcommiteditor(edit=True, editform=editform) message = old.description() pureextra = extra.copy() @@ -2169,17 +2184,24 @@ lockmod.release(lock, wlock) return newid -def commiteditor(repo, ctx, subs): +def commiteditor(repo, ctx, subs, editform=''): if ctx.description(): return ctx.description() - return commitforceeditor(repo, ctx, subs) + return commitforceeditor(repo, ctx, subs, editform=editform) -def commitforceeditor(repo, ctx, subs, finishdesc=None, extramsg=None): +def commitforceeditor(repo, ctx, subs, finishdesc=None, extramsg=None, + editform=''): if not extramsg: extramsg = _("Leave message empty to abort commit.") - tmpl = repo.ui.config('committemplate', 'changeset', '').strip() - if tmpl: - committext = buildcommittemplate(repo, ctx, subs, extramsg, tmpl) + + forms = [e for e in editform.split('.') if e] + forms.insert(0, 'changeset') + while forms: + tmpl = repo.ui.config('committemplate', '.'.join(forms)) + if tmpl: + committext = buildcommittemplate(repo, ctx, subs, extramsg, tmpl) + break + forms.pop() else: committext = buildcommittext(repo, ctx, subs, extramsg) @@ -2206,6 +2228,10 @@ except SyntaxError, inst: raise util.Abort(inst.args[0]) + for k, v in repo.ui.configitems('committemplate'): + if k != 'changeset': + t.t.cache[k] = v + if not extramsg: extramsg = '' # ensure that extramsg is string
--- a/mercurial/commands.py Sun Aug 10 23:09:23 2014 -0500 +++ b/mercurial/commands.py Mon Aug 11 11:24:05 2014 -0500 @@ -505,11 +505,12 @@ def commitfunc(ui, repo, message, match, opts): - e = cmdutil.getcommiteditor(**opts) + editform = 'backout' + e = cmdutil.getcommiteditor(editform=editform, **opts) if not message: # we don't translate commit messages message = "Backed out changeset %s" % short(node) - e = cmdutil.getcommiteditor(edit=True) + e = cmdutil.getcommiteditor(edit=True, editform=editform) return repo.commit(message, opts.get('user'), opts.get('date'), match, editor=e) newnode = cmdutil.commit(ui, repo, commitfunc, [], opts) @@ -1385,9 +1386,6 @@ # Let --subrepos on the command line override config setting. ui.setconfig('ui', 'commitsubrepos', True, 'commit') - # Save this for restoring it later - oldcommitphase = ui.config('phases', 'new-commit') - cmdutil.checkunfinished(repo, commit=True) branch = repo[None].branch() @@ -1441,21 +1439,24 @@ newmarks.write() else: def commitfunc(ui, repo, message, match, opts): + backup = ui.backupconfig('phases', 'new-commit') + baseui = repo.baseui + basebackup = baseui.backupconfig('phases', 'new-commit') try: if opts.get('secret'): ui.setconfig('phases', 'new-commit', 'secret', 'commit') # Propagate to subrepos - repo.baseui.setconfig('phases', 'new-commit', 'secret', - 'commit') - + baseui.setconfig('phases', 'new-commit', 'secret', 'commit') + + editform = 'commit.normal' + editor = cmdutil.getcommiteditor(editform=editform, **opts) return repo.commit(message, opts.get('user'), opts.get('date'), match, - editor=cmdutil.getcommiteditor(**opts), + editor=editor, extra=extra) finally: - ui.setconfig('phases', 'new-commit', oldcommitphase, 'commit') - repo.baseui.setconfig('phases', 'new-commit', oldcommitphase, - 'commit') + ui.restoreconfig(backup) + repo.baseui.restoreconfig(basebackup) node = cmdutil.commit(ui, repo, commitfunc, pats, opts) @@ -3054,6 +3055,7 @@ ('c', 'continue', False, _('resume interrupted graft')), ('e', 'edit', False, _('invoke editor on commit messages')), ('', 'log', None, _('append graft info to log message')), + ('f', 'force', False, _('force graft')), ('D', 'currentdate', False, _('record the current date as commit date')), ('U', 'currentuser', False, @@ -3077,6 +3079,10 @@ (grafted from CHANGESETHASH) + If --force is specified, revisions will be grafted even if they + are already ancestors of or have been grafted to the destination. + This is useful when the revisions have since been backed out. + If a graft merge results in conflicts, the graft process is interrupted so that the current merge can be manually resolved. Once all conflicts are addressed, the graft process can be @@ -3084,7 +3090,8 @@ .. note:: - The -c/--continue option does not reapply earlier options. + The -c/--continue option does not reapply earlier options, except + for --force. .. container:: verbose @@ -3121,7 +3128,7 @@ if not opts.get('date') and opts.get('currentdate'): opts['date'] = "%d %d" % util.makedate() - editor = cmdutil.getcommiteditor(**opts) + editor = cmdutil.getcommiteditor(editform='graft', **opts) cont = False if opts['continue']: @@ -3150,52 +3157,59 @@ if not revs: return -1 - # check for ancestors of dest branch - crev = repo['.'].rev() - ancestors = repo.changelog.ancestors([crev], inclusive=True) - # Cannot use x.remove(y) on smart set, this has to be a list. - # XXX make this lazy in the future - revs = list(revs) - # don't mutate while iterating, create a copy - for rev in list(revs): - if rev in ancestors: - ui.warn(_('skipping ancestor revision %s\n') % rev) - # XXX remove on list is slow - revs.remove(rev) - if not revs: - return -1 - - # analyze revs for earlier grafts - ids = {} - for ctx in repo.set("%ld", revs): - ids[ctx.hex()] = ctx.rev() - n = ctx.extra().get('source') - if n: - ids[n] = ctx.rev() - - # check ancestors for earlier grafts - ui.debug('scanning for duplicate grafts\n') - - for rev in repo.changelog.findmissingrevs(revs, [crev]): - ctx = repo[rev] - n = ctx.extra().get('source') - if n in ids: - r = repo[n].rev() - if r in revs: - ui.warn(_('skipping revision %s (already grafted to %s)\n') - % (r, rev)) + # Don't check in the --continue case, in effect retaining --force across + # --continues. That's because without --force, any revisions we decided to + # skip would have been filtered out here, so they wouldn't have made their + # way to the graftstate. With --force, any revisions we would have otherwise + # skipped would not have been filtered out, and if they hadn't been applied + # already, they'd have been in the graftstate. + if not (cont or opts.get('force')): + # check for ancestors of dest branch + crev = repo['.'].rev() + ancestors = repo.changelog.ancestors([crev], inclusive=True) + # Cannot use x.remove(y) on smart set, this has to be a list. + # XXX make this lazy in the future + revs = list(revs) + # don't mutate while iterating, create a copy + for rev in list(revs): + if rev in ancestors: + ui.warn(_('skipping ancestor revision %s\n') % rev) + # XXX remove on list is slow + revs.remove(rev) + if not revs: + return -1 + + # analyze revs for earlier grafts + ids = {} + for ctx in repo.set("%ld", revs): + ids[ctx.hex()] = ctx.rev() + n = ctx.extra().get('source') + if n: + ids[n] = ctx.rev() + + # check ancestors for earlier grafts + ui.debug('scanning for duplicate grafts\n') + + for rev in repo.changelog.findmissingrevs(revs, [crev]): + ctx = repo[rev] + n = ctx.extra().get('source') + if n in ids: + r = repo[n].rev() + if r in revs: + ui.warn(_('skipping revision %s (already grafted to %s)\n') + % (r, rev)) + revs.remove(r) + elif ids[n] in revs: + ui.warn(_('skipping already grafted revision %s ' + '(%s also has origin %d)\n') % (ids[n], rev, r)) + revs.remove(ids[n]) + elif ctx.hex() in ids: + r = ids[ctx.hex()] + ui.warn(_('skipping already grafted revision %s ' + '(was grafted from %d)\n') % (r, rev)) revs.remove(r) - elif ids[n] in revs: - ui.warn(_('skipping already grafted revision %s ' - '(%s also has origin %d)\n') % (ids[n], rev, r)) - revs.remove(ids[n]) - elif ctx.hex() in ids: - r = ids[ctx.hex()] - ui.warn(_('skipping already grafted revision %s ' - '(was grafted from %d)\n') % (r, rev)) - revs.remove(r) - if not revs: - return -1 + if not revs: + return -1 wlock = repo.wlock() try: @@ -4027,11 +4041,11 @@ rev = scmutil.revsingle(repo, opts.get('rev'), None).node() ret = 1 - m = scmutil.match(repo[rev], pats, opts, default='relglob') + ctx = repo[rev] + m = scmutil.match(ctx, pats, opts, default='relglob') m.bad = lambda x, y: False - for abs in repo[rev].walk(m): - if not rev and abs not in repo.dirstate: - continue + + for abs in ctx.matches(m): if opts.get('fullpath'): ui.write(repo.wjoin(abs), end) else: @@ -4560,17 +4574,22 @@ ctx = repo[r] ui.write('%i: %s\n' % (ctx.rev(), ctx.phasestr())) else: + tr = None lock = repo.lock() try: + tr = repo.transaction("phase") # set phase if not revs: raise util.Abort(_('empty revision set')) nodes = [repo[r].node() for r in revs] olddata = repo._phasecache.getphaserevs(repo)[:] - phases.advanceboundary(repo, targetphase, nodes) + phases.advanceboundary(repo, tr, targetphase, nodes) if opts['force']: - phases.retractboundary(repo, targetphase, nodes) + phases.retractboundary(repo, tr, targetphase, nodes) + tr.close() finally: + if tr is not None: + tr.release() lock.release() # moving revision from public to draft may hide them # We have to check result on an unfiltered repository @@ -5785,7 +5804,11 @@ if date: date = util.parsedate(date) - editor = cmdutil.getcommiteditor(**opts) + if opts.get('remove'): + editform = 'tag.remove' + else: + editform = 'tag.add' + editor = cmdutil.getcommiteditor(editform=editform, **opts) # don't allow tagging the null rev if (not opts.get('remove') and
--- a/mercurial/config.py Sun Aug 10 23:09:23 2014 -0500 +++ b/mercurial/config.py Mon Aug 11 11:24:05 2014 -0500 @@ -76,7 +76,7 @@ # no data before, remove everything section, item = data if section in self._data: - del self._data[section][item] + self._data[section].pop(item, None) self._source.pop((section, item), None) def parse(self, src, data, sections=None, remap=None, include=None):
--- a/mercurial/context.py Sun Aug 10 23:09:23 2014 -0500 +++ b/mercurial/context.py Mon Aug 11 11:24:05 2014 -0500 @@ -276,7 +276,7 @@ def dirs(self): return self._dirs - def dirty(self): + def dirty(self, missing=False, merge=True, branch=True): return False def status(self, other=None, match=None, listignored=False, @@ -598,6 +598,9 @@ continue match.bad(fn, _('no such file in rev %s') % self) + def matches(self, match): + return self.walk(match) + class basefilectx(object): """A filecontext object represents the common logic for its children: filectx: read-only access to a filerevision that is already present @@ -711,6 +714,10 @@ return util.binary(self.data()) except IOError: return False + def isexec(self): + return 'x' in self.flags() + def islink(self): + return 'l' in self.flags() def cmp(self, fctx): """compare with other file context @@ -1144,6 +1151,9 @@ return sorted(self._repo.dirstate.walk(match, sorted(self.substate), True, False)) + def matches(self, match): + return sorted(self._repo.dirstate.matches(match)) + def ancestors(self): for a in self._repo.changelog.ancestors( [p.rev() for p in self._parents]): @@ -1546,6 +1556,14 @@ # invert comparison to reuse the same code path return fctx.cmp(self) + def remove(self, ignoremissing=False): + """wraps unlink for a repo's working directory""" + util.unlinkpath(self._repo.wjoin(self._path), ignoremissing) + + def write(self, data, flags): + """wraps repo.wwrite""" + self._repo.wwrite(self._path, data, flags) + class memctx(committablectx): """Use memctx to perform in-memory commits via localrepo.commitctx(). @@ -1586,6 +1604,20 @@ self._filectxfn = filectxfn self.substate = {} + # if store is not callable, wrap it in a function + if not callable(filectxfn): + def getfilectx(repo, memctx, path): + fctx = filectxfn[path] + # this is weird but apparently we only keep track of one parent + # (why not only store that instead of a tuple?) + copied = fctx.renamed() + if copied: + copied = copied[0] + return memfilectx(repo, path, fctx.data(), + islink=fctx.islink(), isexec=fctx.isexec(), + copied=copied, memctx=memctx) + self._filectxfn = getfilectx + self._extra = extra and extra.copy() or {} if self._extra.get('branch', '') == '': self._extra['branch'] = 'default' @@ -1613,7 +1645,7 @@ for f, fnode in man.iteritems(): p1node = nullid p2node = nullid - p = pctx[f].parents() + p = pctx[f].parents() # if file isn't in pctx, check p2? if len(p) > 0: p1node = p[0].node() if len(p) > 1: @@ -1650,9 +1682,14 @@ return len(self.data()) def flags(self): return self._flags - def isexec(self): - return 'x' in self._flags - def islink(self): - return 'l' in self._flags def renamed(self): return self._copied + + def remove(self, ignoremissing=False): + """wraps unlink for a repo's working directory""" + # need to figure out what to do here + del self._changectx[self._path] + + def write(self, data, flags): + """wraps repo.wwrite""" + self._data = data
--- a/mercurial/dirstate.py Sun Aug 10 23:09:23 2014 -0500 +++ b/mercurial/dirstate.py Mon Aug 11 11:24:05 2014 -0500 @@ -873,3 +873,21 @@ return (lookup, modified, added, removed, deleted, unknown, ignored, clean) + + def matches(self, match): + ''' + return files in the dirstate (in whatever state) filtered by match + ''' + dmap = self._map + if match.always(): + return dmap.keys() + files = match.files() + if match.matchfn == match.exact: + # fast path -- filter the other way around, since typically files is + # much smaller than dmap + return [f for f in files if f in dmap] + if not match.anypats() and util.all(fn in dmap for fn in files): + # fast path -- all the values are known to be files, so just return + # that + return list(files) + return [f for f in dmap if match(f)]
--- a/mercurial/exchange.py Sun Aug 10 23:09:23 2014 -0500 +++ b/mercurial/exchange.py Mon Aug 11 11:24:05 2014 -0500 @@ -77,8 +77,57 @@ self.remoteheads = None # testable as a boolean indicating if any nodes are missing locally. self.incoming = None - # set of all heads common after changeset bundle push - self.commonheads = None + # phases changes that must be pushed along side the changesets + self.outdatedphases = None + # phases changes that must be pushed if changeset push fails + self.fallbackoutdatedphases = None + # outgoing obsmarkers + self.outobsmarkers = set() + + @util.propertycache + def futureheads(self): + """future remote heads if the changeset push succeeds""" + return self.outgoing.missingheads + + @util.propertycache + def fallbackheads(self): + """future remote heads if the changeset push fails""" + if self.revs is None: + # not target to push, all common are relevant + return self.outgoing.commonheads + unfi = self.repo.unfiltered() + # I want cheads = heads(::missingheads and ::commonheads) + # (missingheads is revs with secret changeset filtered out) + # + # This can be expressed as: + # cheads = ( (missingheads and ::commonheads) + # + (commonheads and ::missingheads))" + # ) + # + # while trying to push we already computed the following: + # common = (::commonheads) + # missing = ((commonheads::missingheads) - commonheads) + # + # We can pick: + # * missingheads part of common (::commonheads) + common = set(self.outgoing.common) + nm = self.repo.changelog.nodemap + cheads = [node for node in self.revs if nm[node] in common] + # and + # * commonheads parents on missing + revset = unfi.set('%ln and parents(roots(%ln))', + self.outgoing.commonheads, + self.outgoing.missing) + cheads.extend(c.node() for c in revset) + return cheads + + @property + def commonheads(self): + """set of all common heads after changeset bundle push""" + if self.ret: + return self.futureheads + else: + return self.fallbackheads def push(repo, remote, force=False, revs=None, newbranch=False): '''Push outgoing changesets (limited by revs) from a local @@ -136,7 +185,6 @@ and pushop.remote.capable('bundle2-exp')): _pushbundle2(pushop) _pushchangeset(pushop) - _pushcomputecommonheads(pushop) _pushsyncphase(pushop) _pushobsolete(pushop) finally: @@ -149,8 +197,39 @@ _pushbookmark(pushop) return pushop.ret +# list of steps to perform discovery before push +pushdiscoveryorder = [] + +# Mapping between step name and function +# +# This exists to help extensions wrap steps if necessary +pushdiscoverymapping = {} + +def pushdiscovery(stepname): + """decorator for function performing discovery before push + + The function is added to the step -> function mapping and appended to the + list of steps. Beware that decorated function will be added in order (this + may matter). + + You can only use this decorator for a new step, if you want to wrap a step + from an extension, change the pushdiscovery dictionary directly.""" + def dec(func): + assert stepname not in pushdiscoverymapping + pushdiscoverymapping[stepname] = func + pushdiscoveryorder.append(stepname) + return func + return dec + def _pushdiscovery(pushop): - # discovery + """Run all discovery steps""" + for stepname in pushdiscoveryorder: + step = pushdiscoverymapping[stepname] + step(pushop) + +@pushdiscovery('changeset') +def _pushdiscoverychangeset(pushop): + """discover the changeset that need to be pushed""" unfi = pushop.repo.unfiltered() fci = discovery.findcommonincoming commoninc = fci(unfi, pushop.remote, force=pushop.force) @@ -162,6 +241,45 @@ pushop.remoteheads = remoteheads pushop.incoming = inc +@pushdiscovery('phase') +def _pushdiscoveryphase(pushop): + """discover the phase that needs to be pushed + + (computed for both success and failure case for changesets push)""" + outgoing = pushop.outgoing + unfi = pushop.repo.unfiltered() + remotephases = pushop.remote.listkeys('phases') + publishing = remotephases.get('publishing', False) + ana = phases.analyzeremotephases(pushop.repo, + pushop.fallbackheads, + remotephases) + pheads, droots = ana + extracond = '' + if not publishing: + extracond = ' and public()' + revset = 'heads((%%ln::%%ln) %s)' % extracond + # Get the list of all revs draft on remote by public here. + # XXX Beware that revset break if droots is not strictly + # XXX root we may want to ensure it is but it is costly + fallback = list(unfi.set(revset, droots, pushop.fallbackheads)) + if not outgoing.missing: + future = fallback + else: + # adds changeset we are going to push as draft + # + # should not be necessary for pushblishing server, but because of an + # issue fixed in xxxxx we have to do it anyway. + fdroots = list(unfi.set('roots(%ln + %ln::)', + outgoing.missing, droots)) + fdroots = [f.node() for f in fdroots] + future = list(unfi.set(revset, fdroots, pushop.futureheads)) + pushop.outdatedphases = future + pushop.fallbackoutdatedphases = fallback + +@pushdiscovery('obsmarker') +def _pushdiscoveryobsmarkers(pushop): + pushop.outobsmarkers = pushop.repo.obsstore + def _pushcheckoutgoing(pushop): outgoing = pushop.outgoing unfi = pushop.repo.unfiltered() @@ -201,6 +319,31 @@ newbm) return True +# List of names of steps to perform for an outgoing bundle2, order matters. +b2partsgenorder = [] + +# Mapping between step name and function +# +# This exists to help extensions wrap steps if necessary +b2partsgenmapping = {} + +def b2partsgenerator(stepname): + """decorator for function generating bundle2 part + + The function is added to the step -> function mapping and appended to the + list of steps. Beware that decorated functions will be added in order + (this may matter). + + You can only use this decorator for new steps, if you want to wrap a step + from an extension, attack the b2partsgenmapping dictionary directly.""" + def dec(func): + assert stepname not in b2partsgenmapping + b2partsgenmapping[stepname] = func + b2partsgenorder.append(stepname) + return func + return dec + +@b2partsgenerator('changeset') def _pushb2ctx(pushop, bundler): """handle changegroup push through bundle2 @@ -227,8 +370,37 @@ pushop.ret = cgreplies['changegroup'][0]['return'] return handlereply -# list of function that may decide to add parts to an outgoing bundle2 -bundle2partsgenerators = [_pushb2ctx] +@b2partsgenerator('phase') +def _pushb2phases(pushop, bundler): + """handle phase push through bundle2""" + if 'phases' in pushop.stepsdone: + return + b2caps = bundle2.bundle2caps(pushop.remote) + if not 'b2x:pushkey' in b2caps: + return + pushop.stepsdone.add('phases') + part2node = [] + enc = pushkey.encode + for newremotehead in pushop.outdatedphases: + part = bundler.newpart('b2x:pushkey') + part.addparam('namespace', enc('phases')) + part.addparam('key', enc(newremotehead.hex())) + part.addparam('old', enc(str(phases.draft))) + part.addparam('new', enc(str(phases.public))) + part2node.append((part.id, newremotehead)) + def handlereply(op): + for partid, node in part2node: + partrep = op.records.getreplies(partid) + results = partrep['pushkey'] + assert len(results) <= 1 + msg = None + if not results: + msg = _('server ignored update of %s to public!\n') % node + elif not int(results[0]['return']): + msg = _('updating %s to public failed!\n') % node + if msg is not None: + pushop.ui.warn(msg) + return handlereply def _pushbundle2(pushop): """push data to the remote using bundle2 @@ -240,7 +412,8 @@ capsblob = bundle2.encodecaps(pushop.repo.bundle2caps) bundler.newpart('b2x:replycaps', data=capsblob) replyhandlers = [] - for partgen in bundle2partsgenerators: + for partgenname in b2partsgenorder: + partgen = b2partsgenmapping[partgenname] ret = partgen(pushop, bundler) if callable(ret): replyhandlers.append(ret) @@ -307,43 +480,8 @@ # change pushop.ret = pushop.remote.addchangegroup(cg, 'push', pushop.repo.url()) -def _pushcomputecommonheads(pushop): - unfi = pushop.repo.unfiltered() - if pushop.ret: - # push succeed, synchronize target of the push - cheads = pushop.outgoing.missingheads - elif pushop.revs is None: - # All out push fails. synchronize all common - cheads = pushop.outgoing.commonheads - else: - # I want cheads = heads(::missingheads and ::commonheads) - # (missingheads is revs with secret changeset filtered out) - # - # This can be expressed as: - # cheads = ( (missingheads and ::commonheads) - # + (commonheads and ::missingheads))" - # ) - # - # while trying to push we already computed the following: - # common = (::commonheads) - # missing = ((commonheads::missingheads) - commonheads) - # - # We can pick: - # * missingheads part of common (::commonheads) - common = set(pushop.outgoing.common) - nm = pushop.repo.changelog.nodemap - cheads = [node for node in pushop.revs if nm[node] in common] - # and - # * commonheads parents on missing - revset = unfi.set('%ln and parents(roots(%ln))', - pushop.outgoing.commonheads, - pushop.outgoing.missing) - cheads.extend(c.node() for c in revset) - pushop.commonheads = cheads - def _pushsyncphase(pushop): """synchronise phase information locally and remotely""" - unfi = pushop.repo.unfiltered() cheads = pushop.commonheads # even when we don't push, exchanging phase data is useful remotephases = pushop.remote.listkeys('phases') @@ -376,12 +514,18 @@ _localphasemove(pushop, cheads, phases.draft) ### Apply local phase on remote - # Get the list of all revs draft on remote by public here. - # XXX Beware that revset break if droots is not strictly - # XXX root we may want to ensure it is but it is costly - outdated = unfi.set('heads((%ln::%ln) and public())', - droots, cheads) + if pushop.ret: + if 'phases' in pushop.stepsdone: + # phases already pushed though bundle2 + return + outdated = pushop.outdatedphases + else: + outdated = pushop.fallbackoutdatedphases + pushop.stepsdone.add('phases') + + # filter heads already turned public by the push + outdated = [c for c in outdated if c.node() not in pheads] b2caps = bundle2.bundle2caps(pushop.remote) if 'b2x:pushkey' in b2caps: # server supports bundle2, let's do a batched push through it @@ -431,7 +575,12 @@ def _localphasemove(pushop, nodes, phase=phases.public): """move <nodes> to <phase> in the local source repo""" if pushop.locallocked: - phases.advanceboundary(pushop.repo, phase, nodes) + tr = pushop.repo.transaction('push-phase-sync') + try: + phases.advanceboundary(pushop.repo, tr, phase, nodes) + tr.close() + finally: + tr.release() else: # repo is not locked, do not change any phases! # Informs the user that phases should have been moved when @@ -444,13 +593,16 @@ def _pushobsolete(pushop): """utility function to push obsolete markers to a remote""" + if 'obsmarkers' in pushop.stepsdone: + return pushop.ui.debug('try to push obsolete markers to remote\n') repo = pushop.repo remote = pushop.remote + pushop.stepsdone.add('obsmarkers') if (obsolete._enabled and repo.obsstore and 'obsolete' in remote.listkeys('namespaces')): rslts = [] - remotedata = repo.listkeys('obsolete') + remotedata = obsolete._pushkeyescape(pushop.outobsmarkers) for key in sorted(remotedata, reverse=True): # reverse sort to ensure we end with dump0 data = remotedata[key] @@ -673,14 +825,29 @@ pheads, _dr = phases.analyzeremotephases(pullop.repo, pullop.pulledsubset, remotephases) - phases.advanceboundary(pullop.repo, phases.public, pheads) - phases.advanceboundary(pullop.repo, phases.draft, - pullop.pulledsubset) + dheads = pullop.pulledsubset else: # Remote is old or publishing all common changesets # should be seen as public - phases.advanceboundary(pullop.repo, phases.public, - pullop.pulledsubset) + pheads = pullop.pulledsubset + dheads = [] + unfi = pullop.repo.unfiltered() + phase = unfi._phasecache.phase + rev = unfi.changelog.nodemap.get + public = phases.public + draft = phases.draft + + # exclude changesets already public locally and update the others + pheads = [pn for pn in pheads if phase(unfi, rev(pn)) > public] + if pheads: + tr = pullop.gettransaction() + phases.advanceboundary(pullop.repo, tr, public, pheads) + + # exclude changesets already draft locally and update the others + dheads = [pn for pn in dheads if phase(unfi, rev(pn)) > draft] + if dheads: + tr = pullop.gettransaction() + phases.advanceboundary(pullop.repo, tr, draft, dheads) def _pullobsolete(pullop): """utility function to pull obsolete markers from a remote @@ -726,9 +893,13 @@ The implementation is at a very early stage and will get massive rework when the API of bundle is refined. """ - # build changegroup bundle here. - cg = changegroup.getbundle(repo, source, heads=heads, - common=common, bundlecaps=bundlecaps) + cg = None + if kwargs.get('cg', True): + # build changegroup bundle here. + cg = changegroup.getbundle(repo, source, heads=heads, + common=common, bundlecaps=bundlecaps) + elif 'HG2X' not in bundlecaps: + raise ValueError(_('request for bundle10 must include changegroup')) if bundlecaps is None or 'HG2X' not in bundlecaps: if kwargs: raise ValueError(_('unsupported getbundle arguments: %s')
--- a/mercurial/filemerge.py Sun Aug 10 23:09:23 2014 -0500 +++ b/mercurial/filemerge.py Mon Aug 11 11:24:05 2014 -0500 @@ -178,24 +178,30 @@ ui = repo.ui + validkeep = ['keep', 'keep-merge3'] + # do we attempt to simplemerge first? try: premerge = _toolbool(ui, tool, "premerge", not binary) except error.ConfigError: premerge = _toolstr(ui, tool, "premerge").lower() - valid = 'keep'.split() - if premerge not in valid: - _valid = ', '.join(["'" + v + "'" for v in valid]) + if premerge not in validkeep: + _valid = ', '.join(["'" + v + "'" for v in validkeep]) raise error.ConfigError(_("%s.premerge not valid " "('%s' is neither boolean nor %s)") % (tool, premerge, _valid)) if premerge: + if premerge == 'keep-merge3': + if not labels: + labels = _defaultconflictlabels + if len(labels) < 3: + labels.append('base') r = simplemerge.simplemerge(ui, a, b, c, quiet=True, label=labels) if not r: ui.debug(" premerge successful\n") return 0 - if premerge != 'keep': + if premerge not in validkeep: util.copyfile(back, a) # restore from backup and try again return 1 # continue merging @@ -206,7 +212,8 @@ """ Uses the internal non-interactive simple merge algorithm for merging files. It will fail if there are any conflicts and leave markers in - the partially merged file.""" + the partially merged file. Markers will have two sections, one for each side + of merge.""" tool, toolpath, binary, symlink = toolconf if symlink: repo.ui.warn(_('warning: internal:merge cannot merge symlinks ' @@ -218,10 +225,25 @@ ui = repo.ui - r = simplemerge.simplemerge(ui, a, b, c, label=labels, no_minimal=True) + r = simplemerge.simplemerge(ui, a, b, c, label=labels) return True, r return False, 0 +@internaltool('merge3', True, + _("merging %s incomplete! " + "(edit conflicts, then use 'hg resolve --mark')\n")) +def _imerge3(repo, mynode, orig, fcd, fco, fca, toolconf, files, labels=None): + """ + Uses the internal non-interactive simple merge algorithm for merging + files. It will fail if there are any conflicts and leave markers in + the partially merged file. Marker will have three sections, one from each + side of the merge and one for the base content.""" + if not labels: + labels = _defaultconflictlabels + if len(labels) < 3: + labels.append('base') + return _imerge(repo, mynode, orig, fcd, fco, fca, toolconf, files, labels) + @internaltool('tagmerge', True, _("automatic tag merging of %s failed! " "(use 'hg resolve --tool internal:merge' or another merge " @@ -312,23 +334,27 @@ _defaultconflictlabels = ['local', 'other'] -def _formatlabels(repo, fcd, fco, labels): +def _formatlabels(repo, fcd, fco, fca, labels): """Formats the given labels using the conflict marker template. Returns a list of formatted labels. """ cd = fcd.changectx() co = fco.changectx() + ca = fca.changectx() ui = repo.ui template = ui.config('ui', 'mergemarkertemplate', _defaultconflictmarker) template = templater.parsestring(template, quoted=False) - tmpl = templater.templater(None, cache={ 'conflictmarker' : template }) + tmpl = templater.templater(None, cache={'conflictmarker': template}) + + pad = max(len(l) for l in labels) - pad = max(len(labels[0]), len(labels[1])) - - return [_formatconflictmarker(repo, cd, tmpl, labels[0], pad), - _formatconflictmarker(repo, co, tmpl, labels[1], pad)] + newlabels = [_formatconflictmarker(repo, cd, tmpl, labels[0], pad), + _formatconflictmarker(repo, co, tmpl, labels[1], pad)] + if len(labels) > 2: + newlabels.append(_formatconflictmarker(repo, ca, tmpl, labels[2], pad)) + return newlabels def filemerge(repo, mynode, orig, fcd, fco, fca, labels=None): """perform a 3-way merge in the working directory @@ -388,16 +414,13 @@ ui.debug("my %s other %s ancestor %s\n" % (fcd, fco, fca)) markerstyle = ui.config('ui', 'mergemarkers', 'basic') - if markerstyle == 'basic': - formattedlabels = _defaultconflictlabels - else: - if not labels: - labels = _defaultconflictlabels - - formattedlabels = _formatlabels(repo, fcd, fco, labels) + if not labels: + labels = _defaultconflictlabels + if markerstyle != 'basic': + labels = _formatlabels(repo, fcd, fco, fca, labels) needcheck, r = func(repo, mynode, orig, fcd, fco, fca, toolconf, - (a, b, c, back), labels=formattedlabels) + (a, b, c, back), labels=labels) if not needcheck: if r: if onfailure:
--- a/mercurial/help/config.txt Sun Aug 10 23:09:23 2014 -0500 +++ b/mercurial/help/config.txt Mon Aug 11 11:24:05 2014 -0500 @@ -388,6 +388,48 @@ - :hg:`tag` - :hg:`transplant` +Configuring items below instead of ``changeset`` allows showing +customized message only for specific actions, or showing different +messages for each actions. + +- ``changeset.backout`` for :hg:`backout` +- ``changeset.commit.amend`` for :hg:`commit --amend` +- ``changeset.commit.normal`` for :hg:`commit` without ``--amend`` +- ``changeset.fetch`` for :hg:`fetch` (impling merge commit) +- ``changeset.gpg.sign`` for :hg:`sign` +- ``changeset.graft`` for :hg:`graft` +- ``changeset.histedit.edit`` for ``edit`` of :hg:`histedit` +- ``changeset.histedit.fold`` for ``fold`` of :hg:`histedit` +- ``changeset.histedit.mess`` for ``mess`` of :hg:`histedit` +- ``changeset.histedit.pick`` for ``pick`` of :hg:`histedit` +- ``changeset.import.bypass`` for :hg:`import --bypass` +- ``changeset.import.normal`` for :hg:`import` without ``--bypass`` +- ``changeset.mq.qnew`` for :hg:`qnew` +- ``changeset.mq.qfold`` for :hg:`qfold` +- ``changeset.mq.qrefresh`` for :hg:`qrefresh` +- ``changeset.rebase.collapse`` for :hg:`rebase --collapse` +- ``changeset.rebase.normal`` for :hg:`rebase` without ``--collapse`` +- ``changeset.shelve.shelve`` for :hg:`shelve` +- ``changeset.tag.add`` for :hg:`tag` without ``--remove`` +- ``changeset.tag.remove`` for :hg:`tag --remove` +- ``changeset.transplant`` for :hg:`transplant` + +These dot-separated lists of names are treated as hierarchical ones. +For example, ``changeset.tag.remove`` customizes the commit message +only for :hg:`tag --remove`, but ``changeset.tag`` customizes the +commit message for :hg:`tag` regardless of ``--remove`` option. + +In this section, items other than ``changeset`` can be referred from +others. For example, the configuration to list committed files up +below can be referred as ``{listupfiles}``:: + + [committemplate] + listupfiles = {file_adds % + "HG: added {file}\n" }{file_mods % + "HG: changed {file}\n" }{file_dels % + "HG: removed {file}\n" }{if(files, "", + "HG: no files changed\n")} + ``decode/encode`` ----------------- @@ -912,8 +954,10 @@ ``premerge`` Attempt to run internal non-interactive 3-way merge tool before - launching external tool. Options are ``true``, ``false``, or ``keep`` - to leave markers in the file if the premerge fails. + launching external tool. Options are ``true``, ``false``, ``keep`` or + ``keep-merge3``. The ``keep`` option will leave markers in the file if the + premerge fails. The ``keep-merge3`` will do the same but include information + about the base of the merge in the marker (see internal:merge3). Default: True ``binary``
--- a/mercurial/i18n.py Sun Aug 10 23:09:23 2014 -0500 +++ b/mercurial/i18n.py Mon Aug 11 11:24:05 2014 -0500 @@ -6,7 +6,7 @@ # GNU General Public License version 2 or any later version. import encoding -import gettext, sys, os +import gettext, sys, os, locale # modelled after templater.templatepath: if getattr(sys, 'frozen', None) is not None: @@ -20,7 +20,25 @@ if os.path.isdir(localedir): break -t = gettext.translation('hg', localedir, fallback=True) +_languages = None +if (os.name == 'nt' + and 'LANGUAGE' not in os.environ + and 'LC_ALL' not in os.environ + and 'LC_MESSAGES' not in os.environ + and 'LANG' not in os.environ): + # Try to detect UI language by "User Interface Language Management" API + # if no locale variables are set. Note that locale.getdefaultlocale() + # uses GetLocaleInfo(), which may be different from UI language. + # (See http://msdn.microsoft.com/en-us/library/dd374098(v=VS.85).aspx ) + try: + import ctypes + langid = ctypes.windll.kernel32.GetUserDefaultUILanguage() + _languages = [locale.windows_locale[langid]] + except (ImportError, AttributeError, KeyError): + # ctypes not found or unknown langid + pass + +t = gettext.translation('hg', localedir, _languages, fallback=True) def gettext(message): """Translate message.
--- a/mercurial/localrepo.py Sun Aug 10 23:09:23 2014 -0500 +++ b/mercurial/localrepo.py Mon Aug 11 11:24:05 2014 -0500 @@ -182,7 +182,9 @@ bundle2caps = {'HG2X': (), 'b2x:listkeys': (), - 'b2x:pushkey': ()} + 'b2x:pushkey': (), + 'b2x:changegroup': (), + } # a list of (ui, featureset) functions. # only functions defined in module of enabled extensions are invoked @@ -1087,8 +1089,6 @@ return l def unlock(): - if hasunfilteredcache(self, '_phasecache'): - self._phasecache.write() for k, ce in self._filecache.items(): if k == 'dirstate' or k not in self.__dict__: continue @@ -1440,7 +1440,7 @@ # be compliant anyway # # if minimal phase was 0 we don't need to retract anything - phases.retractboundary(self, targetphase, [n]) + phases.retractboundary(self, tr, targetphase, [n]) tr.close() branchmap.updatecache(self.filtered('served')) return n
--- a/mercurial/phases.py Sun Aug 10 23:09:23 2014 -0500 +++ b/mercurial/phases.py Mon Aug 11 11:24:05 2014 -0500 @@ -196,19 +196,24 @@ return f = self.opener('phaseroots', 'w', atomictemp=True) try: - for phase, roots in enumerate(self.phaseroots): - for h in roots: - f.write('%i %s\n' % (phase, hex(h))) + self._write(f) finally: f.close() + + def _write(self, fp): + for phase, roots in enumerate(self.phaseroots): + for h in roots: + fp.write('%i %s\n' % (phase, hex(h))) self.dirty = False - def _updateroots(self, phase, newroots): + def _updateroots(self, phase, newroots, tr): self.phaseroots[phase] = newroots self._phaserevs = None self.dirty = True - def advanceboundary(self, repo, targetphase, nodes): + tr.addfilegenerator('phase', ('phaseroots',), self._write) + + def advanceboundary(self, repo, tr, targetphase, nodes): # Be careful to preserve shallow-copied values: do not update # phaseroots values, replace them. @@ -224,15 +229,15 @@ roots = set(ctx.node() for ctx in repo.set( 'roots((%ln::) - (%ln::%ln))', olds, olds, nodes)) if olds != roots: - self._updateroots(phase, roots) + self._updateroots(phase, roots, tr) # some roots may need to be declared for lower phases delroots.extend(olds - roots) # declare deleted root in the target phase if targetphase != 0: - self.retractboundary(repo, targetphase, delroots) + self.retractboundary(repo, tr, targetphase, delroots) repo.invalidatevolatilesets() - def retractboundary(self, repo, targetphase, nodes): + def retractboundary(self, repo, tr, targetphase, nodes): # Be careful to preserve shallow-copied values: do not update # phaseroots values, replace them. @@ -247,7 +252,7 @@ currentroots.update(newroots) ctxs = repo.set('roots(%ln::)', currentroots) currentroots.intersection_update(ctx.node() for ctx in ctxs) - self._updateroots(targetphase, currentroots) + self._updateroots(targetphase, currentroots, tr) repo.invalidatevolatilesets() def filterunknown(self, repo): @@ -278,7 +283,7 @@ # (see branchmap one) self._phaserevs = None -def advanceboundary(repo, targetphase, nodes): +def advanceboundary(repo, tr, targetphase, nodes): """Add nodes to a phase changing other nodes phases if necessary. This function move boundary *forward* this means that all nodes @@ -286,10 +291,10 @@ Simplify boundary to contains phase roots only.""" phcache = repo._phasecache.copy() - phcache.advanceboundary(repo, targetphase, nodes) + phcache.advanceboundary(repo, tr, targetphase, nodes) repo._phasecache.replace(phcache) -def retractboundary(repo, targetphase, nodes): +def retractboundary(repo, tr, targetphase, nodes): """Set nodes back to a phase changing other nodes phases if necessary. @@ -298,7 +303,7 @@ Simplify boundary to contains phase roots only.""" phcache = repo._phasecache.copy() - phcache.retractboundary(repo, targetphase, nodes) + phcache.retractboundary(repo, tr, targetphase, nodes) repo._phasecache.replace(phcache) def listphases(repo): @@ -331,13 +336,16 @@ def pushphase(repo, nhex, oldphasestr, newphasestr): """List phases root for serialization over pushkey""" repo = repo.unfiltered() + tr = None lock = repo.lock() try: currentphase = repo[nhex].phase() newphase = abs(int(newphasestr)) # let's avoid negative index surprise oldphase = abs(int(oldphasestr)) # let's avoid negative index surprise if currentphase == oldphase and newphase < oldphase: - advanceboundary(repo, newphase, [bin(nhex)]) + tr = repo.transaction('pushkey-phase') + advanceboundary(repo, tr, newphase, [bin(nhex)]) + tr.close() return 1 elif currentphase == newphase: # raced, but got correct result @@ -345,6 +353,8 @@ else: return 0 finally: + if tr: + tr.release() lock.release() def analyzeremotephases(repo, subset, roots):
--- a/mercurial/repair.py Sun Aug 10 23:09:23 2014 -0500 +++ b/mercurial/repair.py Mon Aug 11 11:24:05 2014 -0500 @@ -47,7 +47,13 @@ return s -def strip(ui, repo, nodelist, backup="all", topic='backup'): +def strip(ui, repo, nodelist, backup=True, topic='backup'): + + # Simple way to maintain backwards compatibility for this + # argument. + if backup in ['none', 'strip']: + backup = False + repo = repo.unfiltered() repo.destroying() @@ -58,8 +64,6 @@ striplist = [cl.rev(node) for node in nodelist] striprev = min(striplist) - keeppartialbundle = backup == 'strip' - # Some revisions with rev > striprev may not be descendants of striprev. # We have to find these revisions and put them in a bundle, so that # we can restore them after the truncations. @@ -109,7 +113,7 @@ # create a changegroup for all the branches we need to keep backupfile = None vfs = repo.vfs - if backup == "all": + if backup: backupfile = _bundle(repo, stripbases, cl.heads(), node, topic) repo.ui.status(_("saved backup bundle to %s\n") % vfs.join(backupfile)) @@ -118,7 +122,7 @@ if saveheads or savebases: # do not compress partial bundle if we remove it from disk later chgrpfile = _bundle(repo, savebases, saveheads, node, 'temp', - compress=keeppartialbundle) + compress=False) mfst = repo.manifest @@ -156,8 +160,6 @@ if not repo.ui.verbose: repo.ui.popbuffer() f.close() - if not keeppartialbundle: - vfs.unlink(chgrpfile) # remove undo files for undovfs, undofile in repo.undofiles(): @@ -179,5 +181,9 @@ ui.warn(_("strip failed, partial bundle stored in '%s'\n") % vfs.join(chgrpfile)) raise + else: + if saveheads or savebases: + # Remove partial backup only if there were no exceptions + vfs.unlink(chgrpfile) repo.destroyed()
--- a/mercurial/simplemerge.py Sun Aug 10 23:09:23 2014 -0500 +++ b/mercurial/simplemerge.py Mon Aug 11 11:24:05 2014 -0500 @@ -82,8 +82,7 @@ start_marker='<<<<<<<', mid_marker='=======', end_marker='>>>>>>>', - base_marker=None, - reprocess=False): + base_marker=None): """Return merge in cvs-like form. """ self.conflicts = False @@ -93,8 +92,6 @@ newline = '\r\n' elif self.a[0].endswith('\r'): newline = '\r' - if base_marker and reprocess: - raise CantReprocessAndShowBase if name_a: start_marker = start_marker + ' ' + name_a if name_b: @@ -102,8 +99,6 @@ if name_base and base_marker: base_marker = base_marker + ' ' + name_base merge_regions = self.merge_regions() - if reprocess is True: - merge_regions = self.reprocess_merge_regions(merge_regions) for t in merge_regions: what = t[0] if what == 'unchanged': @@ -131,33 +126,6 @@ else: raise ValueError(what) - def merge_annotated(self): - """Return merge with conflicts, showing origin of lines. - - Most useful for debugging merge. - """ - for t in self.merge_regions(): - what = t[0] - if what == 'unchanged': - for i in range(t[1], t[2]): - yield 'u | ' + self.base[i] - elif what == 'a' or what == 'same': - for i in range(t[1], t[2]): - yield what[0] + ' | ' + self.a[i] - elif what == 'b': - for i in range(t[1], t[2]): - yield 'b | ' + self.b[i] - elif what == 'conflict': - yield '<<<<\n' - for i in range(t[3], t[4]): - yield 'A | ' + self.a[i] - yield '----\n' - for i in range(t[5], t[6]): - yield 'B | ' + self.b[i] - yield '>>>>\n' - else: - raise ValueError(what) - def merge_groups(self): """Yield sequence of line groups. Each one is a tuple: @@ -278,42 +246,6 @@ ia = aend ib = bend - def reprocess_merge_regions(self, merge_regions): - """Where there are conflict regions, remove the agreed lines. - - Lines where both A and B have made the same changes are - eliminated. - """ - for region in merge_regions: - if region[0] != "conflict": - yield region - continue - type, iz, zmatch, ia, amatch, ib, bmatch = region - a_region = self.a[ia:amatch] - b_region = self.b[ib:bmatch] - matches = mdiff.get_matching_blocks(''.join(a_region), - ''.join(b_region)) - next_a = ia - next_b = ib - for region_ia, region_ib, region_len in matches[:-1]: - region_ia += ia - region_ib += ib - reg = self.mismatch_region(next_a, region_ia, next_b, - region_ib) - if reg is not None: - yield reg - yield 'same', region_ia, region_len + region_ia - next_a = region_ia + region_len - next_b = region_ib + region_len - reg = self.mismatch_region(next_a, amatch, next_b, bmatch) - if reg is not None: - yield reg - - def mismatch_region(next_a, region_ia, next_b, region_ib): - if next_a < region_ia or next_b < region_ib: - return 'conflict', None, None, next_a, region_ia, next_b, region_ib - mismatch_region = staticmethod(mismatch_region) - def find_sync_regions(self): """Return a list of sync regions, where both descendants match the base. @@ -415,13 +347,16 @@ name_a = local name_b = other + name_base = None labels = opts.get('label', []) if len(labels) > 0: name_a = labels[0] if len(labels) > 1: name_b = labels[1] if len(labels) > 2: - raise util.Abort(_("can only specify two labels.")) + name_base = labels[2] + if len(labels) > 3: + raise util.Abort(_("can only specify three labels.")) try: localtext = readfile(local) @@ -437,11 +372,12 @@ else: out = sys.stdout - reprocess = not opts.get('no_minimal') - m3 = Merge3Text(basetext, localtext, othertext) - for line in m3.merge_lines(name_a=name_a, name_b=name_b, - reprocess=reprocess): + extrakwargs = {} + if name_base is not None: + extrakwargs['base_marker'] = '|||||||' + extrakwargs['name_base'] = name_base + for line in m3.merge_lines(name_a=name_a, name_b=name_b, **extrakwargs): out.write(line) if not opts.get('print'):
--- a/mercurial/transaction.py Sun Aug 10 23:09:23 2014 -0500 +++ b/mercurial/transaction.py Mon Aug 11 11:24:05 2014 -0500 @@ -96,6 +96,9 @@ opener.chmod(self.journal, createmode & 0666) opener.chmod(self.backupjournal, createmode & 0666) + # hold file generations to be performed on commit + self._filegenerators = {} + def __del__(self): if self.journal: self._abort() @@ -154,7 +157,7 @@ if file in self.map or file in self.backupmap: return - backupfile = "journal.%s" % file + backupfile = "%s.backup.%s" % (self.journal, file) if self.opener.exists(file): filepath = self.opener.join(file) backuppath = self.opener.join(backupfile) @@ -173,6 +176,28 @@ self.backupsfile.flush() @active + def addfilegenerator(self, genid, filenames, genfunc, order=0): + """add a function to generates some files at transaction commit + + The `genfunc` argument is a function capable of generating proper + content of each entry in the `filename` tuple. + + At transaction close time, `genfunc` will be called with one file + object argument per entries in `filenames`. + + The transaction itself is responsible for the backup, creation and + final write of such file. + + The `genid` argument is used to ensure the same set of file is only + generated once. Call to `addfilegenerator` for a `genid` already + present will overwrite the old entry. + + The `order` argument may be used to control the order in which multiple + generator will be executed. + """ + self._filegenerators[genid] = (order, filenames, genfunc) + + @active def find(self, file): if file in self.map: return self.entries[self.map[file]] @@ -213,6 +238,18 @@ @active def close(self): '''commit the transaction''' + # write files registered for generation + for order, filenames, genfunc in sorted(self._filegenerators.values()): + files = [] + try: + for name in filenames: + self.addbackup(name) + files.append(self.opener(name, 'w', atomictemp=True)) + genfunc(*files) + finally: + for f in files: + f.close() + if self.count == 1 and self.onclose is not None: self.onclose()
--- a/mercurial/wireproto.py Sun Aug 10 23:09:23 2014 -0500 +++ b/mercurial/wireproto.py Mon Aug 11 11:24:05 2014 -0500 @@ -203,7 +203,8 @@ gboptsmap = {'heads': 'nodes', 'common': 'nodes', 'bundlecaps': 'csv', - 'listkeys': 'csv'} + 'listkeys': 'csv', + 'cg': 'boolean'} # client side @@ -349,6 +350,8 @@ value = encodelist(value) elif keytype == 'csv': value = ','.join(value) + elif keytype == 'boolean': + value = bool(value) elif keytype != 'plain': raise KeyError('unknown getbundle option type %s' % keytype) @@ -652,6 +655,8 @@ opts[k] = decodelist(v) elif keytype == 'csv': opts[k] = set(v.split(',')) + elif keytype == 'boolean': + opts[k] = '%i' % bool(v) elif keytype != 'plain': raise KeyError('unknown getbundle option type %s' % keytype)
--- a/tests/hghave.py Sun Aug 10 23:09:23 2014 -0500 +++ b/tests/hghave.py Mon Aug 11 11:24:05 2014 -0500 @@ -5,6 +5,17 @@ tempprefix = 'hg-hghave-' +checks = { + "true": (lambda: True, "yak shaving"), + "false": (lambda: False, "nail clipper"), +} + +def check(name, desc): + def decorator(func): + checks[name] = (func, desc) + return func + return decorator + def matchoutput(cmd, regexp, ignorestatus=False): """Return True if cmd executes successfully and its output is matched by the supplied regular expression. @@ -19,9 +30,11 @@ ret = 1 return (ignorestatus or ret is None) and r.search(s) +@check("baz", "GNU Arch baz client") def has_baz(): return matchoutput('baz --version 2>&1', r'baz Bazaar version') +@check("bzr", "Canonical's Bazaar client") def has_bzr(): try: import bzrlib @@ -29,6 +42,7 @@ except ImportError: return False +@check("bzr114", "Canonical's Bazaar client >= 1.14") def has_bzr114(): try: import bzrlib @@ -37,21 +51,26 @@ except ImportError: return False +@check("cvs", "cvs client/server") def has_cvs(): re = r'Concurrent Versions System.*?server' return matchoutput('cvs --version 2>&1', re) and not has_msys() +@check("cvs112", "cvs client/server >= 1.12") def has_cvs112(): re = r'Concurrent Versions System \(CVS\) 1.12.*?server' return matchoutput('cvs --version 2>&1', re) and not has_msys() +@check("darcs", "darcs client") def has_darcs(): return matchoutput('darcs --version', r'2\.[2-9]', True) +@check("mtn", "monotone client (>= 1.0)") def has_mtn(): return matchoutput('mtn --version', r'monotone', True) and not matchoutput( 'mtn --version', r'monotone 0\.', True) +@check("eol-in-paths", "end-of-lines in paths") def has_eol_in_paths(): try: fd, path = tempfile.mkstemp(dir='.', prefix=tempprefix, suffix='\n\r') @@ -61,6 +80,7 @@ except (IOError, OSError): return False +@check("execbit", "executable bit") def has_executablebit(): try: EXECFLAGS = stat.S_IXUSR | stat.S_IXGRP | stat.S_IXOTH @@ -78,6 +98,7 @@ return False return not (new_file_has_exec or exec_flags_cannot_flip) +@check("icasefs", "case insensitive file system") def has_icasefs(): # Stolen from mercurial.util fd, path = tempfile.mkstemp(dir='.', prefix=tempprefix) @@ -96,6 +117,7 @@ finally: os.remove(path) +@check("fifo", "named pipes") def has_fifo(): if getattr(os, "mkfifo", None) is None: return False @@ -107,9 +129,11 @@ except OSError: return False +@check("killdaemons", 'killdaemons.py support') def has_killdaemons(): return True +@check("cacheable", "cacheable filesystem") def has_cacheable_fs(): from mercurial import util @@ -120,6 +144,7 @@ finally: os.remove(path) +@check("lsprof", "python lsprof module") def has_lsprof(): try: import _lsprof @@ -127,12 +152,15 @@ except ImportError: return False +@check("gettext", "GNU Gettext (msgfmt)") def has_gettext(): return matchoutput('msgfmt --version', 'GNU gettext-tools') +@check("git", "git command line client") def has_git(): return matchoutput('git --version 2>&1', r'^git version') +@check("docutils", "Docutils text processing library") def has_docutils(): try: from docutils.core import publish_cmdline @@ -146,16 +174,20 @@ return (0, 0) return (int(m.group(1)), int(m.group(2))) +@check("svn15", "subversion client and admin tools >= 1.5") def has_svn15(): return getsvnversion() >= (1, 5) +@check("svn13", "subversion client and admin tools >= 1.3") def has_svn13(): return getsvnversion() >= (1, 3) +@check("svn", "subversion client and admin tools") def has_svn(): return matchoutput('svn --version 2>&1', r'^svn, version') and \ matchoutput('svnadmin --version 2>&1', r'^svnadmin, version') +@check("svn-bindings", "subversion python bindings") def has_svn_bindings(): try: import svn.core @@ -166,10 +198,12 @@ except ImportError: return False +@check("p4", "Perforce server and client") def has_p4(): return (matchoutput('p4 -V', r'Rev\. P4/') and matchoutput('p4d -V', r'Rev\. P4D/')) +@check("symlink", "symbolic links") def has_symlink(): if getattr(os, "symlink", None) is None: return False @@ -181,6 +215,7 @@ except (OSError, AttributeError): return False +@check("hardlink", "hardlinks") def has_hardlink(): from mercurial import util fh, fn = tempfile.mkstemp(dir='.', prefix=tempprefix) @@ -196,12 +231,15 @@ finally: os.unlink(fn) +@check("tla", "GNU Arch tla client") def has_tla(): return matchoutput('tla --version 2>&1', r'The GNU Arch Revision') +@check("gpg", "gpg client") def has_gpg(): return matchoutput('gpg --version 2>&1', r'GnuPG') +@check("unix-permissions", "unix-style permissions") def has_unix_permissions(): d = tempfile.mkdtemp(dir='.', prefix=tempprefix) try: @@ -218,14 +256,17 @@ finally: os.rmdir(d) +@check("root", "root permissions") def has_root(): return getattr(os, 'geteuid', None) and os.geteuid() == 0 +@check("pyflakes", "Pyflakes python linter") def has_pyflakes(): return matchoutput("sh -c \"echo 'import re' 2>&1 | pyflakes\"", r"<stdin>:1: 're' imported but unused", True) +@check("pygments", "Pygments source highlighting library") def has_pygments(): try: import pygments @@ -233,14 +274,17 @@ except ImportError: return False +@check("python243", "python >= 2.4.3") def has_python243(): return sys.version_info >= (2, 4, 3) +@check("outer-repo", "outer repo") def has_outer_repo(): # failing for other reasons than 'no repo' imply that there is a repo return not matchoutput('hg root 2>&1', r'abort: no repository found', True) +@check("ssl", "python >= 2.6 ssl module and python OpenSSL") def has_ssl(): try: import ssl @@ -250,19 +294,24 @@ except ImportError: return False +@check("windows", "Windows") def has_windows(): return os.name == 'nt' +@check("system-sh", "system() uses sh") def has_system_sh(): return os.name != 'nt' +@check("serve", "platform and python can manage 'hg serve -d'") def has_serve(): return os.name != 'nt' # gross approximation +@check("test-repo", "running tests from repository") def has_test_repo(): t = os.environ["TESTDIR"] return os.path.isdir(os.path.join(t, "..", ".hg")) +@check("tic", "terminfo compiler and curses module") def has_tic(): try: import curses @@ -271,63 +320,20 @@ except ImportError: return False +@check("msys", "Windows with MSYS") def has_msys(): return os.getenv('MSYSTEM') +@check("aix", "AIX") def has_aix(): return sys.platform.startswith("aix") +@check("absimport", "absolute_import in __future__") def has_absimport(): import __future__ from mercurial import util return util.safehasattr(__future__, "absolute_import") +@check("py3k", "running with Python 3.x") def has_py3k(): return 3 == sys.version_info[0] - -checks = { - "true": (lambda: True, "yak shaving"), - "false": (lambda: False, "nail clipper"), - "baz": (has_baz, "GNU Arch baz client"), - "bzr": (has_bzr, "Canonical's Bazaar client"), - "bzr114": (has_bzr114, "Canonical's Bazaar client >= 1.14"), - "cacheable": (has_cacheable_fs, "cacheable filesystem"), - "cvs": (has_cvs, "cvs client/server"), - "cvs112": (has_cvs112, "cvs client/server >= 1.12"), - "darcs": (has_darcs, "darcs client"), - "docutils": (has_docutils, "Docutils text processing library"), - "eol-in-paths": (has_eol_in_paths, "end-of-lines in paths"), - "execbit": (has_executablebit, "executable bit"), - "fifo": (has_fifo, "named pipes"), - "gettext": (has_gettext, "GNU Gettext (msgfmt)"), - "git": (has_git, "git command line client"), - "gpg": (has_gpg, "gpg client"), - "hardlink": (has_hardlink, "hardlinks"), - "icasefs": (has_icasefs, "case insensitive file system"), - "killdaemons": (has_killdaemons, 'killdaemons.py support'), - "lsprof": (has_lsprof, "python lsprof module"), - "mtn": (has_mtn, "monotone client (>= 1.0)"), - "outer-repo": (has_outer_repo, "outer repo"), - "p4": (has_p4, "Perforce server and client"), - "pyflakes": (has_pyflakes, "Pyflakes python linter"), - "pygments": (has_pygments, "Pygments source highlighting library"), - "python243": (has_python243, "python >= 2.4.3"), - "root": (has_root, "root permissions"), - "serve": (has_serve, "platform and python can manage 'hg serve -d'"), - "ssl": (has_ssl, "python >= 2.6 ssl module and python OpenSSL"), - "svn": (has_svn, "subversion client and admin tools"), - "svn13": (has_svn13, "subversion client and admin tools >= 1.3"), - "svn15": (has_svn15, "subversion client and admin tools >= 1.5"), - "svn-bindings": (has_svn_bindings, "subversion python bindings"), - "symlink": (has_symlink, "symbolic links"), - "system-sh": (has_system_sh, "system() uses sh"), - "test-repo": (has_test_repo, "running tests from repository"), - "tic": (has_tic, "terminfo compiler and curses module"), - "tla": (has_tla, "GNU Arch tla client"), - "unix-permissions": (has_unix_permissions, "unix-style permissions"), - "windows": (has_windows, "Windows"), - "msys": (has_msys, "Windows with MSYS"), - "aix": (has_aix, "AIX"), - "absimport": (has_absimport, "absolute_import in __future__"), - "py3k": (has_py3k, "running with Python 3.x"), -}
--- a/tests/run-tests.py Sun Aug 10 23:09:23 2014 -0500 +++ b/tests/run-tests.py Mon Aug 11 11:24:05 2014 -0500 @@ -57,6 +57,7 @@ import threading import killdaemons as killmod import Queue as queue +from xml.dom import minidom import unittest processlock = threading.Lock() @@ -190,6 +191,8 @@ " (implies --keep-tmpdir)") parser.add_option("-v", "--verbose", action="store_true", help="output verbose messages") + parser.add_option("--xunit", type="string", + help="record xunit results at specified path") parser.add_option("--view", type="string", help="external diff viewer") parser.add_option("--with-hg", type="string", @@ -304,6 +307,20 @@ return log(*msg) +# Bytes that break XML even in a CDATA block: control characters 0-31 +# sans \t, \n and \r +CDATA_EVIL = re.compile(r"[\000-\010\013\014\016-\037]") + +def cdatasafe(data): + """Make a string safe to include in a CDATA block. + + Certain control characters are illegal in a CDATA block, and + there's no way to include a ]]> in a CDATA either. This function + replaces illegal bytes with ? and adds a space between the ]] so + that it won't break the CDATA block. + """ + return CDATA_EVIL.sub('?', data).replace(']]>', '] ]>') + def log(*msg): """Log something to stdout. @@ -460,8 +477,15 @@ raise except SkipTest, e: result.addSkip(self, str(e)) + # The base class will have already counted this as a + # test we "ran", but we want to exclude skipped tests + # from those we count towards those run. + result.testsRun -= 1 except IgnoreTest, e: result.addIgnore(self, str(e)) + # As with skips, ignores also should be excluded from + # the number of tests executed. + result.testsRun -= 1 except WarnTest, e: result.addWarn(self, str(e)) except self.failureException, e: @@ -786,7 +810,15 @@ for n, l in enumerate(lines): if not l.endswith('\n'): l += '\n' - if l.startswith('#if'): + if l.startswith('#require'): + lsplit = l.split() + if len(lsplit) < 2 or lsplit[0] != '#require': + after.setdefault(pos, []).append(' !!! invalid #require\n') + if not self._hghave(lsplit[1:]): + script = ["exit 80\n"] + break + after.setdefault(pos, []).append(l) + elif l.startswith('#if'): lsplit = l.split() if len(lsplit) < 2 or lsplit[0] != '#if': after.setdefault(pos, []).append(' !!! invalid #if\n') @@ -1077,6 +1109,10 @@ self.times = [] self._started = {} + self._stopped = {} + # Data stored for the benefit of generating xunit reports. + self.successes = [] + self.faildata = {} def addFailure(self, test, reason): self.failures.append((test, reason)) @@ -1084,21 +1120,25 @@ if self._options.first: self.stop() else: + iolock.acquire() if not self._options.nodiff: self.stream.write('\nERROR: %s output changed\n' % test) self.stream.write('!') + iolock.release() - def addError(self, *args, **kwargs): - super(TestResult, self).addError(*args, **kwargs) + def addSuccess(self, test): + super(TestResult, self).addSuccess(test) + self.successes.append(test) + def addError(self, test, err): + super(TestResult, self).addError(test, err) if self._options.first: self.stop() # Polyfill. def addSkip(self, test, reason): self.skipped.append((test, reason)) - if self.showAll: self.stream.writeln('skipped %s' % reason) else: @@ -1107,12 +1147,13 @@ def addIgnore(self, test, reason): self.ignored.append((test, reason)) - if self.showAll: self.stream.writeln('ignored %s' % reason) else: if reason != 'not retesting': self.stream.write('i') + else: + self.testsRun += 1 self.stream.flush() def addWarn(self, test, reason): @@ -1131,6 +1172,8 @@ """Record a mismatch in test output for a particular test.""" accepted = False + failed = False + lines = [] iolock.acquire() if self._options.nodiff: @@ -1159,7 +1202,8 @@ else: rename(test.errpath, '%s.out' % test.path) accepted = True - + if not accepted and not failed: + self.faildata[test.name] = ''.join(lines) iolock.release() return accepted @@ -1167,17 +1211,28 @@ def startTest(self, test): super(TestResult, self).startTest(test) - self._started[test.name] = time.time() + # os.times module computes the user time and system time spent by + # child's processes along with real elapsed time taken by a process. + # This module has one limitation. It can only work for Linux user + # and not for Windows. + self._started[test.name] = os.times() def stopTest(self, test, interrupted=False): super(TestResult, self).stopTest(test) - self.times.append((test.name, time.time() - self._started[test.name])) + self._stopped[test.name] = os.times() + + starttime = self._started[test.name] + endtime = self._stopped[test.name] + self.times.append((test.name, endtime[2] - starttime[2], + endtime[3] - starttime[3], endtime[4] - starttime[4])) + del self._started[test.name] + del self._stopped[test.name] if interrupted: self.stream.writeln('INTERRUPTED: %s (after %d seconds)' % ( - test.name, self.times[-1][1])) + test.name, self.times[-1][3])) class TestSuite(unittest.TestSuite): """Custom unitest TestSuite that knows how to execute Mercurial tests.""" @@ -1323,20 +1378,39 @@ for test, msg in result.errors: self.stream.writeln('Errored %s: %s' % (test.name, msg)) + if self._runner.options.xunit: + xuf = open(self._runner.options.xunit, 'wb') + try: + timesd = dict( + (test, real) for test, cuser, csys, real in result.times) + doc = minidom.Document() + s = doc.createElement('testsuite') + s.setAttribute('name', 'run-tests') + s.setAttribute('tests', str(result.testsRun)) + s.setAttribute('errors', "0") # TODO + s.setAttribute('failures', str(failed)) + s.setAttribute('skipped', str(skipped + ignored)) + doc.appendChild(s) + for tc in result.successes: + t = doc.createElement('testcase') + t.setAttribute('name', tc.name) + t.setAttribute('time', '%.3f' % timesd[tc.name]) + s.appendChild(t) + for tc, err in sorted(result.faildata.iteritems()): + t = doc.createElement('testcase') + t.setAttribute('name', tc) + t.setAttribute('time', '%.3f' % timesd[tc]) + cd = doc.createCDATASection(cdatasafe(err)) + t.appendChild(cd) + s.appendChild(t) + xuf.write(doc.toprettyxml(indent=' ', encoding='utf-8')) + finally: + xuf.close() + self._runner._checkhglib('Tested') - # When '--retest' is enabled, only failure tests run. At this point - # "result.testsRun" holds the count of failure test that has run. But - # as while printing output, we have subtracted the skipped and ignored - # count from "result.testsRun". Therefore, to make the count remain - # the same, we need to add skipped and ignored count in here. - if self._runner.options.retest: - result.testsRun = result.testsRun + skipped + ignored - - # This differs from unittest's default output in that we don't count - # skipped and ignored tests as part of the total test count. self.stream.writeln('# Ran %d tests, %d skipped, %d warned, %d failed.' - % (result.testsRun - skipped - ignored, + % (result.testsRun, skipped + ignored, warned, failed)) if failed: self.stream.writeln('python hash seed: %s' % @@ -1348,11 +1422,12 @@ def printtimes(self, times): self.stream.writeln('# Producing time report') - times.sort(key=lambda t: (t[1], t[0]), reverse=True) - cols = '%7.3f %s' - self.stream.writeln('%-7s %s' % ('Time', 'Test')) - for test, timetaken in times: - self.stream.writeln(cols % (timetaken, test)) + times.sort(key=lambda t: (t[3])) + cols = '%7.3f %7.3f %7.3f %s' + self.stream.writeln('%-7s %-7s %-7s %s' % ('cuser', 'csys', 'real', + 'Test')) + for test, cuser, csys, real in times: + self.stream.writeln(cols % (cuser, csys, real, test)) class TestRunner(object): """Holds context for executing tests.
--- a/tests/test-acl.t Sun Aug 10 23:09:23 2014 -0500 +++ b/tests/test-acl.t Mon Aug 11 11:24:05 2014 -0500 @@ -82,6 +82,7 @@ query 1; heads searching for changes all remote heads known locally + listing keys for "phases" listing keys for "bookmarks" 3 changesets found list of changesets: @@ -140,6 +141,7 @@ query 1; heads searching for changes all remote heads known locally + listing keys for "phases" invalid branchheads cache (served): tip differs listing keys for "bookmarks" 3 changesets found @@ -202,6 +204,7 @@ query 1; heads searching for changes all remote heads known locally + listing keys for "phases" invalid branchheads cache (served): tip differs listing keys for "bookmarks" 3 changesets found @@ -274,6 +277,7 @@ query 1; heads searching for changes all remote heads known locally + listing keys for "phases" invalid branchheads cache (served): tip differs listing keys for "bookmarks" 3 changesets found @@ -341,6 +345,7 @@ query 1; heads searching for changes all remote heads known locally + listing keys for "phases" invalid branchheads cache (served): tip differs listing keys for "bookmarks" 3 changesets found @@ -413,6 +418,7 @@ query 1; heads searching for changes all remote heads known locally + listing keys for "phases" invalid branchheads cache (served): tip differs listing keys for "bookmarks" 3 changesets found @@ -482,6 +488,7 @@ query 1; heads searching for changes all remote heads known locally + listing keys for "phases" invalid branchheads cache (served): tip differs listing keys for "bookmarks" 3 changesets found @@ -556,6 +563,7 @@ query 1; heads searching for changes all remote heads known locally + listing keys for "phases" invalid branchheads cache (served): tip differs listing keys for "bookmarks" 3 changesets found @@ -627,6 +635,7 @@ query 1; heads searching for changes all remote heads known locally + listing keys for "phases" invalid branchheads cache (served): tip differs listing keys for "bookmarks" 3 changesets found @@ -700,6 +709,7 @@ query 1; heads searching for changes all remote heads known locally + listing keys for "phases" invalid branchheads cache (served): tip differs listing keys for "bookmarks" 3 changesets found @@ -779,6 +789,7 @@ query 1; heads searching for changes all remote heads known locally + listing keys for "phases" invalid branchheads cache (served): tip differs listing keys for "bookmarks" 3 changesets found @@ -859,6 +870,7 @@ query 1; heads searching for changes all remote heads known locally + listing keys for "phases" invalid branchheads cache (served): tip differs listing keys for "bookmarks" 3 changesets found @@ -934,6 +946,7 @@ query 1; heads searching for changes all remote heads known locally + listing keys for "phases" invalid branchheads cache (served): tip differs listing keys for "bookmarks" 3 changesets found @@ -1020,6 +1033,7 @@ query 1; heads searching for changes all remote heads known locally + listing keys for "phases" invalid branchheads cache (served): tip differs listing keys for "bookmarks" 3 changesets found @@ -1100,6 +1114,7 @@ query 1; heads searching for changes all remote heads known locally + listing keys for "phases" invalid branchheads cache (served): tip differs listing keys for "bookmarks" 3 changesets found @@ -1176,6 +1191,7 @@ query 1; heads searching for changes all remote heads known locally + listing keys for "phases" invalid branchheads cache (served): tip differs listing keys for "bookmarks" 3 changesets found @@ -1252,6 +1268,7 @@ query 1; heads searching for changes all remote heads known locally + listing keys for "phases" invalid branchheads cache (served): tip differs listing keys for "bookmarks" 3 changesets found @@ -1329,6 +1346,7 @@ query 1; heads searching for changes all remote heads known locally + listing keys for "phases" invalid branchheads cache (served): tip differs listing keys for "bookmarks" 3 changesets found @@ -1444,6 +1462,7 @@ query 1; heads searching for changes all remote heads known locally + listing keys for "phases" listing keys for "bookmarks" 4 changesets found list of changesets: @@ -1527,6 +1546,7 @@ query 1; heads searching for changes all remote heads known locally + listing keys for "phases" listing keys for "bookmarks" 4 changesets found list of changesets: @@ -1606,6 +1626,7 @@ query 1; heads searching for changes all remote heads known locally + listing keys for "phases" listing keys for "bookmarks" 4 changesets found list of changesets: @@ -1681,6 +1702,7 @@ query 1; heads searching for changes all remote heads known locally + listing keys for "phases" listing keys for "bookmarks" 4 changesets found list of changesets: @@ -1750,6 +1772,7 @@ query 1; heads searching for changes all remote heads known locally + listing keys for "phases" listing keys for "bookmarks" 4 changesets found list of changesets: @@ -1838,6 +1861,7 @@ query 1; heads searching for changes all remote heads known locally + listing keys for "phases" listing keys for "bookmarks" 4 changesets found list of changesets: @@ -1925,6 +1949,7 @@ query 1; heads searching for changes all remote heads known locally + listing keys for "phases" listing keys for "bookmarks" 4 changesets found list of changesets: @@ -1999,6 +2024,7 @@ query 1; heads searching for changes all remote heads known locally + listing keys for "phases" listing keys for "bookmarks" 4 changesets found list of changesets: @@ -2080,6 +2106,7 @@ query 1; heads searching for changes all remote heads known locally + listing keys for "phases" listing keys for "bookmarks" 4 changesets found list of changesets:
--- a/tests/test-archive-symlinks.t Sun Aug 10 23:09:23 2014 -0500 +++ b/tests/test-archive-symlinks.t Mon Aug 11 11:24:05 2014 -0500 @@ -1,4 +1,4 @@ - $ "$TESTDIR/hghave" symlink || exit 80 +#require symlink $ origdir=`pwd`
--- a/tests/test-archive.t Sun Aug 10 23:09:23 2014 -0500 +++ b/tests/test-archive.t Mon Aug 11 11:24:05 2014 -0500 @@ -1,4 +1,4 @@ - $ "$TESTDIR/hghave" serve || exit 80 +#require serve $ hg init test $ cd test
--- a/tests/test-bad-pull.t Sun Aug 10 23:09:23 2014 -0500 +++ b/tests/test-bad-pull.t Mon Aug 11 11:24:05 2014 -0500 @@ -1,4 +1,4 @@ - $ "$TESTDIR/hghave" serve || exit 80 +#require serve #if windows $ hg clone http://localhost:$HGPORT/ copy
--- a/tests/test-bookmarks-pushpull.t Sun Aug 10 23:09:23 2014 -0500 +++ b/tests/test-bookmarks-pushpull.t Mon Aug 11 11:24:05 2014 -0500 @@ -1,4 +1,4 @@ - $ "$TESTDIR/hghave" serve || exit 80 +#require serve $ cat << EOF >> $HGRCPATH > [ui]
--- a/tests/test-bundle2.t Sun Aug 10 23:09:23 2014 -0500 +++ b/tests/test-bundle2.t Mon Aug 11 11:24:05 2014 -0500 @@ -964,7 +964,8 @@ > raise util.Abort('Abandon ship!', hint="don't panic") > > def uisetup(ui): - > exchange.bundle2partsgenerators.insert(0, _pushbundle2failpart) + > exchange.b2partsgenmapping['failpart'] = _pushbundle2failpart + > exchange.b2partsgenorder.insert(0, 'failpart') > > EOF
--- a/tests/test-casecollision-merge.t Sun Aug 10 23:09:23 2014 -0500 +++ b/tests/test-casecollision-merge.t Mon Aug 11 11:24:05 2014 -0500 @@ -1,6 +1,4 @@ -run only on case-insensitive filesystems - - $ "$TESTDIR/hghave" icasefs || exit 80 +#require icasefs ################################ test for branch merging
--- a/tests/test-casecollision.t Sun Aug 10 23:09:23 2014 -0500 +++ b/tests/test-casecollision.t Mon Aug 11 11:24:05 2014 -0500 @@ -1,6 +1,4 @@ -run only on case-sensitive filesystems - - $ "$TESTDIR/hghave" no-icasefs || exit 80 +#require no-icasefs test file addition with colliding case
--- a/tests/test-casefolding.t Sun Aug 10 23:09:23 2014 -0500 +++ b/tests/test-casefolding.t Mon Aug 11 11:24:05 2014 -0500 @@ -1,4 +1,4 @@ - $ "$TESTDIR/hghave" icasefs || exit 80 +#require icasefs $ hg debugfs | grep 'case-sensitive:' case-sensitive: no
--- a/tests/test-changelog-exec.t Sun Aug 10 23:09:23 2014 -0500 +++ b/tests/test-changelog-exec.t Mon Aug 11 11:24:05 2014 -0500 @@ -1,9 +1,9 @@ +#require execbit + b51a8138292a introduced a regression where we would mention in the changelog executable files added by the second parent of a merge. Test that that doesn't happen anymore - $ "$TESTDIR/hghave" execbit || exit 80 - $ hg init repo $ cd repo $ echo foo > foo
--- a/tests/test-check-code-hg.t Sun Aug 10 23:09:23 2014 -0500 +++ b/tests/test-check-code-hg.t Mon Aug 11 11:24:05 2014 -0500 @@ -1,4 +1,4 @@ -#if test-repo +#require test-repo $ check_code="$TESTDIR"/../contrib/check-code.py $ cd "$TESTDIR"/.. @@ -13,5 +13,3 @@ Skipping mercurial/httpclient/__init__.py it has no-che?k-code (glob) Skipping mercurial/httpclient/_readers.py it has no-che?k-code (glob) Skipping mercurial/httpclient/socketutil.py it has no-che?k-code (glob) - -#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tests/test-check-commit-hg.t Mon Aug 11 11:24:05 2014 -0500 @@ -0,0 +1,26 @@ +#require test-repo + +Enable obsolescence to avoid the warning issue when obsmarker are found + + $ cat > obs.py << EOF + > import mercurial.obsolete + > mercurial.obsolete._enabled = True + > EOF + $ echo '[extensions]' >> $HGRCPATH + $ echo "obs=${TESTTMP}/obs.py" >> $HGRCPATH + +Go back in the hg repo + + $ cd $TESTDIR/.. + + $ for node in `hg log --rev 'draft() and ::.' --template '{node|short}\n'`; do + > hg export $node | contrib/check-commit > ${TESTTMP}/check-commit.out + > if [ $? -ne 0 ]; then + > echo "Revision $node does not comply to commit message rules" + > echo '------------------------------------------------------' + > cat ${TESTTMP}/check-commit.out + > echo + > fi + > done + +
--- a/tests/test-check-pyflakes.t Sun Aug 10 23:09:23 2014 -0500 +++ b/tests/test-check-pyflakes.t Mon Aug 11 11:24:05 2014 -0500 @@ -1,4 +1,4 @@ -#if test-repo pyflakes +#require test-repo pyflakes $ cd "`dirname "$TESTDIR"`" @@ -19,4 +19,4 @@ contrib/win32/hgwebdir_wsgi.py:93: 'from isapi.install import *' used; unable to detect undefined names (glob) tests/filterpyflakes.py:58: undefined name 'undefinedname' -#endif +
--- a/tests/test-clone-cgi.t Sun Aug 10 23:09:23 2014 -0500 +++ b/tests/test-clone-cgi.t Mon Aug 11 11:24:05 2014 -0500 @@ -1,4 +1,4 @@ - $ "$TESTDIR/hghave" no-msys || exit 80 # MSYS will translate web paths as if they were file paths +#require no-msys # MSYS will translate web paths as if they were file paths This is a test of the wire protocol over CGI-based hgweb. initialize repository
--- a/tests/test-commit.t Sun Aug 10 23:09:23 2014 -0500 +++ b/tests/test-commit.t Mon Aug 11 11:24:05 2014 -0500 @@ -359,6 +359,20 @@ $ cat >> .hg/hgrc <<EOF > [committemplate] + > changeset.commit.normal = HG: this is "commit.normal" template + > HG: {extramsg} + > {if(currentbookmark, + > "HG: bookmark '{currentbookmark}' is activated\n", + > "HG: no bookmark is activated\n")}{subrepos % + > "HG: subrepo '{subrepo}' is changed\n"} + > + > changeset.commit = HG: this is "commit" template + > HG: {extramsg} + > {if(currentbookmark, + > "HG: bookmark '{currentbookmark}' is activated\n", + > "HG: no bookmark is activated\n")}{subrepos % + > "HG: subrepo '{subrepo}' is changed\n"} + > > changeset = HG: this is customized commit template > HG: {extramsg} > {if(currentbookmark, @@ -373,7 +387,7 @@ $ echo 'sub2 = sub2' >> .hgsub $ HGEDITOR=cat hg commit -S -q - HG: this is customized commit template + HG: this is "commit.normal" template HG: Leave message empty to abort commit. HG: bookmark 'currentbookmark' is activated HG: subrepo 'sub' is changed @@ -381,9 +395,28 @@ abort: empty commit message [255] + $ cat >> .hg/hgrc <<EOF + > [committemplate] + > changeset.commit.normal = + > # now, "changeset.commit" should be chosen for "hg commit" + > EOF + $ hg bookmark --inactive currentbookmark $ hg forget .hgsub $ HGEDITOR=cat hg commit -q + HG: this is "commit" template + HG: Leave message empty to abort commit. + HG: no bookmark is activated + abort: empty commit message + [255] + + $ cat >> .hg/hgrc <<EOF + > [committemplate] + > changeset.commit = + > # now, "changeset" should be chosen for "hg commit" + > EOF + + $ HGEDITOR=cat hg commit -q HG: this is customized commit template HG: Leave message empty to abort commit. HG: no bookmark is activated
--- a/tests/test-completion.t Sun Aug 10 23:09:23 2014 -0500 +++ b/tests/test-completion.t Mon Aug 11 11:24:05 2014 -0500 @@ -257,7 +257,7 @@ debugsuccessorssets: debugwalk: include, exclude debugwireargs: three, four, five, ssh, remotecmd, insecure - graft: rev, continue, edit, log, currentdate, currentuser, date, user, tool, dry-run + graft: rev, continue, edit, log, force, currentdate, currentuser, date, user, tool, dry-run grep: print0, all, text, follow, ignore-case, files-with-matches, line-number, rev, user, date, include, exclude heads: rev, topo, active, closed, style, template help: extension, command, keyword
--- a/tests/test-conflict.t Sun Aug 10 23:09:23 2014 -0500 +++ b/tests/test-conflict.t Mon Aug 11 11:24:05 2014 -0500 @@ -198,3 +198,37 @@ 5 >>>>>>> other Hop we are done. + +internal:merge3 + + $ hg up -q --clean . + + $ hg merge 1 --tool internal:merge3 + merging a + warning: conflicts during merge. + merging a incomplete! (edit conflicts, then use 'hg resolve --mark') + 0 files updated, 0 files merged, 0 files removed, 1 files unresolved + use 'hg resolve' to retry unresolved file merges or 'hg update -C .' to abandon + [1] + $ cat a + Small Mathematical Series. + <<<<<<< local + 1 + 2 + 3 + 6 + 8 + ||||||| base + One + Two + Three + Four + Five + ======= + 1 + 2 + 3 + 4 + 5 + >>>>>>> other + Hop we are done.
--- a/tests/test-contrib.t Sun Aug 10 23:09:23 2014 -0500 +++ b/tests/test-contrib.t Mon Aug 11 11:24:05 2014 -0500 @@ -143,23 +143,11 @@ $ echo not other >> conflict-local $ echo end >> conflict-local $ echo end >> conflict-other + $ python simplemerge -p conflict-local base conflict-other base <<<<<<< conflict-local not other - ======= - other - >>>>>>> conflict-other - end - warning: conflicts during merge. - [1] - ---no-minimal - - $ python simplemerge -p --no-minimal conflict-local base conflict-other - base - <<<<<<< conflict-local - not other end ======= other @@ -174,10 +162,11 @@ base <<<<<<< foo not other + end ======= other + end >>>>>>> conflict-other - end warning: conflicts during merge. [1] @@ -187,17 +176,33 @@ base <<<<<<< foo not other + end ======= other + end >>>>>>> bar + warning: conflicts during merge. + [1] + +3 labels + + $ python simplemerge -p -L foo -L bar -L base conflict-local base conflict-other + base + <<<<<<< foo + not other end + ||||||| base + ======= + other + end + >>>>>>> bar warning: conflicts during merge. [1] too many labels - $ python simplemerge -p -L foo -L bar -L baz conflict-local base conflict-other - abort: can only specify two labels. + $ python simplemerge -p -L foo -L bar -L baz -L buz conflict-local base conflict-other + abort: can only specify three labels. [255] binary file @@ -231,7 +236,7 @@ -L --label labels to use on conflict markers -a --text treat all files as text -p --print print results instead of overwriting LOCAL - --no-minimal do not try to minimize conflict regions + --no-minimal no effect (DEPRECATED) -h --help display help and exit -q --quiet suppress output @@ -251,7 +256,7 @@ -L --label labels to use on conflict markers -a --text treat all files as text -p --print print results instead of overwriting LOCAL - --no-minimal do not try to minimize conflict regions + --no-minimal no effect (DEPRECATED) -h --help display help and exit -q --quiet suppress output [1] @@ -272,7 +277,7 @@ -L --label labels to use on conflict markers -a --text treat all files as text -p --print print results instead of overwriting LOCAL - --no-minimal do not try to minimize conflict regions + --no-minimal no effect (DEPRECATED) -h --help display help and exit -q --quiet suppress output [1]
--- a/tests/test-convert-baz.t Sun Aug 10 23:09:23 2014 -0500 +++ b/tests/test-convert-baz.t Mon Aug 11 11:24:05 2014 -0500 @@ -1,4 +1,4 @@ - $ "$TESTDIR/hghave" baz symlink || exit 80 +#require baz symlink $ baz my-id "mercurial <mercurial@selenic.com>"
--- a/tests/test-convert-bzr-114.t Sun Aug 10 23:09:23 2014 -0500 +++ b/tests/test-convert-bzr-114.t Mon Aug 11 11:24:05 2014 -0500 @@ -1,5 +1,5 @@ +#require bzr114 - $ "$TESTDIR/hghave" bzr114 || exit 80 $ . "$TESTDIR/bzr-definitions" The file/directory replacement can only be reproduced on
--- a/tests/test-convert-cvs-branch.t Sun Aug 10 23:09:23 2014 -0500 +++ b/tests/test-convert-cvs-branch.t Mon Aug 11 11:24:05 2014 -0500 @@ -1,7 +1,8 @@ +#require cvs + This is http://mercurial.selenic.com/bts/issue1148 and http://mercurial.selenic.com/bts/issue1447 - $ "$TESTDIR/hghave" cvs || exit 80 $ cvscall() > { > cvs -f "$@" > /dev/null
--- a/tests/test-convert-cvs-detectmerge.t Sun Aug 10 23:09:23 2014 -0500 +++ b/tests/test-convert-cvs-detectmerge.t Mon Aug 11 11:24:05 2014 -0500 @@ -1,8 +1,9 @@ +#require cvs + Test config convert.cvsps.mergefrom config setting. (Should test similar mergeto feature, but I don't understand it yet.) Requires builtin cvsps. - $ "$TESTDIR/hghave" cvs || exit 80 $ CVSROOT=`pwd`/cvsrepo $ export CVSROOT
--- a/tests/test-convert-cvs-synthetic.t Sun Aug 10 23:09:23 2014 -0500 +++ b/tests/test-convert-cvs-synthetic.t Mon Aug 11 11:24:05 2014 -0500 @@ -1,6 +1,7 @@ +#require cvs112 + This feature requires use of builtin cvsps! - $ "$TESTDIR/hghave" cvs112 || exit 80 $ echo "[extensions]" >> $HGRCPATH $ echo "convert = " >> $HGRCPATH
--- a/tests/test-convert-cvs.t Sun Aug 10 23:09:23 2014 -0500 +++ b/tests/test-convert-cvs.t Mon Aug 11 11:24:05 2014 -0500 @@ -1,5 +1,5 @@ +#require cvs - $ "$TESTDIR/hghave" cvs || exit 80 $ cvscall() > { > cvs -f "$@"
--- a/tests/test-convert-cvsnt-mergepoints.t Sun Aug 10 23:09:23 2014 -0500 +++ b/tests/test-convert-cvsnt-mergepoints.t Mon Aug 11 11:24:05 2014 -0500 @@ -1,5 +1,5 @@ +#require cvs - $ "$TESTDIR/hghave" cvs || exit 80 $ filterpath() > { > eval "$@" | sed "s:$CVSROOT:*REPO*:g"
--- a/tests/test-convert-darcs.t Sun Aug 10 23:09:23 2014 -0500 +++ b/tests/test-convert-darcs.t Mon Aug 11 11:24:05 2014 -0500 @@ -1,5 +1,5 @@ +#require darcs - $ "$TESTDIR/hghave" darcs || exit 80 $ echo "[extensions]" >> $HGRCPATH $ echo "convert=" >> $HGRCPATH $ DARCS_EMAIL='test@example.org'; export DARCS_EMAIL
--- a/tests/test-convert-git.t Sun Aug 10 23:09:23 2014 -0500 +++ b/tests/test-convert-git.t Mon Aug 11 11:24:05 2014 -0500 @@ -1,5 +1,5 @@ +#require git - $ "$TESTDIR/hghave" git || exit 80 $ echo "[core]" >> $HOME/.gitconfig $ echo "autocrlf = false" >> $HOME/.gitconfig $ echo "[core]" >> $HOME/.gitconfig
--- a/tests/test-convert-hg-svn.t Sun Aug 10 23:09:23 2014 -0500 +++ b/tests/test-convert-hg-svn.t Mon Aug 11 11:24:05 2014 -0500 @@ -1,5 +1,5 @@ +#require svn svn-bindings - $ "$TESTDIR/hghave" svn svn-bindings || exit 80 $ echo "[extensions]" >> $HGRCPATH $ echo "convert = " >> $HGRCPATH $ echo "mq = " >> $HGRCPATH
--- a/tests/test-convert-mtn.t Sun Aug 10 23:09:23 2014 -0500 +++ b/tests/test-convert-mtn.t Mon Aug 11 11:24:05 2014 -0500 @@ -1,5 +1,4 @@ - - $ "$TESTDIR/hghave" mtn || exit 80 +#require mtn Monotone directory is called .monotone on *nix and monotone on Windows.
--- a/tests/test-convert-p4-filetypes.t Sun Aug 10 23:09:23 2014 -0500 +++ b/tests/test-convert-p4-filetypes.t Mon Aug 11 11:24:05 2014 -0500 @@ -1,4 +1,4 @@ - $ "$TESTDIR/hghave" p4 execbit symlink || exit 80 +#require p4 execbit symlink $ echo "[extensions]" >> $HGRCPATH $ echo "convert = " >> $HGRCPATH
--- a/tests/test-convert-p4.t Sun Aug 10 23:09:23 2014 -0500 +++ b/tests/test-convert-p4.t Mon Aug 11 11:24:05 2014 -0500 @@ -1,4 +1,4 @@ - $ "$TESTDIR/hghave" p4 || exit 80 +#require p4 $ echo "[extensions]" >> $HGRCPATH $ echo "convert = " >> $HGRCPATH
--- a/tests/test-convert-svn-branches.t Sun Aug 10 23:09:23 2014 -0500 +++ b/tests/test-convert-svn-branches.t Mon Aug 11 11:24:05 2014 -0500 @@ -1,5 +1,4 @@ - - $ "$TESTDIR/hghave" svn svn-bindings || exit 80 +#require svn svn-bindings $ cat >> $HGRCPATH <<EOF > [extensions]
--- a/tests/test-convert-svn-encoding.t Sun Aug 10 23:09:23 2014 -0500 +++ b/tests/test-convert-svn-encoding.t Mon Aug 11 11:24:05 2014 -0500 @@ -1,5 +1,4 @@ - - $ "$TESTDIR/hghave" svn svn-bindings || exit 80 +#require svn svn-bindings $ cat >> $HGRCPATH <<EOF > [extensions]
--- a/tests/test-convert-svn-move.t Sun Aug 10 23:09:23 2014 -0500 +++ b/tests/test-convert-svn-move.t Mon Aug 11 11:24:05 2014 -0500 @@ -1,5 +1,4 @@ - - $ "$TESTDIR/hghave" svn svn-bindings || exit 80 +#require svn svn-bindings $ cat >> $HGRCPATH <<EOF > [extensions]
--- a/tests/test-convert-svn-sink.t Sun Aug 10 23:09:23 2014 -0500 +++ b/tests/test-convert-svn-sink.t Mon Aug 11 11:24:05 2014 -0500 @@ -1,4 +1,4 @@ - $ "$TESTDIR/hghave" svn13 || exit 80 +#require svn13 $ svnupanddisplay() > {
--- a/tests/test-convert-svn-source.t Sun Aug 10 23:09:23 2014 -0500 +++ b/tests/test-convert-svn-source.t Mon Aug 11 11:24:05 2014 -0500 @@ -1,5 +1,4 @@ - - $ "$TESTDIR/hghave" svn svn-bindings || exit 80 +#require svn svn-bindings $ cat >> $HGRCPATH <<EOF > [extensions]
--- a/tests/test-convert-svn-startrev.t Sun Aug 10 23:09:23 2014 -0500 +++ b/tests/test-convert-svn-startrev.t Mon Aug 11 11:24:05 2014 -0500 @@ -1,5 +1,4 @@ - - $ "$TESTDIR/hghave" svn svn-bindings || exit 80 +#require svn svn-bindings $ cat >> $HGRCPATH <<EOF > [extensions]
--- a/tests/test-convert-svn-tags.t Sun Aug 10 23:09:23 2014 -0500 +++ b/tests/test-convert-svn-tags.t Mon Aug 11 11:24:05 2014 -0500 @@ -1,5 +1,4 @@ - - $ "$TESTDIR/hghave" svn svn-bindings || exit 80 +#require svn svn-bindings $ cat >> $HGRCPATH <<EOF > [extensions]
--- a/tests/test-convert-tagsbranch-topology.t Sun Aug 10 23:09:23 2014 -0500 +++ b/tests/test-convert-tagsbranch-topology.t Mon Aug 11 11:24:05 2014 -0500 @@ -1,5 +1,5 @@ +#require git - $ "$TESTDIR/hghave" git || exit 80 $ echo "[core]" >> $HOME/.gitconfig $ echo "autocrlf = false" >> $HOME/.gitconfig $ echo "[core]" >> $HOME/.gitconfig
--- a/tests/test-convert-tla.t Sun Aug 10 23:09:23 2014 -0500 +++ b/tests/test-convert-tla.t Mon Aug 11 11:24:05 2014 -0500 @@ -1,5 +1,5 @@ +#require tla symlink - $ "$TESTDIR/hghave" tla symlink || exit 80 $ tla my-id "mercurial <mercurial@selenic.com>" $ echo "[extensions]" >> $HGRCPATH $ echo "convert=" >> $HGRCPATH
--- a/tests/test-diff-upgrade.t Sun Aug 10 23:09:23 2014 -0500 +++ b/tests/test-diff-upgrade.t Mon Aug 11 11:24:05 2014 -0500 @@ -1,4 +1,4 @@ - $ "$TESTDIR/hghave" execbit || exit 80 +#require execbit $ echo "[extensions]" >> $HGRCPATH $ echo "autodiff=$TESTDIR/autodiff.py" >> $HGRCPATH
--- a/tests/test-eolfilename.t Sun Aug 10 23:09:23 2014 -0500 +++ b/tests/test-eolfilename.t Mon Aug 11 11:24:05 2014 -0500 @@ -1,6 +1,6 @@ -http://mercurial.selenic.com/bts/issue352 +#require eol-in-paths - $ "$TESTDIR/hghave" eol-in-paths || exit 80 +http://mercurial.selenic.com/bts/issue352 test issue352
--- a/tests/test-execute-bit.t Sun Aug 10 23:09:23 2014 -0500 +++ b/tests/test-execute-bit.t Mon Aug 11 11:24:05 2014 -0500 @@ -1,4 +1,4 @@ - $ "$TESTDIR/hghave" execbit || exit 80 +#require execbit $ hg init $ echo a > a
--- a/tests/test-fetch.t Sun Aug 10 23:09:23 2014 -0500 +++ b/tests/test-fetch.t Mon Aug 11 11:24:05 2014 -0500 @@ -1,4 +1,4 @@ - $ "$TESTDIR/hghave" serve || exit 80 +#require serve $ echo "[extensions]" >> $HGRCPATH $ echo "fetch=" >> $HGRCPATH
--- a/tests/test-flags.t Sun Aug 10 23:09:23 2014 -0500 +++ b/tests/test-flags.t Mon Aug 11 11:24:05 2014 -0500 @@ -1,4 +1,4 @@ - $ "$TESTDIR/hghave" execbit || exit 80 +#require execbit $ umask 027
--- a/tests/test-gendoc.t Sun Aug 10 23:09:23 2014 -0500 +++ b/tests/test-gendoc.t Mon Aug 11 11:24:05 2014 -0500 @@ -1,6 +1,7 @@ +#require docutils + Test document extraction - $ "$TESTDIR/hghave" docutils || exit 80 $ HGENCODING=UTF-8 $ export HGENCODING $ { echo C; ls "$TESTDIR/../i18n"/*.po | sort; } | while read PO; do
--- a/tests/test-getbundle.t Sun Aug 10 23:09:23 2014 -0500 +++ b/tests/test-getbundle.t Mon Aug 11 11:24:05 2014 -0500 @@ -1,4 +1,4 @@ - $ "$TESTDIR/hghave" serve || exit 80 +#require serve = Test the getbundle() protocol function =
--- a/tests/test-glog.t Sun Aug 10 23:09:23 2014 -0500 +++ b/tests/test-glog.t Mon Aug 11 11:24:05 2014 -0500 @@ -1645,13 +1645,28 @@ ('symbol', 'filelog') ('string', 'aa')))) -Test --follow on a directory +Test --follow on a non-existent directory $ testlog -f dir abort: cannot follow file not in parent revision: "dir" abort: cannot follow file not in parent revision: "dir" abort: cannot follow file not in parent revision: "dir" +Test --follow on a directory + + $ hg up -q '.^' + $ testlog -f dir + [] + (group + (func + ('symbol', '_matchfiles') + (list + (list + ('string', 'r:') + ('string', 'd:relpath')) + ('string', 'p:dir')))) + $ hg up -q tip + Test --follow on file not in parent revision $ testlog -f a @@ -1662,9 +1677,15 @@ Test --follow and patterns $ testlog -f 'glob:*' - abort: can only follow copies/renames for explicit filenames - abort: can only follow copies/renames for explicit filenames - abort: can only follow copies/renames for explicit filenames + [] + (group + (func + ('symbol', '_matchfiles') + (list + (list + ('string', 'r:') + ('string', 'd:relpath')) + ('string', 'p:glob:*')))) Test --follow on a single rename @@ -1829,9 +1850,15 @@ ('string', 'd:relpath')) ('string', 'p:a')))) $ testlog --removed --follow a - abort: can only follow copies/renames for explicit filenames - abort: can only follow copies/renames for explicit filenames - abort: can only follow copies/renames for explicit filenames + [] + (group + (func + ('symbol', '_matchfiles') + (list + (list + ('string', 'r:') + ('string', 'd:relpath')) + ('string', 'p:a')))) Test --patch and --stat with --follow and --follow-first
--- a/tests/test-gpg.t Sun Aug 10 23:09:23 2014 -0500 +++ b/tests/test-gpg.t Mon Aug 11 11:24:05 2014 -0500 @@ -1,6 +1,7 @@ +#require gpg + Test the GPG extension - $ "$TESTDIR/hghave" gpg || exit 80 $ cat <<EOF >> $HGRCPATH > [extensions] > gpg=
--- a/tests/test-graft.t Sun Aug 10 23:09:23 2014 -0500 +++ b/tests/test-graft.t Mon Aug 11 11:24:05 2014 -0500 @@ -631,3 +631,50 @@ grafting revision 13 grafting revision 19 merging b + +graft with --force (still doesn't graft merges) + + $ hg graft 19 0 6 + skipping ungraftable merge revision 6 + skipping ancestor revision 0 + skipping already grafted revision 19 (22 also has origin 2) + [255] + $ hg graft 19 0 6 --force + skipping ungraftable merge revision 6 + grafting revision 19 + merging b + grafting revision 0 + +graft --force after backout + + $ echo abc > a + $ hg ci -m 28 + $ hg backout 28 + reverting a + changeset 29:484c03b8dfa4 backs out changeset 28:6c56f0f7f033 + $ hg graft 28 + skipping ancestor revision 28 + [255] + $ hg graft 28 --force + grafting revision 28 + merging a + $ cat a + abc + +graft --continue after --force + + $ hg backout 30 + reverting a + changeset 31:3b96c18b7a1b backs out changeset 30:8f539994be33 + $ hg graft 28 --force --tool internal:fail + grafting revision 28 + abort: unresolved conflicts, can't continue + (use hg resolve and hg graft --continue) + [255] + $ hg resolve --all + merging a + (no more unresolved files) + $ hg graft -c + grafting revision 28 + $ cat a + abc
--- a/tests/test-hardlinks.t Sun Aug 10 23:09:23 2014 -0500 +++ b/tests/test-hardlinks.t Mon Aug 11 11:24:05 2014 -0500 @@ -1,4 +1,4 @@ - $ "$TESTDIR/hghave" hardlink || exit 80 +#require hardlink $ cat > nlinks.py <<EOF > import sys
--- a/tests/test-hgweb-commands.t Sun Aug 10 23:09:23 2014 -0500 +++ b/tests/test-hgweb-commands.t Mon Aug 11 11:24:05 2014 -0500 @@ -1,4 +1,4 @@ - $ "$TESTDIR/hghave" serve || exit 80 +#require serve An attempt at more fully testing the hgweb web interface. The following things are tested elsewhere and are therefore omitted:
--- a/tests/test-hgweb-descend-empties.t Sun Aug 10 23:09:23 2014 -0500 +++ b/tests/test-hgweb-descend-empties.t Mon Aug 11 11:24:05 2014 -0500 @@ -1,4 +1,4 @@ - $ "$TESTDIR/hghave" serve || exit 80 +#require serve Test chains of near empty directories, terminating 3 different ways: - a1: file at level 4 (deepest)
--- a/tests/test-hgweb-diffs.t Sun Aug 10 23:09:23 2014 -0500 +++ b/tests/test-hgweb-diffs.t Mon Aug 11 11:24:05 2014 -0500 @@ -1,4 +1,4 @@ - $ "$TESTDIR/hghave" serve || exit 80 +#require serve setting up repo
--- a/tests/test-hgweb-empty.t Sun Aug 10 23:09:23 2014 -0500 +++ b/tests/test-hgweb-empty.t Mon Aug 11 11:24:05 2014 -0500 @@ -1,4 +1,4 @@ - $ "$TESTDIR/hghave" serve || exit 80 +#require serve Some tests for hgweb in an empty repository
--- a/tests/test-hgweb-filelog.t Sun Aug 10 23:09:23 2014 -0500 +++ b/tests/test-hgweb-filelog.t Mon Aug 11 11:24:05 2014 -0500 @@ -1,4 +1,4 @@ - $ "$TESTDIR/hghave" serve || exit 80 +#require serve $ hg init test $ cd test
--- a/tests/test-hgweb-raw.t Sun Aug 10 23:09:23 2014 -0500 +++ b/tests/test-hgweb-raw.t Mon Aug 11 11:24:05 2014 -0500 @@ -1,4 +1,4 @@ - $ "$TESTDIR/hghave" serve || exit 80 +#require serve Test raw style of hgweb
--- a/tests/test-hgweb-removed.t Sun Aug 10 23:09:23 2014 -0500 +++ b/tests/test-hgweb-removed.t Mon Aug 11 11:24:05 2014 -0500 @@ -1,4 +1,4 @@ - $ "$TESTDIR/hghave" serve || exit 80 +#require serve setting up repo
--- a/tests/test-hgweb.t Sun Aug 10 23:09:23 2014 -0500 +++ b/tests/test-hgweb.t Mon Aug 11 11:24:05 2014 -0500 @@ -1,4 +1,4 @@ - $ "$TESTDIR/hghave" serve || exit 80 +#require serve Some tests for hgweb. Tests static files, plain files and different 404's.
--- a/tests/test-hgwebdir.t Sun Aug 10 23:09:23 2014 -0500 +++ b/tests/test-hgwebdir.t Mon Aug 11 11:24:05 2014 -0500 @@ -1,4 +1,4 @@ - $ "$TESTDIR/hghave" serve || exit 80 +#require serve hide outer repo and work in dir without '.hg' $ hg init
--- a/tests/test-hgwebdirsym.t Sun Aug 10 23:09:23 2014 -0500 +++ b/tests/test-hgwebdirsym.t Mon Aug 11 11:24:05 2014 -0500 @@ -1,6 +1,6 @@ -Tests whether or not hgwebdir properly handles various symlink topologies. +#require serve symlink - $ "$TESTDIR/hghave" serve symlink || exit 80 +Tests whether or not hgwebdir properly handles various symlink topologies. hide outer repo $ hg init
--- a/tests/test-highlight.t Sun Aug 10 23:09:23 2014 -0500 +++ b/tests/test-highlight.t Mon Aug 11 11:24:05 2014 -0500 @@ -1,5 +1,5 @@ +#require pygments serve - $ "$TESTDIR/hghave" pygments serve || exit 80 $ cat <<EOF >> $HGRCPATH > [extensions] > highlight =
--- a/tests/test-hook.t Sun Aug 10 23:09:23 2014 -0500 +++ b/tests/test-hook.t Mon Aug 11 11:24:05 2014 -0500 @@ -210,6 +210,7 @@ $ hg push -B baz ../a pushing to ../a searching for changes + listkeys hook: HG_NAMESPACE=phases HG_VALUES={'cb9a9f314b8b07ba71012fcdbc544b5a4d82ff5b': '1', 'publishing': 'True'} no changes found listkeys hook: HG_NAMESPACE=phases HG_VALUES={'cb9a9f314b8b07ba71012fcdbc544b5a4d82ff5b': '1', 'publishing': 'True'} listkeys hook: HG_NAMESPACE=bookmarks HG_VALUES={'bar': '0000000000000000000000000000000000000000', 'foo': '0000000000000000000000000000000000000000'}
--- a/tests/test-http-branchmap.t Sun Aug 10 23:09:23 2014 -0500 +++ b/tests/test-http-branchmap.t Mon Aug 11 11:24:05 2014 -0500 @@ -1,4 +1,4 @@ - $ "$TESTDIR/hghave" killdaemons || exit 80 +#require killdaemons $ hgserve() { > hg serve -a localhost -p $HGPORT1 -d --pid-file=hg.pid \
--- a/tests/test-http-clone-r.t Sun Aug 10 23:09:23 2014 -0500 +++ b/tests/test-http-clone-r.t Mon Aug 11 11:24:05 2014 -0500 @@ -1,4 +1,4 @@ - $ "$TESTDIR/hghave" serve || exit 80 +#require serve creating 'remote
--- a/tests/test-http-proxy.t Sun Aug 10 23:09:23 2014 -0500 +++ b/tests/test-http-proxy.t Mon Aug 11 11:24:05 2014 -0500 @@ -1,4 +1,4 @@ - $ "$TESTDIR/hghave" serve || exit 80 +#require serve $ hg init a $ cd a
--- a/tests/test-http.t Sun Aug 10 23:09:23 2014 -0500 +++ b/tests/test-http.t Mon Aug 11 11:24:05 2014 -0500 @@ -1,4 +1,4 @@ - $ "$TESTDIR/hghave" serve || exit 80 +#require serve $ hg init test $ cd test @@ -261,9 +261,10 @@ "GET /?cmd=listkeys HTTP/1.1" 403 - x-hgarg-1:namespace=namespaces "GET /?cmd=capabilities HTTP/1.1" 200 - "GET /?cmd=batch HTTP/1.1" 200 - x-hgarg-1:cmds=heads+%3Bknown+nodes%3D7f4e523d01f2cc3765ac8934da3d14db775ff872 + "GET /?cmd=listkeys HTTP/1.1" 401 - x-hgarg-1:namespace=phases + "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=phases "GET /?cmd=branchmap HTTP/1.1" 200 - "GET /?cmd=branchmap HTTP/1.1" 200 - - "GET /?cmd=listkeys HTTP/1.1" 401 - x-hgarg-1:namespace=bookmarks "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=bookmarks "POST /?cmd=unbundle HTTP/1.1" 200 - x-hgarg-1:heads=686173686564+5eb5abfefeea63c80dd7553bcc3783f37e0c5524 "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=phases
--- a/tests/test-https.t Sun Aug 10 23:09:23 2014 -0500 +++ b/tests/test-https.t Mon Aug 11 11:24:05 2014 -0500 @@ -1,6 +1,6 @@ -Proper https client requires the built-in ssl from Python 2.6. +#require serve ssl - $ "$TESTDIR/hghave" serve ssl || exit 80 +Proper https client requires the built-in ssl from Python 2.6. Certificates created with: printf '.\n.\n.\n.\n.\nlocalhost\nhg@localhost\n' | \
--- a/tests/test-hup.t Sun Aug 10 23:09:23 2014 -0500 +++ b/tests/test-hup.t Mon Aug 11 11:24:05 2014 -0500 @@ -1,6 +1,7 @@ +#require serve fifo + Test hangup signal in the middle of transaction - $ "$TESTDIR/hghave" serve fifo || exit 80 $ hg init $ mkfifo p $ hg serve --stdio < p 1>out 2>&1 &
--- a/tests/test-i18n.t Sun Aug 10 23:09:23 2014 -0500 +++ b/tests/test-i18n.t Mon Aug 11 11:24:05 2014 -0500 @@ -1,6 +1,6 @@ -Translations are optional: +#require gettext - $ "$TESTDIR/hghave" gettext || exit 80 +(Translations are optional) #if no-outer-repo
--- a/tests/test-identify.t Sun Aug 10 23:09:23 2014 -0500 +++ b/tests/test-identify.t Mon Aug 11 11:24:05 2014 -0500 @@ -1,4 +1,4 @@ - $ "$TESTDIR/hghave" serve || exit 80 +#require serve #if no-outer-repo
--- a/tests/test-incoming-outgoing.t Sun Aug 10 23:09:23 2014 -0500 +++ b/tests/test-incoming-outgoing.t Mon Aug 11 11:24:05 2014 -0500 @@ -1,4 +1,4 @@ - $ "$TESTDIR/hghave" serve || exit 80 +#require serve $ hg init test $ cd test
--- a/tests/test-inherit-mode.t Sun Aug 10 23:09:23 2014 -0500 +++ b/tests/test-inherit-mode.t Mon Aug 11 11:24:05 2014 -0500 @@ -1,7 +1,6 @@ -test that new files created in .hg inherit the permissions from .hg/store +#require unix-permissions - - $ "$TESTDIR/hghave" unix-permissions || exit 80 +test that new files created in .hg inherit the permissions from .hg/store $ mkdir dir @@ -121,7 +120,6 @@ 00660 ../push/.hg/store/data/dir/bar.i 00660 ../push/.hg/store/data/foo.i 00660 ../push/.hg/store/fncache - 00660 ../push/.hg/store/phaseroots 00660 ../push/.hg/store/undo 00660 ../push/.hg/store/undo.phaseroots 00660 ../push/.hg/undo.bookmarks
--- a/tests/test-issue1438.t Sun Aug 10 23:09:23 2014 -0500 +++ b/tests/test-issue1438.t Mon Aug 11 11:24:05 2014 -0500 @@ -1,6 +1,6 @@ -http://mercurial.selenic.com/bts/issue1438 +#require symlink - $ "$TESTDIR/hghave" symlink || exit 80 +http://mercurial.selenic.com/bts/issue1438 $ hg init
--- a/tests/test-issue1802.t Sun Aug 10 23:09:23 2014 -0500 +++ b/tests/test-issue1802.t Mon Aug 11 11:24:05 2014 -0500 @@ -1,4 +1,4 @@ - $ "$TESTDIR/hghave" execbit || exit 80 +#require execbit Create extension that can disable exec checks:
--- a/tests/test-known.t Sun Aug 10 23:09:23 2014 -0500 +++ b/tests/test-known.t Mon Aug 11 11:24:05 2014 -0500 @@ -1,4 +1,4 @@ - $ "$TESTDIR/hghave" killdaemons || exit 80 +#require killdaemons = Test the known() protocol function =
--- a/tests/test-largefiles-update.t Sun Aug 10 23:09:23 2014 -0500 +++ b/tests/test-largefiles-update.t Mon Aug 11 11:24:05 2014 -0500 @@ -99,4 +99,72 @@ $ cat .hglf/large1 58e24f733a964da346e2407a2bee99d9001184f5 +Test that "hg rollback" restores status of largefiles correctly + + $ hg update -C -q + $ hg remove large1 + $ hg forget large2 + $ echo largeX > largeX + $ hg add --large largeX + $ hg commit -m 'will be rollback-ed soon' + $ echo largeY > largeY + $ hg add --large largeY + $ hg status -A large1 + large1: No such file or directory + $ hg status -A large2 + ? large2 + $ hg status -A largeX + C largeX + $ hg status -A largeY + A largeY + $ hg rollback + repository tip rolled back to revision 3 (undo commit) + working directory now based on revision 3 + $ hg status -A large1 + R large1 + $ hg status -A large2 + R large2 + $ hg status -A largeX + A largeX + $ hg status -A largeY + ? largeY + +Test that "hg status" shows status of largefiles correctly just after +automated commit like rebase/transplant + + $ cat >> .hg/hgrc <<EOF + > [extensions] + > rebase = + > strip = + > transplant = + > EOF + $ hg update -q -C 1 + $ hg remove large1 + $ echo largeX > largeX + $ hg add --large largeX + $ hg commit -m '#4' + + $ hg rebase -s 1 -d 2 --keep + $ hg status -A large1 + large1: No such file or directory + $ hg status -A largeX + C largeX + $ hg strip -q 5 + + $ hg update -q -C 2 + $ hg transplant -q 1 4 + $ hg status -A large1 + large1: No such file or directory + $ hg status -A largeX + C largeX + $ hg strip -q 5 + + $ hg update -q -C 2 + $ hg transplant -q --merge 1 --merge 4 + $ hg status -A large1 + large1: No such file or directory + $ hg status -A largeX + C largeX + $ hg strip -q 5 + $ cd ..
--- a/tests/test-lock-badness.t Sun Aug 10 23:09:23 2014 -0500 +++ b/tests/test-lock-badness.t Mon Aug 11 11:24:05 2014 -0500 @@ -1,4 +1,4 @@ -#if unix-permissions no-root no-windows +#require unix-permissions no-root no-windows Prepare @@ -39,4 +39,3 @@ [255] $ chmod 700 a/.hg/store -#endif
--- a/tests/test-log.t Sun Aug 10 23:09:23 2014 -0500 +++ b/tests/test-log.t Mon Aug 11 11:24:05 2014 -0500 @@ -78,12 +78,52 @@ summary: c --f, directory +-f, non-existent directory $ hg log -f dir abort: cannot follow file not in parent revision: "dir" [255] +-f, directory + + $ hg up -q 3 + $ hg log -f dir + changeset: 2:f8954cd4dc1f + user: test + date: Thu Jan 01 00:00:03 1970 +0000 + summary: c + +-f, directory with --patch + + $ hg log -f dir -p + changeset: 2:f8954cd4dc1f + user: test + date: Thu Jan 01 00:00:03 1970 +0000 + summary: c + + diff -r d89b0a12d229 -r f8954cd4dc1f dir/b + --- /dev/null* (glob) + +++ b/dir/b* (glob) + @@ -0,0 +1,1 @@ + +a + + +-f, pattern + + $ hg log -f -I 'dir**' -p + changeset: 2:f8954cd4dc1f + user: test + date: Thu Jan 01 00:00:03 1970 +0000 + summary: c + + diff -r d89b0a12d229 -r f8954cd4dc1f dir/b + --- /dev/null* (glob) + +++ b/dir/b* (glob) + @@ -0,0 +1,1 @@ + +a + + $ hg up -q 4 + -f, a wrong style $ hg log -f -l1 --style something
--- a/tests/test-merge-tools.t Sun Aug 10 23:09:23 2014 -0500 +++ b/tests/test-merge-tools.t Mon Aug 11 11:24:05 2014 -0500 @@ -30,6 +30,14 @@ $ echo "revision 3" >> f $ hg commit -Am "revision 3" created new head + +revision 4 - hard to merge + + $ hg update 0 > /dev/null + $ echo "revision 4" > f + $ hg commit -Am "revision 4" + created new head + $ echo "[merge-tools]" > .hg/hgrc $ beforemerge() { @@ -701,6 +709,77 @@ # hg stat M f +premerge=keep keeps conflict markers in: + + $ beforemerge + [merge-tools] + false.whatever= + true.priority=1 + true.executable=cat + # hg update -C 1 + $ hg merge -r 4 --config merge-tools.true.premerge=keep + merging f + <<<<<<< local: ef83787e2614 - test: revision 1 + revision 1 + space + ======= + revision 4 + >>>>>>> other: 81448d39c9a0 - test: revision 4 + revision 0 + space + revision 4 + 0 files updated, 1 files merged, 0 files removed, 0 files unresolved + (branch merge, don't forget to commit) + $ aftermerge + # cat f + <<<<<<< local: ef83787e2614 - test: revision 1 + revision 1 + space + ======= + revision 4 + >>>>>>> other: 81448d39c9a0 - test: revision 4 + # hg stat + M f + +premerge=keep-merge3 keeps conflict markers with base content: + + $ beforemerge + [merge-tools] + false.whatever= + true.priority=1 + true.executable=cat + # hg update -C 1 + $ hg merge -r 4 --config merge-tools.true.premerge=keep-merge3 + merging f + <<<<<<< local: ef83787e2614 - test: revision 1 + revision 1 + space + ||||||| base + revision 0 + space + ======= + revision 4 + >>>>>>> other: 81448d39c9a0 - test: revision 4 + revision 0 + space + revision 4 + 0 files updated, 1 files merged, 0 files removed, 0 files unresolved + (branch merge, don't forget to commit) + $ aftermerge + # cat f + <<<<<<< local: ef83787e2614 - test: revision 1 + revision 1 + space + ||||||| base + revision 0 + space + ======= + revision 4 + >>>>>>> other: 81448d39c9a0 - test: revision 4 + # hg stat + M f + + Tool execution set tools.args explicit to include $base $local $other $output: @@ -832,17 +911,17 @@ true.priority=1 true.executable=cat # hg update -C 1 - $ echo "revision 4" > '"; exit 1; echo "' - $ hg commit -Am "revision 4" - adding "; exit 1; echo " - warning: filename contains '"', which is reserved on Windows: '"; exit 1; echo "' - $ hg update -C 1 > /dev/null $ echo "revision 5" > '"; exit 1; echo "' $ hg commit -Am "revision 5" adding "; exit 1; echo " warning: filename contains '"', which is reserved on Windows: '"; exit 1; echo "' + $ hg update -C 1 > /dev/null + $ echo "revision 6" > '"; exit 1; echo "' + $ hg commit -Am "revision 6" + adding "; exit 1; echo " + warning: filename contains '"', which is reserved on Windows: '"; exit 1; echo "' created new head - $ hg merge --config merge-tools.true.executable="true" -r 4 + $ hg merge --config merge-tools.true.executable="true" -r 5 merging "; exit 1; echo " 0 files updated, 1 files merged, 0 files removed, 0 files unresolved (branch merge, don't forget to commit)
--- a/tests/test-merge-types.t Sun Aug 10 23:09:23 2014 -0500 +++ b/tests/test-merge-types.t Mon Aug 11 11:24:05 2014 -0500 @@ -1,4 +1,4 @@ - $ "$TESTDIR/hghave" symlink execbit || exit 80 +#require symlink execbit $ tellmeabout() { > if [ -h $1 ]; then
--- a/tests/test-mq-qclone-http.t Sun Aug 10 23:09:23 2014 -0500 +++ b/tests/test-mq-qclone-http.t Mon Aug 11 11:24:05 2014 -0500 @@ -1,4 +1,4 @@ - $ "$TESTDIR/hghave" killdaemons || exit 80 +#require killdaemons hide outer repo $ hg init
--- a/tests/test-mq-qimport.t Sun Aug 10 23:09:23 2014 -0500 +++ b/tests/test-mq-qimport.t Mon Aug 11 11:24:05 2014 -0500 @@ -1,4 +1,4 @@ - $ "$TESTDIR/hghave" killdaemons || exit 80 +#require killdaemons $ cat > writelines.py <<EOF > import sys
--- a/tests/test-mq-qrefresh-replace-log-message.t Sun Aug 10 23:09:23 2014 -0500 +++ b/tests/test-mq-qrefresh-replace-log-message.t Mon Aug 11 11:24:05 2014 -0500 @@ -32,17 +32,19 @@ $ cat >> .hg/hgrc <<EOF > [committemplate] + > listupfiles = {file_adds % + > "HG: added {file}\n" }{file_mods % + > "HG: changed {file}\n" }{file_dels % + > "HG: removed {file}\n" }{if(files, "", + > "HG: no files changed\n")} + > > changeset = HG: this is customized commit template > {desc}\n\n > HG: Enter commit message. Lines beginning with 'HG:' are removed. > HG: {extramsg} > HG: -- > HG: user: {author} - > HG: branch '{branch}'\n{file_adds % - > "HG: added {file}\n" }{file_mods % - > "HG: changed {file}\n" }{file_dels % - > "HG: removed {file}\n" }{if(files, "", - > "HG: no files changed\n")} + > HG: branch '{branch}'\n{listupfiles} > EOF $ echo bbbb > file
--- a/tests/test-mq-subrepo-svn.t Sun Aug 10 23:09:23 2014 -0500 +++ b/tests/test-mq-subrepo-svn.t Mon Aug 11 11:24:05 2014 -0500 @@ -1,4 +1,4 @@ - $ "$TESTDIR/hghave" svn13 || exit 80 +#require svn13 $ echo "[extensions]" >> $HGRCPATH $ echo "mq=" >> $HGRCPATH
--- a/tests/test-mq-symlinks.t Sun Aug 10 23:09:23 2014 -0500 +++ b/tests/test-mq-symlinks.t Mon Aug 11 11:24:05 2014 -0500 @@ -1,4 +1,4 @@ - $ "$TESTDIR/hghave" symlink || exit 80 +#require symlink $ echo "[extensions]" >> $HGRCPATH $ echo "mq=" >> $HGRCPATH
--- a/tests/test-newcgi.t Sun Aug 10 23:09:23 2014 -0500 +++ b/tests/test-newcgi.t Mon Aug 11 11:24:05 2014 -0500 @@ -1,4 +1,4 @@ - $ "$TESTDIR/hghave" no-msys || exit 80 # MSYS will translate web paths as if they were file paths +#require no-msys # MSYS will translate web paths as if they were file paths This tests if CGI files from after d0db3462d568 but before d74fc8dec2b4 still work.
--- a/tests/test-newercgi.t Sun Aug 10 23:09:23 2014 -0500 +++ b/tests/test-newercgi.t Mon Aug 11 11:24:05 2014 -0500 @@ -1,4 +1,4 @@ - $ "$TESTDIR/hghave" no-msys || exit 80 # MSYS will translate web paths as if they were file paths +#require no-msys # MSYS will translate web paths as if they were file paths This is a rudimentary test of the CGI files as of d74fc8dec2b4.
--- a/tests/test-no-symlinks.t Sun Aug 10 23:09:23 2014 -0500 +++ b/tests/test-no-symlinks.t Mon Aug 11 11:24:05 2014 -0500 @@ -1,4 +1,4 @@ - $ "$TESTDIR/hghave" no-symlink || exit 80 +#require no-symlink # The following script was used to create the bundle: #
--- a/tests/test-obsolete.t Sun Aug 10 23:09:23 2014 -0500 +++ b/tests/test-obsolete.t Mon Aug 11 11:24:05 2014 -0500 @@ -2,6 +2,8 @@ > [phases] > # public changeset are not obsolete > publish=false + > [ui] + > logtemplate="{rev}:{node|short} ({phase}) [{tags} {bookmarks}] {desc|firstline}\n" > EOF $ mkcommit() { > echo "$1" > "$1" @@ -58,11 +60,7 @@ $ hg up null --quiet # having 0 as parent prevents it to be hidden $ hg tip - changeset: -1:000000000000 - tag: tip - user: - date: Thu Jan 01 00:00:00 1970 +0000 - + -1:000000000000 (public) [tip ] $ hg up --hidden tip --quiet $ cd .. @@ -125,59 +123,22 @@ Check that graphlog detect that a changeset is obsolete: $ hg log -G - @ changeset: 5:5601fb93a350 - | tag: tip - | parent: 1:7c3bad9141dc - | user: test - | date: Thu Jan 01 00:00:00 1970 +0000 - | summary: add new_3_c + @ 5:5601fb93a350 (draft) [tip ] add new_3_c | - o changeset: 1:7c3bad9141dc - | user: test - | date: Thu Jan 01 00:00:00 1970 +0000 - | summary: add b + o 1:7c3bad9141dc (draft) [ ] add b | - o changeset: 0:1f0dee641bb7 - user: test - date: Thu Jan 01 00:00:00 1970 +0000 - summary: add a + o 0:1f0dee641bb7 (draft) [ ] add a check that heads does not report them $ hg heads - changeset: 5:5601fb93a350 - tag: tip - parent: 1:7c3bad9141dc - user: test - date: Thu Jan 01 00:00:00 1970 +0000 - summary: add new_3_c - + 5:5601fb93a350 (draft) [tip ] add new_3_c $ hg heads --hidden - changeset: 5:5601fb93a350 - tag: tip - parent: 1:7c3bad9141dc - user: test - date: Thu Jan 01 00:00:00 1970 +0000 - summary: add new_3_c - - changeset: 4:ca819180edb9 - parent: 1:7c3bad9141dc - user: test - date: Thu Jan 01 00:00:00 1970 +0000 - summary: add new_2_c - - changeset: 3:cdbce2fbb163 - parent: 1:7c3bad9141dc - user: test - date: Thu Jan 01 00:00:00 1970 +0000 - summary: add new_c - - changeset: 2:245bde4270cd - user: test - date: Thu Jan 01 00:00:00 1970 +0000 - summary: add original_c - + 5:5601fb93a350 (draft) [tip ] add new_3_c + 4:ca819180edb9 (draft) [ ] add new_2_c + 3:cdbce2fbb163 (draft) [ ] add new_c + 2:245bde4270cd (draft) [ ] add original_c check that summary does not report them @@ -204,13 +165,7 @@ check that various commands work well with filtering $ hg tip - changeset: 5:5601fb93a350 - tag: tip - parent: 1:7c3bad9141dc - user: test - date: Thu Jan 01 00:00:00 1970 +0000 - summary: add new_3_c - + 5:5601fb93a350 (draft) [tip ] add new_3_c $ hg log -r 6 abort: unknown revision '6'! [255] @@ -222,27 +177,13 @@ $ hg --hidden phase --public 2 $ hg log -G - @ changeset: 5:5601fb93a350 - | tag: tip - | parent: 1:7c3bad9141dc - | user: test - | date: Thu Jan 01 00:00:00 1970 +0000 - | summary: add new_3_c + @ 5:5601fb93a350 (draft) [tip ] add new_3_c | - | o changeset: 2:245bde4270cd - |/ user: test - | date: Thu Jan 01 00:00:00 1970 +0000 - | summary: add original_c + | o 2:245bde4270cd (public) [ ] add original_c + |/ + o 1:7c3bad9141dc (public) [ ] add b | - o changeset: 1:7c3bad9141dc - | user: test - | date: Thu Jan 01 00:00:00 1970 +0000 - | summary: add b - | - o changeset: 0:1f0dee641bb7 - user: test - date: Thu Jan 01 00:00:00 1970 +0000 - summary: add a + o 0:1f0dee641bb7 (public) [ ] add a And that bumped changeset are detected @@ -253,13 +194,7 @@ the public changeset $ hg log --hidden -r 'bumped()' - changeset: 5:5601fb93a350 - tag: tip - parent: 1:7c3bad9141dc - user: test - date: Thu Jan 01 00:00:00 1970 +0000 - summary: add new_3_c - + 5:5601fb93a350 (draft) [tip ] add new_3_c And that we can't push bumped changeset @@ -289,27 +224,13 @@ $ hg debugobsolete -d '1338 0' --flags 1 `getid new_3_c` `getid n3w_3_c` $ hg log -r 'bumped()' $ hg log -G - @ changeset: 6:6f9641995072 - | tag: tip - | parent: 1:7c3bad9141dc - | user: test - | date: Thu Jan 01 00:00:00 1970 +0000 - | summary: add n3w_3_c + @ 6:6f9641995072 (draft) [tip ] add n3w_3_c | - | o changeset: 2:245bde4270cd - |/ user: test - | date: Thu Jan 01 00:00:00 1970 +0000 - | summary: add original_c + | o 2:245bde4270cd (public) [ ] add original_c + |/ + o 1:7c3bad9141dc (public) [ ] add b | - o changeset: 1:7c3bad9141dc - | user: test - | date: Thu Jan 01 00:00:00 1970 +0000 - | summary: add b - | - o changeset: 0:1f0dee641bb7 - user: test - date: Thu Jan 01 00:00:00 1970 +0000 - summary: add a + o 0:1f0dee641bb7 (public) [ ] add a @@ -328,28 +249,10 @@ $ cd tmpc $ hg incoming ../tmpb comparing with ../tmpb - changeset: 0:1f0dee641bb7 - user: test - date: Thu Jan 01 00:00:00 1970 +0000 - summary: add a - - changeset: 1:7c3bad9141dc - user: test - date: Thu Jan 01 00:00:00 1970 +0000 - summary: add b - - changeset: 2:245bde4270cd - user: test - date: Thu Jan 01 00:00:00 1970 +0000 - summary: add original_c - - changeset: 6:6f9641995072 - tag: tip - parent: 1:7c3bad9141dc - user: test - date: Thu Jan 01 00:00:00 1970 +0000 - summary: add n3w_3_c - + 0:1f0dee641bb7 (public) [ ] add a + 1:7c3bad9141dc (public) [ ] add b + 2:245bde4270cd (public) [ ] add original_c + 6:6f9641995072 (draft) [tip ] add n3w_3_c Try to pull markers (extinct changeset are excluded but marker are pushed) @@ -414,6 +317,7 @@ $ hg init empty $ hg --config extensions.debugkeys=debugkeys.py -R empty push tmpd pushing to tmpd + listkeys phases no changes found listkeys phases listkeys bookmarks @@ -426,45 +330,19 @@ updating to branch default 3 files updated, 0 files merged, 0 files removed, 0 files unresolved $ hg -R clone-dest log -G --hidden - @ changeset: 6:6f9641995072 - | tag: tip - | parent: 1:7c3bad9141dc - | user: test - | date: Thu Jan 01 00:00:00 1970 +0000 - | summary: add n3w_3_c - | - | x changeset: 5:5601fb93a350 - |/ parent: 1:7c3bad9141dc - | user: test - | date: Thu Jan 01 00:00:00 1970 +0000 - | summary: add new_3_c - | - | x changeset: 4:ca819180edb9 - |/ parent: 1:7c3bad9141dc - | user: test - | date: Thu Jan 01 00:00:00 1970 +0000 - | summary: add new_2_c + @ 6:6f9641995072 (draft) [tip ] add n3w_3_c | - | x changeset: 3:cdbce2fbb163 - |/ parent: 1:7c3bad9141dc - | user: test - | date: Thu Jan 01 00:00:00 1970 +0000 - | summary: add new_c + | x 5:5601fb93a350 (draft) [ ] add new_3_c + |/ + | x 4:ca819180edb9 (draft) [ ] add new_2_c + |/ + | x 3:cdbce2fbb163 (draft) [ ] add new_c + |/ + | o 2:245bde4270cd (public) [ ] add original_c + |/ + o 1:7c3bad9141dc (public) [ ] add b | - | o changeset: 2:245bde4270cd - |/ user: test - | date: Thu Jan 01 00:00:00 1970 +0000 - | summary: add original_c - | - o changeset: 1:7c3bad9141dc - | user: test - | date: Thu Jan 01 00:00:00 1970 +0000 - | summary: add b - | - o changeset: 0:1f0dee641bb7 - user: test - date: Thu Jan 01 00:00:00 1970 +0000 - summary: add a + o 0:1f0dee641bb7 (public) [ ] add a $ hg -R clone-dest debugobsolete 245bde4270cd1072a27757984f9cda8ba26f08ca cdbce2fbb16313928851e97e0d85413f3f7eb77f C {'date': '56 12', 'user': 'test'} @@ -519,27 +397,13 @@ $ hg log -G - o changeset: 3:6f9641995072 - | tag: tip - | parent: 1:7c3bad9141dc - | user: test - | date: Thu Jan 01 00:00:00 1970 +0000 - | summary: add n3w_3_c + o 3:6f9641995072 (draft) [tip ] add n3w_3_c | - | o changeset: 2:245bde4270cd - |/ user: test - | date: Thu Jan 01 00:00:00 1970 +0000 - | summary: add original_c + | o 2:245bde4270cd (public) [ ] add original_c + |/ + o 1:7c3bad9141dc (public) [ ] add b | - o changeset: 1:7c3bad9141dc - | user: test - | date: Thu Jan 01 00:00:00 1970 +0000 - | summary: add b - | - o changeset: 0:1f0dee641bb7 - user: test - date: Thu Jan 01 00:00:00 1970 +0000 - summary: add a + o 0:1f0dee641bb7 (public) [ ] add a $ hg up 'desc("n3w_3_c")' 3 files updated, 0 files merged, 0 files removed, 0 files unresolved @@ -547,38 +411,17 @@ $ mkcommit original_e $ hg debugobsolete `getid original_d` -d '0 0' $ hg log -r 'obsolete()' - changeset: 4:94b33453f93b - user: test - date: Thu Jan 01 00:00:00 1970 +0000 - summary: add original_d - + 4:94b33453f93b (draft) [ ] add original_d $ hg log -G -r '::unstable()' - @ changeset: 5:cda648ca50f5 - | tag: tip - | user: test - | date: Thu Jan 01 00:00:00 1970 +0000 - | summary: add original_e + @ 5:cda648ca50f5 (draft) [tip ] add original_e + | + x 4:94b33453f93b (draft) [ ] add original_d | - x changeset: 4:94b33453f93b - | user: test - | date: Thu Jan 01 00:00:00 1970 +0000 - | summary: add original_d + o 3:6f9641995072 (draft) [ ] add n3w_3_c | - o changeset: 3:6f9641995072 - | parent: 1:7c3bad9141dc - | user: test - | date: Thu Jan 01 00:00:00 1970 +0000 - | summary: add n3w_3_c + o 1:7c3bad9141dc (public) [ ] add b | - o changeset: 1:7c3bad9141dc - | user: test - | date: Thu Jan 01 00:00:00 1970 +0000 - | summary: add b - | - o changeset: 0:1f0dee641bb7 - user: test - date: Thu Jan 01 00:00:00 1970 +0000 - summary: add a + o 0:1f0dee641bb7 (public) [ ] add a refuse to push obsolete changeset @@ -607,38 +450,12 @@ $ hg out ../tmpf comparing with ../tmpf searching for changes - changeset: 0:1f0dee641bb7 - user: test - date: Thu Jan 01 00:00:00 1970 +0000 - summary: add a - - changeset: 1:7c3bad9141dc - user: test - date: Thu Jan 01 00:00:00 1970 +0000 - summary: add b - - changeset: 2:245bde4270cd - user: test - date: Thu Jan 01 00:00:00 1970 +0000 - summary: add original_c - - changeset: 3:6f9641995072 - parent: 1:7c3bad9141dc - user: test - date: Thu Jan 01 00:00:00 1970 +0000 - summary: add n3w_3_c - - changeset: 4:94b33453f93b - user: test - date: Thu Jan 01 00:00:00 1970 +0000 - summary: add original_d - - changeset: 5:cda648ca50f5 - tag: tip - user: test - date: Thu Jan 01 00:00:00 1970 +0000 - summary: add original_e - + 0:1f0dee641bb7 (public) [ ] add a + 1:7c3bad9141dc (public) [ ] add b + 2:245bde4270cd (public) [ ] add original_c + 3:6f9641995072 (draft) [ ] add n3w_3_c + 4:94b33453f93b (draft) [ ] add original_d + 5:cda648ca50f5 (draft) [tip ] add original_e $ hg push ../tmpf -f # -f because be push unstable too pushing to ../tmpf searching for changes @@ -658,37 +475,17 @@ Do not warn about new head when the new head is a successors of a remote one $ hg log -G - @ changeset: 5:cda648ca50f5 - | tag: tip - | user: test - | date: Thu Jan 01 00:00:00 1970 +0000 - | summary: add original_e + @ 5:cda648ca50f5 (draft) [tip ] add original_e | - x changeset: 4:94b33453f93b - | user: test - | date: Thu Jan 01 00:00:00 1970 +0000 - | summary: add original_d + x 4:94b33453f93b (draft) [ ] add original_d + | + o 3:6f9641995072 (draft) [ ] add n3w_3_c | - o changeset: 3:6f9641995072 - | parent: 1:7c3bad9141dc - | user: test - | date: Thu Jan 01 00:00:00 1970 +0000 - | summary: add n3w_3_c + | o 2:245bde4270cd (public) [ ] add original_c + |/ + o 1:7c3bad9141dc (public) [ ] add b | - | o changeset: 2:245bde4270cd - |/ user: test - | date: Thu Jan 01 00:00:00 1970 +0000 - | summary: add original_c - | - o changeset: 1:7c3bad9141dc - | user: test - | date: Thu Jan 01 00:00:00 1970 +0000 - | summary: add b - | - o changeset: 0:1f0dee641bb7 - user: test - date: Thu Jan 01 00:00:00 1970 +0000 - summary: add a + o 0:1f0dee641bb7 (public) [ ] add a $ hg up -q 'desc(n3w_3_c)' $ mkcommit obsolete_e @@ -697,13 +494,7 @@ $ hg outgoing ../tmpf # parasite hg outgoing testin comparing with ../tmpf searching for changes - changeset: 6:3de5eca88c00 - tag: tip - parent: 3:6f9641995072 - user: test - date: Thu Jan 01 00:00:00 1970 +0000 - summary: add obsolete_e - + 6:3de5eca88c00 (draft) [tip ] add obsolete_e $ hg push ../tmpf pushing to ../tmpf searching for changes @@ -773,13 +564,7 @@ $ echo "obs=!" >> $HGRCPATH $ hg log -r tip obsolete feature not enabled but 68 markers found! - changeset: 68:c15e9edfca13 - tag: tip - parent: 7:50c51b361e60 - user: test - date: Thu Jan 01 00:00:00 1970 +0000 - summary: add celestine - + 68:c15e9edfca13 (draft) [tip ] add celestine reenable for later test @@ -805,40 +590,19 @@ $ hg ci --amend $ cd ../other-issue3805 $ hg log -G - @ changeset: 0:193e9254ce7e - tag: tip - user: test - date: Thu Jan 01 00:00:00 1970 +0000 - summary: A + @ 0:193e9254ce7e (draft) [tip ] A $ hg log -G -R ../repo-issue3805 - @ changeset: 2:3816541e5485 - tag: tip - parent: -1:000000000000 - user: test - date: Thu Jan 01 00:00:00 1970 +0000 - summary: A + @ 2:3816541e5485 (draft) [tip ] A $ hg incoming comparing with $TESTTMP/tmpe/repo-issue3805 (glob) searching for changes - changeset: 2:3816541e5485 - tag: tip - parent: -1:000000000000 - user: test - date: Thu Jan 01 00:00:00 1970 +0000 - summary: A - + 2:3816541e5485 (draft) [tip ] A $ hg incoming --bundle ../issue3805.hg comparing with $TESTTMP/tmpe/repo-issue3805 (glob) searching for changes - changeset: 2:3816541e5485 - tag: tip - parent: -1:000000000000 - user: test - date: Thu Jan 01 00:00:00 1970 +0000 - summary: A - + 2:3816541e5485 (draft) [tip ] A $ hg outgoing comparing with $TESTTMP/tmpe/repo-issue3805 (glob) searching for changes @@ -853,13 +617,7 @@ $ hg incoming http://localhost:$HGPORT comparing with http://localhost:$HGPORT/ searching for changes - changeset: 1:3816541e5485 - tag: tip - parent: -1:000000000000 - user: test - date: Thu Jan 01 00:00:00 1970 +0000 - summary: A - + 1:3816541e5485 (public) [tip ] A $ hg outgoing http://localhost:$HGPORT comparing with http://localhost:$HGPORT/ searching for changes @@ -894,18 +652,9 @@ $ hg tag -l visible -r 0 --hidden $ hg log -G - @ changeset: 2:3816541e5485 - tag: tip - parent: -1:000000000000 - user: test - date: Thu Jan 01 00:00:00 1970 +0000 - summary: A + @ 2:3816541e5485 (draft) [tip ] A - x changeset: 0:193e9254ce7e - tag: visible - user: test - date: Thu Jan 01 00:00:00 1970 +0000 - summary: A + x 0:193e9254ce7e (draft) [visible ] A Test that removing a local tag does not cause some commands to fail
--- a/tests/test-oldcgi.t Sun Aug 10 23:09:23 2014 -0500 +++ b/tests/test-oldcgi.t Mon Aug 11 11:24:05 2014 -0500 @@ -1,4 +1,4 @@ - $ "$TESTDIR/hghave" no-msys || exit 80 # MSYS will translate web paths as if they were file paths +#require no-msys # MSYS will translate web paths as if they were file paths This tests if CGI files from before d0db3462d568 still work.
--- a/tests/test-patchbomb.t Sun Aug 10 23:09:23 2014 -0500 +++ b/tests/test-patchbomb.t Mon Aug 11 11:24:05 2014 -0500 @@ -8,6 +8,21 @@ --===+[0-9]+=+--$ -> --===*=-- (glob) --===+[0-9]+=+$ -> --===*= (glob) + $ cat > prune-blank-after-boundary.py <<EOF + > import sys + > skipblank = False + > trim = lambda x: x.strip(' \r\n') + > for l in sys.stdin: + > if trim(l).endswith('=--') or trim(l).endswith('=='): + > skipblank = True + > print l, + > continue + > if not trim(l) and skipblank: + > continue + > skipblank = False + > print l, + > EOF + $ FILTERBOUNDARY="python `pwd`/prune-blank-after-boundary.py" $ echo "[extensions]" >> $HGRCPATH $ echo "patchbomb=" >> $HGRCPATH @@ -214,7 +229,7 @@ test bundle and description: $ hg email --date '1970-1-1 0:3' -n -f quux -t foo \ - > -c bar -s test -r tip -b --desc description + > -c bar -s test -r tip -b --desc description | $FILTERBOUNDARY searching for changes 1 changesets found @@ -689,7 +704,7 @@ test inline for single patch: - $ hg email --date '1970-1-1 0:1' -n -f quux -t foo -c bar -s test -i -r 2 + $ hg email --date '1970-1-1 0:1' -n -f quux -t foo -c bar -s test -i -r 2 | $FILTERBOUNDARY this patch series consists of 1 patches. @@ -732,7 +747,7 @@ test inline for single patch (quoted-printable): - $ hg email --date '1970-1-1 0:1' -n -f quux -t foo -c bar -s test -i -r 4 + $ hg email --date '1970-1-1 0:1' -n -f quux -t foo -c bar -s test -i -r 4 | $FILTERBOUNDARY this patch series consists of 1 patches. @@ -791,7 +806,7 @@ test inline for multiple patches: $ hg email --date '1970-1-1 0:1' -n -f quux -t foo -c bar -s test -i \ - > -r 0:1 -r 4 + > -r 0:1 -r 4 | $FILTERBOUNDARY this patch series consists of 3 patches. @@ -943,7 +958,7 @@ --===*=-- (glob) test attach for single patch: - $ hg email --date '1970-1-1 0:1' -n -f quux -t foo -c bar -s test -a -r 2 + $ hg email --date '1970-1-1 0:1' -n -f quux -t foo -c bar -s test -a -r 2 | $FILTERBOUNDARY this patch series consists of 1 patches. @@ -994,7 +1009,7 @@ --===*=-- (glob) test attach for single patch (quoted-printable): - $ hg email --date '1970-1-1 0:1' -n -f quux -t foo -c bar -s test -a -r 4 + $ hg email --date '1970-1-1 0:1' -n -f quux -t foo -c bar -s test -a -r 4 | $FILTERBOUNDARY this patch series consists of 1 patches. @@ -1061,7 +1076,7 @@ --===*=-- (glob) test attach and body for single patch: - $ hg email --date '1970-1-1 0:1' -n -f quux -t foo -c bar -s test -a --body -r 2 + $ hg email --date '1970-1-1 0:1' -n -f quux -t foo -c bar -s test -a --body -r 2 | $FILTERBOUNDARY this patch series consists of 1 patches. @@ -1123,7 +1138,7 @@ test attach for multiple patches: $ hg email --date '1970-1-1 0:1' -n -f quux -t foo -c bar -s test -a \ - > -r 0:1 -r 4 + > -r 0:1 -r 4 | $FILTERBOUNDARY this patch series consists of 3 patches. @@ -1579,7 +1594,8 @@ $ hg tag -r2 two two.diff test inline for single named patch: - $ hg email --date '1970-1-1 0:1' -n -f quux -t foo -c bar -s test -i -r 2 + $ hg email --date '1970-1-1 0:1' -n -f quux -t foo -c bar -s test -i \ + > -r 2 | $FILTERBOUNDARY this patch series consists of 1 patches. @@ -1621,7 +1637,8 @@ --===*=-- (glob) test inline for multiple named/unnamed patches: - $ hg email --date '1970-1-1 0:1' -n -f quux -t foo -c bar -s test -i -r 0:1 + $ hg email --date '1970-1-1 0:1' -n -f quux -t foo -c bar -s test -i \ + > -r 0:1 | $FILTERBOUNDARY this patch series consists of 2 patches. @@ -1927,7 +1944,7 @@ $ hg up -qr1 $ echo dirt > a $ hg email --date '1970-1-1 0:1' -n --flag fooFlag -f quux -t foo -c bar -s test \ - > -r 2 + > -r 2 | $FILTERBOUNDARY this patch series consists of 1 patches.
--- a/tests/test-permissions.t Sun Aug 10 23:09:23 2014 -0500 +++ b/tests/test-permissions.t Mon Aug 11 11:24:05 2014 -0500 @@ -1,4 +1,4 @@ -#if unix-permissions no-root +#require unix-permissions no-root $ hg init t $ cd t @@ -70,5 +70,3 @@ $ chmod +rx dir $ cd .. - -#endif
--- a/tests/test-phases-exchange.t Sun Aug 10 23:09:23 2014 -0500 +++ b/tests/test-phases-exchange.t Mon Aug 11 11:24:05 2014 -0500 @@ -1,4 +1,4 @@ - $ "$TESTDIR/hghave" killdaemons || exit 80 +#require killdaemons $ hgph() { hg log -G --template "{rev} {phase} {desc} - {node|short}\n" $*; }
--- a/tests/test-pull-http.t Sun Aug 10 23:09:23 2014 -0500 +++ b/tests/test-pull-http.t Mon Aug 11 11:24:05 2014 -0500 @@ -1,4 +1,4 @@ - $ "$TESTDIR/hghave" killdaemons || exit 80 +#require killdaemons $ hg init test $ cd test
--- a/tests/test-pull-permission.t Sun Aug 10 23:09:23 2014 -0500 +++ b/tests/test-pull-permission.t Mon Aug 11 11:24:05 2014 -0500 @@ -1,4 +1,4 @@ -#if unix-permissions no-root +#require unix-permissions no-root $ hg init a $ cd a @@ -30,5 +30,3 @@ 1 files, 1 changesets, 1 total revisions $ cd .. - -#endif
--- a/tests/test-pull.t Sun Aug 10 23:09:23 2014 -0500 +++ b/tests/test-pull.t Mon Aug 11 11:24:05 2014 -0500 @@ -1,4 +1,4 @@ - $ "$TESTDIR/hghave" serve || exit 80 +#require serve $ hg init test $ cd test
--- a/tests/test-push-cgi.t Sun Aug 10 23:09:23 2014 -0500 +++ b/tests/test-push-cgi.t Mon Aug 11 11:24:05 2014 -0500 @@ -1,4 +1,4 @@ - $ "$TESTDIR/hghave" no-msys || exit 80 # MSYS will translate web paths as if they were file paths +#require no-msys # MSYS will translate web paths as if they were file paths This is a test of the push wire protocol over CGI-based hgweb.
--- a/tests/test-push-http.t Sun Aug 10 23:09:23 2014 -0500 +++ b/tests/test-push-http.t Mon Aug 11 11:24:05 2014 -0500 @@ -1,4 +1,4 @@ - $ "$TESTDIR/hghave" killdaemons || exit 80 +#require killdaemons $ hg init test $ cd test
--- a/tests/test-push-warn.t Sun Aug 10 23:09:23 2014 -0500 +++ b/tests/test-push-warn.t Mon Aug 11 11:24:05 2014 -0500 @@ -35,6 +35,7 @@ searching: 2 queries query 2; still undecided: 1, sample size is: 1 2 total queries + listing keys for "phases" listing keys for "bookmarks" remote has heads on branch 'default' that are not known locally: 1c9246a22a0a new remote heads on branch 'default':
--- a/tests/test-relink.t Sun Aug 10 23:09:23 2014 -0500 +++ b/tests/test-relink.t Mon Aug 11 11:24:05 2014 -0500 @@ -1,4 +1,4 @@ - $ "$TESTDIR/hghave" hardlink || exit 80 +#require hardlink $ echo "[extensions]" >> $HGRCPATH $ echo "relink=" >> $HGRCPATH
--- a/tests/test-repair-strip.t Sun Aug 10 23:09:23 2014 -0500 +++ b/tests/test-repair-strip.t Mon Aug 11 11:24:05 2014 -0500 @@ -1,4 +1,4 @@ -#if unix-permissions no-root +#require unix-permissions no-root $ echo "[extensions]" >> $HGRCPATH $ echo "mq=">> $HGRCPATH @@ -130,5 +130,3 @@ 2 files, 2 changesets, 2 total revisions $ cd .. - -#endif
--- a/tests/test-revert-flags.t Sun Aug 10 23:09:23 2014 -0500 +++ b/tests/test-revert-flags.t Mon Aug 11 11:24:05 2014 -0500 @@ -1,4 +1,4 @@ - $ "$TESTDIR/hghave" execbit || exit 80 +#require execbit $ hg init repo $ cd repo
--- a/tests/test-revert.t Sun Aug 10 23:09:23 2014 -0500 +++ b/tests/test-revert.t Mon Aug 11 11:24:05 2014 -0500 @@ -14,6 +14,9 @@ [255] $ hg revert --all +Introduce some changes and revert them +-------------------------------------- + $ echo 123 > b should show b unknown @@ -42,6 +45,9 @@ M c A b R a + +revert removal of a file + $ hg revert a should show b added, copy saved, and c modified @@ -49,6 +55,9 @@ $ hg status M c A b + +revert addition of a file + $ hg revert b should show b unknown, and c modified @@ -56,12 +65,19 @@ $ hg status M c ? b + +revert modification of a file (--no-backup) + $ hg revert --no-backup c should show unknown: b $ hg status ? b + +revert deletion (! status) of a added file +------------------------------------------ + $ hg add b should show b added @@ -89,26 +105,30 @@ c e -should verbosely save backup to e.orig +Test creation of backup (.orig) files +------------------------------------- $ echo z > e $ hg revert --all -v saving current version of e as e.orig reverting e -should say no changes needed +revert on clean file (no change) +-------------------------------- $ hg revert a no changes needed to a -should say file not managed +revert on an untracked file +--------------------------- $ echo q > q $ hg revert q file not managed: q $ rm q -should say file not found +revert on file that does not exists +----------------------------------- $ hg revert notfound notfound: no such file in rev 334a9e57682c @@ -122,21 +142,26 @@ A z ? e.orig -should add a, remove d, forget z +revert to another revision (--rev) +---------------------------------- $ hg revert --all -r0 adding a removing d forgetting z -should forget a, undelete d +revert explicitly to parent (--rev) +----------------------------------- $ hg revert --all -rtip forgetting a undeleting d $ rm a *.orig -should silently add a +revert to another revision (--rev) and exact match +-------------------------------------------------- + +exact match are more silent $ hg revert -r0 a $ hg st a @@ -153,6 +178,10 @@ $ hg update -C 1 files updated, 0 files merged, 0 files removed, 0 files unresolved + +revert of exec bit +------------------ + #if execbit $ chmod +x c $ hg revert --all @@ -180,6 +209,7 @@ Issue241: update and revert produces inconsistent repositories +-------------------------------------------------------------- $ hg init a $ cd a @@ -193,20 +223,23 @@ $ mkdir b $ echo b > b/b -should fail - no arguments +call `hg revert` with no file specified +--------------------------------------- $ hg revert -rtip abort: no files or directories specified (use --all to revert all files, or 'hg update 1' to update) [255] -should succeed +call `hg revert` with --all +--------------------------- $ hg revert --all -rtip reverting a Issue332: confusing message when reverting directory +---------------------------------------------------- $ hg ci -A -m b adding b/b @@ -224,6 +257,7 @@ reverting a rename target should revert the source +-------------------------------------------------- $ hg mv a newa $ hg revert newa @@ -258,6 +292,7 @@ $ hg rm removed ignoreddir/removed should revert ignored* and undelete *removed +-------------------------------------------- $ hg revert -a --no-backup reverting ignored @@ -271,10 +306,14 @@ $ hg rm removed should silently revert the named files +-------------------------------------- $ hg revert --no-backup ignored removed $ hg st -mardi +Reverting copy (issue3920) +-------------------------- + someone set up us the copies $ rm .hgignore @@ -300,8 +339,9 @@ R ignored Test revert of a file added by one side of the merge +==================================================== -(remove any pending change) +remove any pending change $ hg revert --all forgetting allyour @@ -309,7 +349,7 @@ undeleting ignored $ hg purge --all --config extensions.purge= -(Adds a new commit) +Adds a new commit $ echo foo > newadd $ hg add newadd @@ -317,7 +357,7 @@ created new head -(merge it with the other head) +merge it with the other head $ hg merge # merge 1 into 2 2 files updated, 0 files merged, 1 files removed, 0 files unresolved @@ -331,7 +371,7 @@ commit: 2 modified, 1 removed (merge) update: (current) -(clarifies who added what) +clarifies who added what $ hg status M allyour @@ -344,7 +384,8 @@ A base R ignored -(revert file added by p1() to p1() state) +revert file added by p1() to p1() state +----------------------------------------- $ hg revert -r 'p1()' 'glob:newad?' $ hg status @@ -352,7 +393,8 @@ M base R ignored -(revert file added by p1() to p2() state) +revert file added by p1() to p2() state +------------------------------------------ $ hg revert -r 'p2()' 'glob:newad?' removing newadd @@ -362,7 +404,8 @@ R ignored R newadd -(revert file added by p2() to p2() state) +revert file added by p2() to p2() state +------------------------------------------ $ hg revert -r 'p2()' 'glob:allyou?' $ hg status @@ -371,7 +414,8 @@ R ignored R newadd -(revert file added by p2() to p1() state) +revert file added by p2() to p1() state +------------------------------------------ $ hg revert -r 'p1()' 'glob:allyou?' removing allyour
--- a/tests/test-run-tests.t Sun Aug 10 23:09:23 2014 -0500 +++ b/tests/test-run-tests.t Mon Aug 11 11:24:05 2014 -0500 @@ -13,6 +13,8 @@ $ cat > test-success.t << EOF > $ echo babar > babar + > $ echo xyzzy + > xyzzy > EOF $ $TESTDIR/run-tests.py --with-hg=`which hg` @@ -25,16 +27,20 @@ $ cat > test-failure.t << EOF > $ echo babar > rataxes + > This is a noop statement so that + > this test is still more bytes than success. > EOF $ $TESTDIR/run-tests.py --with-hg=`which hg` --- $TESTTMP/test-failure.t +++ $TESTTMP/test-failure.t.err - @@ -1,2 +1,2 @@ + @@ -1,4 +1,4 @@ $ echo babar - rataxes + babar + This is a noop statement so that + this test is still more bytes than success. ERROR: test-failure.t output changed !. @@ -42,6 +48,39 @@ # Ran 2 tests, 0 skipped, 0 warned, 1 failed. python hash seed: * (glob) [1] +test --xunit support + $ $TESTDIR/run-tests.py --with-hg=`which hg` --xunit=xunit.xml + + --- $TESTTMP/test-failure.t + +++ $TESTTMP/test-failure.t.err + @@ -1,4 +1,4 @@ + $ echo babar + - rataxes + + babar + This is a noop statement so that + this test is still more bytes than success. + + ERROR: test-failure.t output changed + !. + Failed test-failure.t: output changed + # Ran 2 tests, 0 skipped, 0 warned, 1 failed. + python hash seed: * (glob) + [1] + $ cat xunit.xml + <?xml version="1.0" encoding="utf-8"?> + <testsuite errors="0" failures="1" name="run-tests" skipped="0" tests="2"> + <testcase name="test-success.t" time="*"/> (glob) + <testcase name="test-failure.t" time="*"> (glob) + <![CDATA[--- $TESTTMP/test-failure.t + +++ $TESTTMP/test-failure.t.err + @@ -1,4 +1,4 @@ + $ echo babar + - rataxes + + babar + This is a noop statement so that + this test is still more bytes than success. + ]]> </testcase> + </testsuite> test for --retest ==================== @@ -50,15 +89,17 @@ --- $TESTTMP/test-failure.t +++ $TESTTMP/test-failure.t.err - @@ -1,2 +1,2 @@ + @@ -1,4 +1,4 @@ $ echo babar - rataxes + babar + This is a noop statement so that + this test is still more bytes than success. ERROR: test-failure.t output changed ! Failed test-failure.t: output changed - # Ran 1 tests, 1 skipped, 0 warned, 1 failed. + # Ran 2 tests, 1 skipped, 0 warned, 1 failed. python hash seed: * (glob) [1] @@ -71,16 +112,23 @@ . # Ran 1 tests, 0 skipped, 0 warned, 0 failed. +success w/ keyword + $ $TESTDIR/run-tests.py --with-hg=`which hg` -k xyzzy + i. + # Ran 1 tests, 1 skipped, 0 warned, 0 failed. + failed $ $TESTDIR/run-tests.py --with-hg=`which hg` test-failure.t --- $TESTTMP/test-failure.t +++ $TESTTMP/test-failure.t.err - @@ -1,2 +1,2 @@ + @@ -1,4 +1,4 @@ $ echo babar - rataxes + babar + This is a noop statement so that + this test is still more bytes than success. ERROR: test-failure.t output changed ! @@ -89,6 +137,25 @@ python hash seed: * (glob) [1] +failure w/ keyword + $ $TESTDIR/run-tests.py --with-hg=`which hg` -k rataxes + i + --- $TESTTMP/test-failure.t + +++ $TESTTMP/test-failure.t.err + @@ -1,4 +1,4 @@ + $ echo babar + - rataxes + + babar + This is a noop statement so that + this test is still more bytes than success. + + ERROR: test-failure.t output changed + ! + Failed test-failure.t: output changed + # Ran 1 tests, 1 skipped, 0 warned, 1 failed. + python hash seed: * (glob) + [1] + Running In Debug Mode ====================== @@ -97,14 +164,18 @@ SALT* 0 0 (glob) + echo babar babar - + echo SALT* 2 0 (glob) - SALT* 2 0 (glob) + + echo SALT* 4 0 (glob) + SALT* 4 0 (glob) .+ echo SALT* 0 0 (glob) SALT* 0 0 (glob) + echo babar babar + echo SALT* 2 0 (glob) SALT* 2 0 (glob) + + echo xyzzy + xyzzy + + echo SALT* 4 0 (glob) + SALT* 4 0 (glob) . # Ran 2 tests, 0 skipped, 0 warned, 0 failed. @@ -118,19 +189,23 @@ --- $TESTTMP/test-failure*.t (glob) +++ $TESTTMP/test-failure*.t.err (glob) - @@ -1,2 +1,2 @@ + @@ -1,4 +1,4 @@ $ echo babar - rataxes + babar + This is a noop statement so that + this test is still more bytes than success. ERROR: test-failure*.t output changed (glob) ! --- $TESTTMP/test-failure*.t (glob) +++ $TESTTMP/test-failure*.t.err (glob) - @@ -1,2 +1,2 @@ + @@ -1,4 +1,4 @@ $ echo babar - rataxes + babar + This is a noop statement so that + this test is still more bytes than success. ERROR: test-failure*.t output changed (glob) ! @@ -156,10 +231,12 @@ --- $TESTTMP/test-failure.t +++ $TESTTMP/test-failure.t.err - @@ -1,2 +1,2 @@ + @@ -1,4 +1,4 @@ $ echo babar - rataxes + babar + This is a noop statement so that + this test is still more bytes than success. Accept this change? [n] ERROR: test-failure.t output changed !. @@ -171,6 +248,8 @@ $ cat test-failure.t $ echo babar rataxes + This is a noop statement so that + this test is still more bytes than success. Accept the fix @@ -178,16 +257,20 @@ --- $TESTTMP/test-failure.t +++ $TESTTMP/test-failure.t.err - @@ -1,2 +1,2 @@ + @@ -1,4 +1,4 @@ $ echo babar - rataxes + babar + This is a noop statement so that + this test is still more bytes than success. Accept this change? [n] .. # Ran 2 tests, 0 skipped, 0 warned, 0 failed. $ cat test-failure.t $ echo babar babar + This is a noop statement so that + this test is still more bytes than success. (reinstall) $ mv backup test-failure.t @@ -201,3 +284,64 @@ # Ran 2 tests, 0 skipped, 0 warned, 1 failed. python hash seed: * (glob) [1] + +test for --time +================== + + $ $TESTDIR/run-tests.py --with-hg=`which hg` test-success.t --time + . + # Ran 1 tests, 0 skipped, 0 warned, 0 failed. + # Producing time report + cuser csys real Test + \s*[\d\.]{5} \s*[\d\.]{5} \s*[\d\.]{5} test-success.t (re) + +test for --time with --job enabled +==================================== + + $ $TESTDIR/run-tests.py --with-hg=`which hg` test-success.t --time --jobs 2 + . + # Ran 1 tests, 0 skipped, 0 warned, 0 failed. + # Producing time report + cuser csys real Test + \s*[\d\.]{5} \s*[\d\.]{5} \s*[\d\.]{5} test-success.t (re) + +Skips +================ + $ cat > test-skip.t <<EOF + > $ echo xyzzy + > #require false + > EOF + $ $TESTDIR/run-tests.py --with-hg=`which hg` --nodiff + !.s + Skipped test-skip.t: irrelevant + Failed test-failure.t: output changed + # Ran 2 tests, 1 skipped, 0 warned, 1 failed. + python hash seed: * (glob) + [1] + + $ $TESTDIR/run-tests.py --with-hg=`which hg` --keyword xyzzy + i.s + Skipped test-skip.t: irrelevant + # Ran 1 tests, 2 skipped, 0 warned, 0 failed. + +Skips with xml + $ $TESTDIR/run-tests.py --with-hg=`which hg` --keyword xyzzy \ + > --xunit=xunit.xml + i.s + Skipped test-skip.t: irrelevant + # Ran 1 tests, 2 skipped, 0 warned, 0 failed. + $ cat xunit.xml + <?xml version="1.0" encoding="utf-8"?> + <testsuite errors="0" failures="0" name="run-tests" skipped="2" tests="1"> + <testcase name="test-success.t" time="*"/> (glob) + </testsuite> + +Missing skips or blacklisted skips don't count as executed: + $ echo test-failure.t > blacklist + $ $TESTDIR/run-tests.py --with-hg=`which hg` --blacklist=blacklist \ + > test-failure.t test-bogus.t + ss + Skipped test-bogus.t: Doesn't exist + Skipped test-failure.t: blacklisted + # Ran 0 tests, 2 skipped, 0 warned, 0 failed. +
--- a/tests/test-schemes.t Sun Aug 10 23:09:23 2014 -0500 +++ b/tests/test-schemes.t Mon Aug 11 11:24:05 2014 -0500 @@ -1,4 +1,4 @@ - $ "$TESTDIR/hghave" serve || exit 80 +#require serve $ cat <<EOF >> $HGRCPATH > [extensions]
--- a/tests/test-serve.t Sun Aug 10 23:09:23 2014 -0500 +++ b/tests/test-serve.t Mon Aug 11 11:24:05 2014 -0500 @@ -1,4 +1,4 @@ - $ "$TESTDIR/hghave" serve || exit 80 +#require serve $ hgserve() > {
--- a/tests/test-share.t Sun Aug 10 23:09:23 2014 -0500 +++ b/tests/test-share.t Mon Aug 11 11:24:05 2014 -0500 @@ -1,4 +1,4 @@ - $ "$TESTDIR/hghave" killdaemons || exit 80 +#require killdaemons $ echo "[extensions]" >> $HGRCPATH $ echo "share = " >> $HGRCPATH
--- a/tests/test-simplemerge.py Sun Aug 10 23:09:23 2014 -0500 +++ b/tests/test-simplemerge.py Mon Aug 11 11:24:05 2014 -0500 @@ -320,66 +320,6 @@ self.log(''.join(ml)) self.assertEquals(ml, MERGED_RESULT) - def test_minimal_conflicts_common(self): - """Reprocessing""" - base_text = ("a\n" * 20).splitlines(True) - this_text = ("a\n"*10+"b\n" * 10).splitlines(True) - other_text = ("a\n"*10+"c\n"+"b\n" * 8 + "c\n").splitlines(True) - m3 = Merge3(base_text, other_text, this_text) - m_lines = m3.merge_lines('OTHER', 'THIS', reprocess=True) - merged_text = "".join(list(m_lines)) - optimal_text = ("a\n" * 10 + "<<<<<<< OTHER\nc\n=======\n" - + ">>>>>>> THIS\n" - + 8* "b\n" + "<<<<<<< OTHER\nc\n=======\n" - + 2* "b\n" + ">>>>>>> THIS\n") - self.assertEquals(optimal_text, merged_text) - - def test_minimal_conflicts_unique(self): - def add_newline(s): - """Add a newline to each entry in the string""" - return [(x+'\n') for x in s] - - base_text = add_newline("abcdefghijklm") - this_text = add_newline("abcdefghijklmNOPQRSTUVWXYZ") - other_text = add_newline("abcdefghijklm1OPQRSTUVWXY2") - m3 = Merge3(base_text, other_text, this_text) - m_lines = m3.merge_lines('OTHER', 'THIS', reprocess=True) - merged_text = "".join(list(m_lines)) - optimal_text = ''.join(add_newline("abcdefghijklm") - + ["<<<<<<< OTHER\n1\n=======\nN\n>>>>>>> THIS\n"] - + add_newline('OPQRSTUVWXY') - + ["<<<<<<< OTHER\n2\n=======\nZ\n>>>>>>> THIS\n"] - ) - self.assertEquals(optimal_text, merged_text) - - def test_minimal_conflicts_nonunique(self): - def add_newline(s): - """Add a newline to each entry in the string""" - return [(x+'\n') for x in s] - - base_text = add_newline("abacddefgghij") - this_text = add_newline("abacddefgghijkalmontfprz") - other_text = add_newline("abacddefgghijknlmontfprd") - m3 = Merge3(base_text, other_text, this_text) - m_lines = m3.merge_lines('OTHER', 'THIS', reprocess=True) - merged_text = "".join(list(m_lines)) - optimal_text = ''.join(add_newline("abacddefgghijk") - + ["<<<<<<< OTHER\nn\n=======\na\n>>>>>>> THIS\n"] - + add_newline('lmontfpr') - + ["<<<<<<< OTHER\nd\n=======\nz\n>>>>>>> THIS\n"] - ) - self.assertEquals(optimal_text, merged_text) - - def test_reprocess_and_base(self): - """Reprocessing and showing base breaks correctly""" - base_text = ("a\n" * 20).splitlines(True) - this_text = ("a\n"*10+"b\n" * 10).splitlines(True) - other_text = ("a\n"*10+"c\n"+"b\n" * 8 + "c\n").splitlines(True) - m3 = Merge3(base_text, other_text, this_text) - m_lines = m3.merge_lines('OTHER', 'THIS', reprocess=True, - base_marker='|||||||') - self.assertRaises(CantReprocessAndShowBase, list, m_lines) - def test_binary(self): self.assertRaises(util.Abort, Merge3, ['\x00'], ['a'], ['b'])
--- a/tests/test-simplemerge.py.out Sun Aug 10 23:09:23 2014 -0500 +++ b/tests/test-simplemerge.py.out Mon Aug 11 11:24:05 2014 -0500 @@ -1,5 +1,5 @@ -.................... +................ ---------------------------------------------------------------------- -Ran 20 tests in 0.000s +Ran 16 tests in 0.000s OK
--- a/tests/test-static-http.t Sun Aug 10 23:09:23 2014 -0500 +++ b/tests/test-static-http.t Mon Aug 11 11:24:05 2014 -0500 @@ -1,4 +1,4 @@ - $ "$TESTDIR/hghave" killdaemons || exit 80 +#require killdaemons #if windows $ hg clone http://localhost:$HGPORT/ copy
--- a/tests/test-subrepo-git.t Sun Aug 10 23:09:23 2014 -0500 +++ b/tests/test-subrepo-git.t Mon Aug 11 11:24:05 2014 -0500 @@ -1,4 +1,4 @@ - $ "$TESTDIR/hghave" git || exit 80 +#require git make git commits repeatable
--- a/tests/test-subrepo-relative-path.t Sun Aug 10 23:09:23 2014 -0500 +++ b/tests/test-subrepo-relative-path.t Mon Aug 11 11:24:05 2014 -0500 @@ -1,4 +1,4 @@ - $ "$TESTDIR/hghave" killdaemons || exit 80 +#require killdaemons Preparing the subrepository 'sub'
--- a/tests/test-subrepo-svn.t Sun Aug 10 23:09:23 2014 -0500 +++ b/tests/test-subrepo-svn.t Mon Aug 11 11:24:05 2014 -0500 @@ -1,4 +1,4 @@ - $ "$TESTDIR/hghave" svn15 || exit 80 +#require svn15 $ SVNREPOPATH=`pwd`/svn-repo #if windows
--- a/tests/test-symlink-placeholder.t Sun Aug 10 23:09:23 2014 -0500 +++ b/tests/test-symlink-placeholder.t Mon Aug 11 11:24:05 2014 -0500 @@ -1,4 +1,4 @@ - $ "$TESTDIR/hghave" symlink || exit 80 +#require symlink Create extension that can disable symlink support:
--- a/tests/test-symlinks.t Sun Aug 10 23:09:23 2014 -0500 +++ b/tests/test-symlinks.t Mon Aug 11 11:24:05 2014 -0500 @@ -1,4 +1,4 @@ - $ "$TESTDIR/hghave" symlink || exit 80 +#require symlink == tests added in 0.7 ==
--- a/tests/test-transplant.t Sun Aug 10 23:09:23 2014 -0500 +++ b/tests/test-transplant.t Mon Aug 11 11:24:05 2014 -0500 @@ -1,4 +1,4 @@ - $ "$TESTDIR/hghave" killdaemons || exit 80 +#require killdaemons $ cat <<EOF >> $HGRCPATH > [extensions]
--- a/tests/test-treediscovery-legacy.t Sun Aug 10 23:09:23 2014 -0500 +++ b/tests/test-treediscovery-legacy.t Mon Aug 11 11:24:05 2014 -0500 @@ -1,4 +1,4 @@ - $ "$TESTDIR/hghave" killdaemons || exit 80 +#require killdaemons Tests discovery against servers without getbundle support:
--- a/tests/test-treediscovery.t Sun Aug 10 23:09:23 2014 -0500 +++ b/tests/test-treediscovery.t Mon Aug 11 11:24:05 2014 -0500 @@ -1,4 +1,4 @@ - $ "$TESTDIR/hghave" killdaemons || exit 80 +#require killdaemons Tests discovery against servers without getbundle support:
--- a/tests/test-unbundlehash.t Sun Aug 10 23:09:23 2014 -0500 +++ b/tests/test-unbundlehash.t Mon Aug 11 11:24:05 2014 -0500 @@ -1,4 +1,4 @@ - $ "$TESTDIR/hghave" killdaemons || exit 80 +#require killdaemons Test wire protocol unbundle with hashed heads (capability: unbundlehash)
--- a/tests/test-update-issue1456.t Sun Aug 10 23:09:23 2014 -0500 +++ b/tests/test-update-issue1456.t Mon Aug 11 11:24:05 2014 -0500 @@ -1,4 +1,4 @@ - $ "$TESTDIR/hghave" execbit || exit 80 +#require execbit $ rm -rf a $ hg init a