--- 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
--- a/tests/test-websub.t Sun Aug 10 23:09:23 2014 -0500
+++ b/tests/test-websub.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-wireproto.t Sun Aug 10 23:09:23 2014 -0500
+++ b/tests/test-wireproto.t Mon Aug 11 11:24:05 2014 -0500
@@ -1,4 +1,4 @@
- $ "$TESTDIR/hghave" killdaemons || exit 80
+#require killdaemons
Test wire protocol argument passing