Mercurial > hg
changeset 22315:188b8aa2120b
merge with crew
author | Matt Mackall <mpm@selenic.com> |
---|---|
date | Sat, 30 Aug 2014 18:44:59 +0200 |
parents | d226fe36e362 (diff) 6a8b8efb0641 (current diff) |
children | b31d29b2a7f2 |
files | mercurial/commands.py |
diffstat | 246 files changed, 5263 insertions(+), 2148 deletions(-) [+] |
line wrap: on
line diff
--- a/Makefile Sat Aug 30 15:13:02 2014 +0200 +++ b/Makefile Sat Aug 30 18:44:59 2014 +0200 @@ -135,7 +135,7 @@ # Packaging targets osx: - @which -s bdist_mpkg || \ + @which bdist_mpkg >/dev/null || \ (echo "Missing bdist_mpkg (easy_install bdist_mpkg)"; false) bdist_mpkg setup.py mkdir -p packages/osx
--- a/contrib/check-code.py Sat Aug 30 15:13:02 2014 +0200 +++ b/contrib/check-code.py Sat Aug 30 18:44:59 2014 +0200 @@ -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), @@ -214,8 +216,9 @@ (r'(\w|\)),\w', "missing whitespace after ,"), (r'(\w|\))[+/*\-<>]\w', "missing whitespace in expression"), (r'^\s+(\w|\.)+=\w[^,()\n]*$', "missing whitespace in assignment"), - (r'(\s+)try:\n((?:\n|\1\s.*\n)+?)\1except.*?:\n' - r'((?:\n|\1\s.*\n)+?)\1finally:', 'no try/except/finally in Python 2.4'), + (r'(\s+)try:\n((?:\n|\1\s.*\n)+?)(\1except.*?:\n' + r'((?:\n|\1\s.*\n)+?))+\1finally:', + 'no try/except/finally in Python 2.4'), (r'(?<!def)(\s+|^|\()next\(.+\)', 'no next(foo) in Python 2.4 and 2.5, use foo.next() instead'), (r'(\s+)try:\n((?:\n|\1\s.*\n)*?)\1\s*yield\b.*?'
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/contrib/check-commit Sat Aug 30 18:44:59 2014 +0200 @@ -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)
--- a/contrib/convert-repo Sat Aug 30 15:13:02 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,27 +0,0 @@ -#!/usr/bin/env python -# -# Wrapper script around the convert.py hgext extension -# for foreign SCM conversion to mercurial format. -# - -import sys -from mercurial import ui, fancyopts -from hgext import convert - -# Options extracted from the cmdtable -func, options, help = convert.cmdtable['convert'] - -# An ui instance -u = ui.ui() - -opts = {} -args = [] -try: - args = list(fancyopts.fancyopts(sys.argv[1:], options, opts)) - args += [None]*(3 - len(args)) - src, dest, revmapfile = args -except (fancyopts.getopt.GetoptError, ValueError), inst: - u.warn('Usage:\n%s\n' % help) - sys.exit(-1) - -convert.convert(u, src, dest, revmapfile, **opts)
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/contrib/hg-test-mode.el Sat Aug 30 18:44:59 2014 +0200 @@ -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) + '("^ \\([[][0-9]+[]]\\)$" 1 font-lock-warning-face) + '("^ \\(.*?\\)\\(\\( [(][-a-z]+[)]\\)*\\)$" 1 font-lock-string-face) + '("\\$?\\(HG\\|TEST\\)\\w+=?" . font-lock-variable-name-face) + '("^ \\(.*?\\)\\(\\( [(][-a-z]+[)]\\)+\\)$" 2 font-lock-type-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 Sat Aug 30 15:13:02 2014 +0200 +++ b/contrib/revsetbenchmarks.py Sat Aug 30 18:44:59 2014 +0200 @@ -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/revsetbenchmarks.txt Sat Aug 30 15:13:02 2014 +0200 +++ b/contrib/revsetbenchmarks.txt Sat Aug 30 18:44:59 2014 +0200 @@ -22,3 +22,4 @@ :10000 and draft() max(::(tip~20) - obsolete()) roots((0:tip)::) +(not public() - obsolete())
--- a/contrib/sample.hgrc Sat Aug 30 15:13:02 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,128 +0,0 @@ -### --- User interface - -[ui] - -### show changed files and be a bit more verbose if True - -# verbose = True - -### username data to appear in comits -### it usually takes the form: Joe User <joe.user@host.com> - -# username = Joe User <j.user@example.com> - -### --- Extensions - -[extensions] - -### each extension has its own 'extension_name=path' line -### the default python library path is used when path is left blank -### the hgext dir is used when 'hgext.extension_name=' is written - -### acl - Access control lists -### hg help acl - -# hgext.acl = - -### bisect - binary search changesets to detect bugs -### hg help bisect - -# hgext.hbisect = - -### bugzilla - update bugzilla bugs when changesets mention them -### hg help bugzilla - -# hgext.bugzilla = - -### extdiff - Use external diff application instead of builtin one - -# hgext.extdiff = - -### gpg - GPG checks and signing -### hg help gpg - -# hgext.gpg = - -### hgk - GUI repository browser -### hg help view - -# hgext.hgk = - -### strip - Remove changesets and their descendents from history -### hg help strip - -# hgext.strip = - -### notify - Template driven e-mail notifications -### hg help notify - -# hgext.notify = - -### patchbomb - send changesets as a series of patch emails -### hg help email - -# hgext.patchbomb = - -### churn - create a graph showing who changed the most lines -### hg help churn - -# hgext.churn = /home/user/hg/hg/contrib/churn.py - -### eol - automatic management of line endings - -# hgext.eol = - -### --- hgk additional configuration - -[hgk] - -### set executable path - -# path = /home/user/hg/hg/contrib/hgk - -### --- Hook to Mercurial actions - See hgrc man page for avaliable hooks - -[hooks] - -### Example notify hooks (load hgext.notify extension before use) - -# incoming.notify = python:hgext.notify.hook -# changegroup.notify = python:hgext.notify.hook - -### Email configuration for the notify and patchbomb extensions - -[email] - -### Your email address - -# from = user@example.com - -### Method to send email - smtp or /usr/sbin/sendmail or other program name - -# method = smtp - -### smtp server to send email to - -[smtp] - -# host = mail -# port = 25 -# tls = false -# username = user -# password = blivet -# local_hostname = myhost - -### --- Email notification hook for server - -[notify] -### multiple sources can be specified as a whitespace or comma separated list - -# sources = serve push pull bundle - -### set this to False when you're ready for mail to start sending - -# test = True - -### path to config file with names of subscribers - -# config = /path/to/subscription/file
--- a/contrib/simplemerge Sat Aug 30 15:13:02 2014 +0200 +++ b/contrib/simplemerge Sat Aug 30 18:44:59 2014 +0200 @@ -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/contrib/win32/hgwebdir_wsgi.py Sat Aug 30 15:13:02 2014 +0200 +++ b/contrib/win32/hgwebdir_wsgi.py Sat Aug 30 18:44:59 2014 +0200 @@ -52,6 +52,7 @@ # Enable tracing. Run 'python -m win32traceutil' to debug if getattr(sys, 'isapidllhandle', None) is not None: import win32traceutil + win32traceutil.SetupForPrint # silence unused import warning # To serve pages in local charset instead of UTF-8, remove the two lines below import os @@ -90,6 +91,6 @@ return isapi_wsgi.ISAPISimpleHandler(handler) if __name__=='__main__': - from isapi.install import * + from isapi.install import ISAPIParameters, HandleCommandLine params = ISAPIParameters() HandleCommandLine(params)
--- a/hgext/convert/__init__.py Sat Aug 30 15:13:02 2014 +0200 +++ b/hgext/convert/__init__.py Sat Aug 30 18:44:59 2014 +0200 @@ -29,6 +29,8 @@ ('A', 'authormap', '', _('remap usernames using this file'), _('FILE')), ('', 'filemap', '', _('remap file names using contents of file'), _('FILE')), + ('', 'full', None, + _('apply filemap changes by converting all files again')), ('', 'splicemap', '', _('splice synthesized history into place'), _('FILE')), ('', 'branchmap', '', _('change branch names while converting'), @@ -131,6 +133,14 @@ it is converted. To rename from a subdirectory into the root of the repository, use ``.`` as the path to rename to. + ``--full`` will make sure the converted changesets contain exactly + the right files with the right content. It will make a full + conversion of all files, not just the ones that have + changed. Files that already are correct will not be changed. This + can be used to apply filemap changes when converting + incrementally. This is currently only supported for Mercurial and + Subversion. + The splicemap is a file that allows insertion of synthetic history, letting you specify the parents of a revision. This is useful if you want to e.g. give a Subversion merge two parents, or
--- a/hgext/convert/bzr.py Sat Aug 30 15:13:02 2014 +0200 +++ b/hgext/convert/bzr.py Sat Aug 30 18:44:59 2014 +0200 @@ -122,8 +122,7 @@ kind = revtree.kind(fileid) if kind not in supportedkinds: # the file is not available anymore - was deleted - raise IOError(_('%s is not available in %s anymore') % - (name, rev)) + return None, None mode = self._modecache[(name, rev)] if kind == 'symlink': target = revtree.get_symlink_target(fileid) @@ -135,8 +134,9 @@ sio = revtree.get_file(fileid) return sio.read(), mode - def getchanges(self, version): - # set up caches: modecache and revtree + def getchanges(self, version, full): + if full: + raise util.Abort(_("convert from cvs do not support --full")) self._modecache = {} self._revtree = self.sourcerepo.revision_tree(version) # get the parentids from the cache
--- a/hgext/convert/common.py Sat Aug 30 15:13:02 2014 +0200 +++ b/hgext/convert/common.py Sat Aug 30 18:44:59 2014 +0200 @@ -88,17 +88,18 @@ def getfile(self, name, rev): """Return a pair (data, mode) where data is the file content as a string and mode one of '', 'x' or 'l'. rev is the - identifier returned by a previous call to getchanges(). Raise - IOError to indicate that name was deleted in rev. + identifier returned by a previous call to getchanges(). + Data is None if file is missing/deleted in rev. """ raise NotImplementedError - def getchanges(self, version): + def getchanges(self, version, full): """Returns a tuple of (files, copies). files is a sorted list of (filename, id) tuples for all files changed between version and its first parent returned by - getcommit(). id is the source revision id of the file. + getcommit(). If full, all files in that revision is returned. + id is the source revision id of the file. copies is a dictionary of dest: source """ @@ -204,7 +205,7 @@ mapping equivalent authors identifiers for each system.""" return None - def putcommit(self, files, copies, parents, commit, source, revmap): + def putcommit(self, files, copies, parents, commit, source, revmap, full): """Create a revision with all changed files listed in 'files' and having listed parents. 'commit' is a commit object containing at a minimum the author, date, and message for this @@ -212,7 +213,8 @@ 'copies' is a dictionary mapping destinations to sources, 'source' is the source repository, and 'revmap' is a mapfile of source revisions to converted revisions. Only getfile() and - lookuprev() should be called on 'source'. + lookuprev() should be called on 'source'. 'full' means that 'files' + is complete and all other files should be removed. Note that the sink repository is not told to update itself to a particular revision (or even what that revision would be)
--- a/hgext/convert/convcmd.py Sat Aug 30 15:13:02 2014 +0200 +++ b/hgext/convert/convcmd.py Sat Aug 30 18:44:59 2014 +0200 @@ -386,8 +386,8 @@ def copy(self, rev): commit = self.commitcache[rev] - - changes = self.source.getchanges(rev) + full = self.opts.get('full') + changes = self.source.getchanges(rev, full) if isinstance(changes, basestring): if changes == SKIPREV: dest = SKIPREV @@ -413,7 +413,7 @@ parents = [b[0] for b in pbranches] source = progresssource(self.ui, self.source, len(files)) newnode = self.dest.putcommit(files, copies, parents, commit, - source, self.map) + source, self.map, full) source.close() self.source.converted(rev, newnode) self.map[rev] = newnode
--- a/hgext/convert/cvs.py Sat Aug 30 15:13:02 2014 +0200 +++ b/hgext/convert/cvs.py Sat Aug 30 18:44:59 2014 +0200 @@ -220,7 +220,7 @@ self._parse() if rev.endswith("(DEAD)"): - raise IOError + return None, None args = ("-N -P -kk -r %s --" % rev).split() args.append(self.cvsrepo + '/' + name) @@ -258,7 +258,9 @@ else: raise util.Abort(_("unknown CVS response: %s") % line) - def getchanges(self, rev): + def getchanges(self, rev, full): + if full: + raise util.Abort(_("convert from cvs do not support --full")) self._parse() return sorted(self.files[rev].iteritems()), {}
--- a/hgext/convert/cvsps.py Sat Aug 30 15:13:02 2014 +0200 +++ b/hgext/convert/cvsps.py Sat Aug 30 18:44:59 2014 +0200 @@ -8,7 +8,6 @@ import os import re import cPickle as pickle -from mercurial import util from mercurial.i18n import _ from mercurial import hook from mercurial import util @@ -632,7 +631,19 @@ odd.add((l, r)) d = -1 break + # By this point, the changesets are sufficiently compared that + # we don't really care about ordering. However, this leaves + # some race conditions in the tests, so we compare on the + # number of files modified and the number of branchpoints in + # each changeset to ensure test output remains stable. + # recommended replacement for cmp from + # https://docs.python.org/3.0/whatsnew/3.0.html + c = lambda x, y: (x > y) - (x < y) + if not d: + d = c(len(l.entries), len(r.entries)) + if not d: + d = c(len(l.branchpoints), len(r.branchpoints)) return d changesets.sort(cscmp)
--- a/hgext/convert/darcs.py Sat Aug 30 15:13:02 2014 +0200 +++ b/hgext/convert/darcs.py Sat Aug 30 18:44:59 2014 +0200 @@ -8,7 +8,7 @@ from common import NoRepo, checktool, commandline, commit, converter_source from mercurial.i18n import _ from mercurial import util -import os, shutil, tempfile, re +import os, shutil, tempfile, re, errno # The naming drift of ElementTree is fun! @@ -156,7 +156,9 @@ output, status = self.run('revert', all=True, repodir=self.tmppath) self.checkexit(status, output) - def getchanges(self, rev): + def getchanges(self, rev, full): + if full: + raise util.Abort(_("convert from darcs do not support --full")) copies = {} changes = [] man = None @@ -192,8 +194,13 @@ if rev != self.lastrev: raise util.Abort(_('internal calling inconsistency')) path = os.path.join(self.tmppath, name) - data = util.readfile(path) - mode = os.lstat(path).st_mode + try: + data = util.readfile(path) + mode = os.lstat(path).st_mode + except IOError, inst: + if inst.errno == errno.ENOENT: + return None, None + raise mode = (mode & 0111) and 'x' or '' return data, mode
--- a/hgext/convert/filemap.py Sat Aug 30 15:13:02 2014 +0200 +++ b/hgext/convert/filemap.py Sat Aug 30 18:44:59 2014 +0200 @@ -304,7 +304,7 @@ wrev.add(rev) self.wantedancestors[rev] = wrev - def getchanges(self, rev): + def getchanges(self, rev, full): parents = self.commits[rev].parents if len(parents) > 1: self.rebuild() @@ -384,7 +384,7 @@ # Get the real changes and do the filtering/mapping. To be # able to get the files later on in getfile, we hide the # original filename in the rev part of the return value. - changes, copies = self.base.getchanges(rev) + changes, copies = self.base.getchanges(rev, full) files = {} for f, r in changes: newf = self.filemapper(f)
--- a/hgext/convert/git.py Sat Aug 30 15:13:02 2014 +0200 +++ b/hgext/convert/git.py Sat Aug 30 18:44:59 2014 +0200 @@ -135,7 +135,7 @@ def getfile(self, name, rev): if rev == hex(nullid): - raise IOError + return None, None if name == '.hgsub': data = '\n'.join([m.hgsub() for m in self.submoditer()]) mode = '' @@ -180,7 +180,9 @@ continue m.node = node.strip() - def getchanges(self, version): + def getchanges(self, version, full): + if full: + raise util.Abort(_("convert from git do not support --full")) self.modecache = {} fh = self.gitopen("git diff-tree -z --root -m -r %s" % version) changes = []
--- a/hgext/convert/gnuarch.py Sat Aug 30 15:13:02 2014 +0200 +++ b/hgext/convert/gnuarch.py Sat Aug 30 18:44:59 2014 +0200 @@ -137,13 +137,14 @@ if rev != self.lastrev: raise util.Abort(_('internal calling inconsistency')) - # Raise IOError if necessary (i.e. deleted files). if not os.path.lexists(os.path.join(self.tmppath, name)): - raise IOError + return None, None return self._getfile(name, rev) - def getchanges(self, rev): + def getchanges(self, rev, full): + if full: + raise util.Abort(_("convert from arch do not support --full")) self._update(rev) changes = [] copies = {}
--- a/hgext/convert/hg.py Sat Aug 30 15:13:02 2014 +0200 +++ b/hgext/convert/hg.py Sat Aug 30 18:44:59 2014 +0200 @@ -128,12 +128,16 @@ fp.write('%s %s\n' % (revid, s[1])) return fp.getvalue() - def putcommit(self, files, copies, parents, commit, source, revmap): - + def putcommit(self, files, copies, parents, commit, source, revmap, full): files = dict(files) def getfilectx(repo, memctx, f): - v = files[f] + try: + v = files[f] + except KeyError: + return None data, mode = source.getfile(f, v) + if data is None: + return None if f == '.hgtags': data = self._rewritetags(source, revmap, data) return context.memfilectx(self.repo, f, data, 'l' in mode, @@ -191,7 +195,10 @@ while parents: p1 = p2 p2 = parents.pop(0) - ctx = context.memctx(self.repo, (p1, p2), text, files.keys(), + fileset = set(files) + if full: + fileset.update(self.repo[p1], self.repo[p2]) + ctx = context.memctx(self.repo, (p1, p2), text, fileset, getfilectx, commit.author, commit.date, extra) self.repo.commitctx(ctx) text = "(octopus merge fixup)\n" @@ -299,7 +306,7 @@ raise NoRepo(_("%s is not a local Mercurial repository") % path) self.lastrev = None self.lastctx = None - self._changescache = None + self._changescache = None, None self.convertfp = None # Restrict converted revisions to startrev descendants startnode = ui.config('convert', 'hg.startrev') @@ -351,29 +358,28 @@ try: fctx = self.changectx(rev)[name] return fctx.data(), fctx.flags() - except error.LookupError, err: - raise IOError(err) + except error.LookupError: + return None, None - def getchanges(self, rev): + def getchanges(self, rev, full): ctx = self.changectx(rev) parents = self.parents(ctx) - if not parents: - files = sorted(ctx.manifest()) - # getcopies() is not needed for roots, but it is a simple way to - # detect missing revlogs and abort on errors or populate - # self.ignored - self.getcopies(ctx, parents, files) - return [(f, rev) for f in files if f not in self.ignored], {} - if self._changescache and self._changescache[0] == rev: - m, a, r = self._changescache[1] - else: - m, a, r = self.repo.status(parents[0].node(), ctx.node())[:3] - # getcopies() detects missing revlogs early, run it before - # filtering the changes. - copies = self.getcopies(ctx, parents, m + a) - changes = [(name, rev) for name in m + a + r - if name not in self.ignored] - return sorted(changes), copies + if full or not parents: + files = copyfiles = ctx.manifest() + if parents: + if self._changescache[0] == rev: + m, a, r = self._changescache[1] + else: + m, a, r = self.repo.status(parents[0].node(), ctx.node())[:3] + if not full: + files = m + a + r + copyfiles = m + a + # getcopies() is also run for roots and before filtering so missing + # revlogs are detected early + copies = self.getcopies(ctx, parents, copyfiles) + changes = [(f, rev) for f in files if f not in self.ignored] + changes.sort() + return changes, copies def getcopies(self, ctx, parents, files): copies = {}
--- a/hgext/convert/monotone.py Sat Aug 30 15:13:02 2014 +0200 +++ b/hgext/convert/monotone.py Sat Aug 30 18:44:59 2014 +0200 @@ -224,7 +224,9 @@ else: return [self.rev] - def getchanges(self, rev): + def getchanges(self, rev, full): + if full: + raise util.Abort(_("convert from monotone do not support --full")) revision = self.mtnrun("get_revision", rev).split("\n\n") files = {} ignoremove = {} @@ -282,11 +284,11 @@ def getfile(self, name, rev): if not self.mtnisfile(name, rev): - raise IOError # file was deleted or renamed + return None, None try: data = self.mtnrun("get_file_of", name, r=rev) except Exception: - raise IOError # file was deleted or renamed + return None, None self.mtnloadmanifest(rev) node, attr = self.files.get(name, (None, "")) return data, attr
--- a/hgext/convert/p4.py Sat Aug 30 15:13:02 2014 +0200 +++ b/hgext/convert/p4.py Sat Aug 30 18:44:59 2014 +0200 @@ -164,6 +164,8 @@ raise IOError(d["generic"], data) elif code == "stat": + if d.get("action") == "purge": + return None, None p4type = self.re_type.match(d["type"]) if p4type: mode = "" @@ -181,7 +183,7 @@ contents += data if mode is None: - raise IOError(0, "bad stat") + return None, None if keywords: contents = keywords.sub("$\\1$", contents) @@ -190,7 +192,9 @@ return contents, mode - def getchanges(self, rev): + def getchanges(self, rev, full): + if full: + raise util.Abort(_("convert from p4 do not support --full")) return self.files[rev], {} def getcommit(self, rev):
--- a/hgext/convert/subversion.py Sat Aug 30 15:13:02 2014 +0200 +++ b/hgext/convert/subversion.py Sat Aug 30 18:44:59 2014 +0200 @@ -347,7 +347,7 @@ % self.module) self.last_changed = self.revnum(self.head) - self._changescache = None + self._changescache = (None, None) if os.path.exists(os.path.join(url, '.svn/entries')): self.wc = url @@ -444,34 +444,39 @@ return self.heads - def getchanges(self, rev): - if self._changescache and self._changescache[0] == rev: - return self._changescache[1] - self._changescache = None + def _getchanges(self, rev, full): (paths, parents) = self.paths[rev] + copies = {} if parents: files, self.removed, copies = self.expandpaths(rev, paths, parents) - else: + if full or not parents: # Perform a full checkout on roots uuid, module, revnum = revsplit(rev) entries = svn.client.ls(self.baseurl + quote(module), optrev(revnum), True, self.ctx) files = [n for n, e in entries.iteritems() if e.kind == svn.core.svn_node_file] - copies = {} self.removed = set() files.sort() files = zip(files, [rev] * len(files)) + return (files, copies) - # caller caches the result, so free it here to release memory - del self.paths[rev] + def getchanges(self, rev, full): + # reuse cache from getchangedfiles + if self._changescache[0] == rev and not full: + (files, copies) = self._changescache[1] + else: + (files, copies) = self._getchanges(rev, full) + # caller caches the result, so free it here to release memory + del self.paths[rev] return (files, copies) def getchangedfiles(self, rev, i): - changes = self.getchanges(rev) - self._changescache = (rev, changes) - return [f[0] for f in changes[0]] + # called from filemap - cache computed values for reuse in getchanges + (files, copies) = self._getchanges(rev, False) + self._changescache = (rev, (files, copies)) + return [f[0] for f in files] def getcommit(self, rev): if rev not in self.commits: @@ -490,10 +495,10 @@ self._fetch_revisions(revnum, stop) if rev not in self.commits: raise util.Abort(_('svn: revision %s not found') % revnum) - commit = self.commits[rev] + revcommit = self.commits[rev] # caller caches the result, so free it here to release memory del self.commits[rev] - return commit + return revcommit def checkrevformat(self, revstr, mapname='splicemap'): """ fails if revision format does not match the correct format""" @@ -933,7 +938,7 @@ def getfile(self, file, rev): # TODO: ra.get_file transmits the whole file instead of diffs. if file in self.removed: - raise IOError + return None, None mode = '' try: new_module, revnum = revsplit(rev)[1:] @@ -954,7 +959,7 @@ notfound = (svn.core.SVN_ERR_FS_NOT_FOUND, svn.core.SVN_ERR_RA_DAV_PATH_NOT_FOUND) if e.apr_err in notfound: # File not found - raise IOError + return None, None raise if mode == 'l': link_prefix = "link " @@ -1211,23 +1216,13 @@ self.xargs(files, 'add', quiet=True) return files - def tidy_dirs(self, names): - deleted = [] - for d in sorted(self.dirs_of(names), reverse=True): - wd = self.wjoin(d) - if os.listdir(wd) == '.svn': - self.run0('delete', d) - self.manifest.remove(d) - deleted.append(d) - return deleted - def addchild(self, parent, child): self.childmap[parent] = child def revid(self, rev): return u"svn:%s@%s" % (self.uuid, rev) - def putcommit(self, files, copies, parents, commit, source, revmap): + def putcommit(self, files, copies, parents, commit, source, revmap, full): for parent in parents: try: return self.revid(self.childmap[parent]) @@ -1236,14 +1231,15 @@ # Apply changes to working copy for f, v in files: - try: - data, mode = source.getfile(f, v) - except IOError: + data, mode = source.getfile(f, v) + if data is None: self.delete.append(f) else: self.putfile(f, mode, data) if f in copies: self.copies.append([copies[f], f]) + if full: + self.delete.extend(sorted(self.manifest.difference(files))) files = [f[0] for f in files] entries = set(self.delete) @@ -1259,7 +1255,6 @@ self.manifest.remove(f) self.delete = [] entries.update(self.add_files(files.difference(entries))) - entries.update(self.tidy_dirs(entries)) if self.delexec: self.xargs(self.delexec, 'propdel', 'svn:executable') self.delexec = []
--- a/hgext/extdiff.py Sat Aug 30 15:13:02 2014 +0200 +++ b/hgext/extdiff.py Sat Aug 30 18:44:59 2014 +0200 @@ -63,7 +63,7 @@ from mercurial.i18n import _ from mercurial.node import short, nullid -from mercurial import cmdutil, scmutil, scmutil, util, commands, encoding +from mercurial import cmdutil, scmutil, util, commands, encoding import os, shlex, shutil, tempfile, re cmdtable = {}
--- a/hgext/fetch.py Sat Aug 30 15:13:02 2014 +0200 +++ b/hgext/fetch.py Sat Aug 30 18:44:59 2014 +0200 @@ -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 Sat Aug 30 15:13:02 2014 +0200 +++ b/hgext/gpg.py Sat Aug 30 18:44:59 2014 +0200 @@ -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 Sat Aug 30 15:13:02 2014 +0200 +++ b/hgext/histedit.py Sat Aug 30 18:44:59 2014 +0200 @@ -36,6 +36,7 @@ # p, pick = use commit # e, edit = use commit, but stop for amending # f, fold = use commit, but combine it with the one above + # r, roll = like fold, but discard this commit's description # d, drop = remove commit from history # m, mess = edit message without changing commit content # @@ -57,6 +58,7 @@ # p, pick = use commit # e, edit = use commit, but stop for amending # f, fold = use commit, but combine it with the one above + # r, roll = like fold, but discard this commit's description # d, drop = remove commit from history # m, mess = edit message without changing commit content # @@ -179,6 +181,7 @@ # p, pick = use commit # e, edit = use commit, but stop for amending # f, fold = use commit, but combine it with the one above +# r, roll = like fold, but discard this commit's description # d, drop = remove commit from history # m, mess = edit message without changing commit content # @@ -208,8 +211,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] @@ -282,7 +283,7 @@ isexec='x' in flags, copied=copied.get(path)) return mctx - raise IOError() + return None if commitopts.get('message'): message = commitopts['message'] @@ -293,6 +294,9 @@ extra = commitopts.get('extra') parents = (first.p1().node(), first.p2().node()) + editor = None + if not commitopts.get('rollup'): + editor = cmdutil.getcommiteditor(edit=True, editform='histedit.fold') new = context.memctx(repo, parents=parents, text=message, @@ -301,7 +305,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): @@ -334,6 +338,11 @@ _('Make changes as needed, you may commit or record as needed now.\n' 'When you are finished, run hg histedit --continue to resume.')) +def rollup(ui, repo, ctx, ha, opts): + rollupopts = opts.copy() + rollupopts['rollup'] = True + return fold(ui, repo, ctx, ha, rollupopts) + def fold(ui, repo, ctx, ha, opts): oldctx = repo[ha] hg.update(repo, ctx.node()) @@ -356,10 +365,13 @@ commitopts = opts.copy() commitopts['user'] = ctx.user() # commit message - newmessage = '\n***\n'.join( - [ctx.description()] + - [repo[r].description() for r in internalchanges] + - [oldctx.description()]) + '\n' + if opts.get('rollup'): + newmessage = ctx.description() + else: + newmessage = '\n***\n'.join( + [ctx.description()] + + [repo[r].description() for r in internalchanges] + + [oldctx.description()]) + '\n' commitopts['message'] = newmessage # date commitopts['date'] = max(ctx.date(), oldctx.date()) @@ -400,9 +412,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,))] @@ -439,6 +452,8 @@ 'edit': edit, 'f': fold, 'fold': fold, + 'r': rollup, + 'roll': rollup, 'd': drop, 'drop': drop, 'm': message, @@ -595,11 +610,10 @@ rules = f.read() f.close() rules = [l for l in (r.strip() for r in rules.splitlines()) - if l and not l[0] == '#'] + if l and not l.startswith('#')] rules = verifyrules(rules, repo, ctxs) parentctx = repo[root].parents()[0] - keep = opts.get('keep', False) replacements = [] @@ -674,12 +688,14 @@ m, a, r, d = repo.status()[:4] if m or a or r or d: # prepare the message for the commit to comes - if action in ('f', 'fold'): + if action in ('f', 'fold', 'r', 'roll'): message = 'fold-temp-revision %s' % currentnode 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(), @@ -695,15 +711,19 @@ # to parent. replacements.append((ctx.node(), tuple(newchildren))) - if action in ('f', 'fold'): + if action in ('f', 'fold', 'r', 'roll'): if newchildren: # finalize fold operation if applicable if new is None: new = newchildren[-1] else: newchildren.pop() # remove new from internal changes - parentctx, repl = finishfold(ui, repo, parentctx, ctx, new, opts, - newchildren) + foldopts = opts + if action in ('r', 'roll'): + foldopts = foldopts.copy() + foldopts['rollup'] = True + parentctx, repl = finishfold(ui, repo, parentctx, ctx, new, + foldopts, newchildren) replacements.extend(repl) else: # newchildren is empty if the fold did not result in any commit
--- a/hgext/keyword.py Sat Aug 30 15:13:02 2014 +0200 +++ b/hgext/keyword.py Sat Aug 30 18:44:59 2014 +0200 @@ -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 Sat Aug 30 15:13:02 2014 +0200 +++ b/hgext/largefiles/lfcommands.py Sat Aug 30 18:44:59 2014 +0200 @@ -146,7 +146,7 @@ try: fctx = ctx.filectx(lfutil.standin(f)) except error.LookupError: - raise IOError + return None renamed = fctx.renamed() if renamed: renamed = lfutil.splitstandin(renamed[0]) @@ -248,7 +248,7 @@ try: fctx = ctx.filectx(srcfname) except error.LookupError: - raise IOError + return None renamed = fctx.renamed() if renamed: # standin is always a largefile because largefile-ness @@ -298,7 +298,7 @@ try: fctx = ctx.filectx(f) except error.LookupError: - raise IOError + return None renamed = fctx.renamed() if renamed: renamed = renamed[0] @@ -443,6 +443,7 @@ lfiles = set(lfutil.listlfiles(repo)) | set(lfdirstate) if filelist is not None: + filelist = set(filelist) lfiles = [f for f in lfiles if f in filelist] update = {} @@ -510,26 +511,20 @@ 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) + + if filelist is not None: + # If "local largefile" is chosen at file merging, it is + # not listed in "filelist" (= dirstate syncing is + # omitted), because the standin file is not changed before and + # after merging. + # But the status of such files may have to be changed by + # merging. For example, locally modified ("M") largefile + # has to become re-added("A"), if it is "normal" file in + # the target revision of linear-merging. + for lfile in lfdirstate: + if lfile not in filelist: + lfutil.synclfdirstate(repo, lfdirstate, lfile, True) lfdirstate.write() if printmessage and lfiles:
--- a/hgext/largefiles/lfutil.py Sat Aug 30 15:13:02 2014 +0200 +++ b/hgext/largefiles/lfutil.py Sat Aug 30 18:44:59 2014 +0200 @@ -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 Sat Aug 30 15:13:02 2014 +0200 +++ b/hgext/largefiles/overrides.py Sat Aug 30 18:44:59 2014 +0200 @@ -12,7 +12,7 @@ import copy from mercurial import hg, commands, util, cmdutil, scmutil, match as match_, \ - archival, merge, pathutil, revset + archival, pathutil, revset from mercurial.i18n import _ from mercurial.node import hex from hgext import rebase @@ -369,10 +369,6 @@ lfdirstate.write() if mod: raise util.Abort(_('uncommitted changes')) - # XXX handle removed differently - if not opts['clean']: - for lfile in unsure + modified + added: - lfutil.updatestandin(repo, lfutil.standin(lfile)) return orig(ui, repo, *pats, **opts) finally: wlock.release() @@ -430,6 +426,7 @@ removes = set(a[0] for a in actions['r']) newglist = [] + lfmr = [] # LargeFiles: Mark as Removed for action in actions['g']: f, args, msg = action splitstandin = f and lfutil.splitstandin(f) @@ -456,7 +453,16 @@ 'keep (l)argefile or use (n)ormal file?' '$$ &Largefile $$ &Normal file') % lfile if repo.ui.promptchoice(msg, 0) == 0: - actions['r'].append((lfile, None, msg)) + if branchmerge: + # largefile can be restored from standin safely + actions['r'].append((lfile, None, msg)) + else: + # "lfile" should be marked as "removed" without + # removal of itself + lfmr.append((lfile, None, msg)) + + # linear-merge should treat this largefile as 're-added' + actions['a'].append((standin, None, msg)) else: actions['r'].append((standin, None, msg)) newglist.append((lfile, (p2.flags(lfile),), msg)) @@ -465,9 +471,22 @@ newglist.sort() actions['g'] = newglist + if lfmr: + lfmr.sort() + actions['lfmr'] = lfmr return actions +def mergerecordupdates(orig, repo, actions, branchmerge): + if 'lfmr' in actions: + # this should be executed before 'orig', to execute 'remove' + # before all other actions + for lfile, args, msg in actions['lfmr']: + repo.dirstate.remove(lfile) + + return orig(repo, actions, branchmerge) + + # Override filemerge to prompt the user about how they wish to merge # largefiles. This will handle identical edits without prompting the user. def overridefilemerge(origfn, repo, mynode, orig, fcd, fco, fca, labels=None): @@ -695,25 +714,6 @@ finally: wlock.release() -def hgupdaterepo(orig, repo, node, overwrite): - if not overwrite: - # Only call updatelfiles on the standins that have changed to save time - oldstandins = lfutil.getstandinsstate(repo) - - result = orig(repo, node, overwrite) - - filelist = None - if not overwrite: - newstandins = lfutil.getstandinsstate(repo) - filelist = lfutil.getlfilestoupdate(oldstandins, newstandins) - lfcommands.updatelfiles(repo.ui, repo, filelist=filelist) - return result - -def hgmerge(orig, repo, node, force=None, remind=True): - result = orig(repo, node, force, remind) - lfcommands.updatelfiles(repo.ui, repo) - return result - # When we rebase a repository with remotely changed largefiles, we need to # take some extra care so that the largefiles are correctly updated in the # working copy @@ -1157,19 +1157,40 @@ 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: + before = repo.dirstate.parents() + orphans = set(f for f in repo.dirstate + if lfutil.isstandin(f) and repo.dirstate[f] != 'r') + result = orig(ui, repo, **opts) + after = repo.dirstate.parents() + if before == after: + return result # no need to restore standins + + pctx = repo['.'] + for f in repo.dirstate: + if lfutil.isstandin(f): + orphans.discard(f) + if repo.dirstate[f] == 'r': + repo.wvfs.unlinkpath(f, ignoremissing=True) + elif f in pctx: + fctx = pctx[f] + repo.wwrite(f, fctx.data(), fctx.flags()) + else: + # content of standin is not so important in 'a', + # 'm' or 'n' (coming from the 2nd parent) cases + lfutil.writestandin(repo, f, '', False) + for standin in orphans: + repo.wvfs.unlinkpath(standin, ignoremissing=True) + 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() @@ -1243,3 +1264,67 @@ def mercurialsinkafter(orig, sink): sink.repo._isconverting = False orig(sink) + +def mergeupdate(orig, repo, node, branchmerge, force, partial, + *args, **kwargs): + wlock = repo.wlock() + try: + # branch | | | + # merge | force | partial | action + # -------+-------+---------+-------------- + # x | x | x | linear-merge + # o | x | x | branch-merge + # x | o | x | overwrite (as clean update) + # o | o | x | force-branch-merge (*1) + # x | x | o | (*) + # o | x | o | (*) + # x | o | o | overwrite (as revert) + # o | o | o | (*) + # + # (*) don't care + # (*1) deprecated, but used internally (e.g: "rebase --collapse") + + linearmerge = not branchmerge and not force and not partial + + if linearmerge or (branchmerge and force and not partial): + # update standins for linear-merge or force-branch-merge, + # because largefiles in the working directory may be modified + lfdirstate = lfutil.openlfdirstate(repo.ui, repo) + s = lfdirstate.status(match_.always(repo.root, repo.getcwd()), + [], False, False, False) + unsure, modified, added = s[:3] + for lfile in unsure + modified + added: + lfutil.updatestandin(repo, lfutil.standin(lfile)) + + if linearmerge: + # Only call updatelfiles on the standins that have changed + # to save time + oldstandins = lfutil.getstandinsstate(repo) + + result = orig(repo, node, branchmerge, force, partial, *args, **kwargs) + + filelist = None + if linearmerge: + newstandins = lfutil.getstandinsstate(repo) + filelist = lfutil.getlfilestoupdate(oldstandins, newstandins) + + # suppress status message while automated committing + printmessage = not (getattr(repo, "_isrebasing", False) or + getattr(repo, "_istransplanting", False)) + lfcommands.updatelfiles(repo.ui, repo, filelist=filelist, + printmessage=printmessage, + normallookup=partial) + + return result + finally: + wlock.release() + +def scmutilmarktouched(orig, repo, files, *args, **kwargs): + result = orig(repo, files, *args, **kwargs) + + filelist = [lfutil.splitstandin(f) for f in files if lfutil.isstandin(f)] + if filelist: + lfcommands.updatelfiles(repo.ui, repo, filelist=filelist, + printmessage=False, normallookup=True) + + return result
--- a/hgext/largefiles/reposetup.py Sat Aug 30 15:13:02 2014 +0200 +++ b/hgext/largefiles/reposetup.py Sat Aug 30 18:44:59 2014 +0200 @@ -272,19 +272,29 @@ wlock = self.wlock() try: - # Case 0: Rebase or Transplant - # We have to take the time to pull down the new largefiles now. - # Otherwise, any largefiles that were modified in the - # destination changesets get overwritten, either by the rebase - # or in the first commit after the rebase or transplant. - # updatelfiles will update the dirstate to mark any pulled - # largefiles as modified + # Case 0: Automated committing + # + # While automated committing (like rebase, transplant + # and so on), this code path is used to avoid: + # (1) updating standins, because standins should + # be already updated at this point + # (2) aborting when stadnins are matched by "match", + # because automated committing may specify them directly + # if getattr(self, "_isrebasing", False) or \ getattr(self, "_istransplanting", False): - lfcommands.updatelfiles(self.ui, self, filelist=None, - 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/largefiles/uisetup.py Sat Aug 30 15:13:02 2014 +0200 +++ b/hgext/largefiles/uisetup.py Sat Aug 30 18:44:59 2014 +0200 @@ -99,6 +99,10 @@ overrides.overridecheckunknownfile) entry = extensions.wrapfunction(merge, 'calculateupdates', overrides.overridecalculateupdates) + entry = extensions.wrapfunction(merge, 'recordupdates', + overrides.mergerecordupdates) + entry = extensions.wrapfunction(merge, 'update', + overrides.mergeupdate) entry = extensions.wrapfunction(filemerge, 'filemerge', overrides.overridefilemerge) entry = extensions.wrapfunction(cmdutil, 'copy', @@ -115,15 +119,15 @@ entry = extensions.wrapfunction(commands, 'revert', overrides.overriderevert) - extensions.wrapfunction(hg, 'updaterepo', overrides.hgupdaterepo) - extensions.wrapfunction(hg, 'merge', overrides.hgmerge) - extensions.wrapfunction(archival, 'archive', overrides.overridearchive) extensions.wrapfunction(subrepo.hgsubrepo, 'archive', overrides.hgsubrepoarchive) extensions.wrapfunction(cmdutil, 'bailifchanged', overrides.overridebailifchanged) + extensions.wrapfunction(scmutil, 'marktouched', + overrides.scmutilmarktouched) + # create the new wireproto commands ... wireproto.commands['putlfile'] = (proto.putlfile, 'sha') wireproto.commands['getlfile'] = (proto.getlfile, 'sha')
--- a/hgext/mq.py Sat Aug 30 15:13:02 2014 +0200 +++ b/hgext/mq.py Sat Aug 30 18:44:59 2014 +0200 @@ -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 Sat Aug 30 15:13:02 2014 +0200 +++ b/hgext/purge.py Sat Aug 30 18:44:59 2014 +0200 @@ -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,27 +95,17 @@ 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 + if removedirs: + directories = [] + match.explicitdir = match.traversedir = directories.append status = repo.status(match=match, ignored=opts['all'], unknown=True) if removefiles: 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 Sat Aug 30 15:13:02 2014 +0200 +++ b/hgext/rebase.py Sat Aug 30 18:44:59 2014 +0200 @@ -138,7 +138,6 @@ skipped = set() targetancestors = set() - editor = cmdutil.getcommiteditor(**opts) lock = wlock = None try: @@ -354,6 +353,9 @@ p1rev = repo[rev].p1().rev() cmdutil.duplicatecopies(repo, rev, p1rev, skiprev=target) if not collapsef: + merging = repo[p2].rev() != nullrev + editform = cmdutil.mergeeditform(merging, 'rebase') + editor = cmdutil.getcommiteditor(editform=editform, **opts) newrev = concludenode(repo, rev, p1, p2, extrafn=extrafn, editor=editor) else: @@ -376,6 +378,8 @@ if collapsef and not keepopen: p1, p2 = defineparents(repo, min(state), target, state, targetancestors) + editopt = opts.get('edit') + editform = 'rebase.collapse' if collapsemsg: commitmsg = collapsemsg else: @@ -383,7 +387,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) + editopt = True + editor = cmdutil.getcommiteditor(edit=editopt, editform=editform) newrev = concludenode(repo, rev, p1, external, commitmsg=commitmsg, extrafn=extrafn, editor=editor) for oldrev in state.iterkeys(): @@ -468,15 +473,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 Sat Aug 30 15:13:02 2014 +0200 +++ b/hgext/shelve.py Sat Aug 30 18:44:59 2014 +0200 @@ -25,7 +25,7 @@ from mercurial.node import nullid, nullrev, bin, hex from mercurial import changegroup, cmdutil, scmutil, phases, commands from mercurial import error, hg, mdiff, merge, patch, repair, util -from mercurial import templatefilters, changegroup, exchange +from mercurial import templatefilters, exchange from mercurial import lock as lockmod from hgext import rebase import errno @@ -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)) @@ -266,7 +269,7 @@ wlock = None try: wlock = repo.wlock() - for (name, _) in repo.vfs.readdir('shelved'): + for (name, _type) in repo.vfs.readdir('shelved'): suffix = name.rsplit('.', 1)[-1] if suffix in ('hg', 'files', 'patch'): shelvedfile(repo, name).unlink() @@ -300,7 +303,7 @@ raise return [] info = [] - for (name, _) in names: + for (name, _type) in names: pfx, sfx = name.rsplit('.', 1) if not pfx or sfx != 'patch': continue @@ -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: @@ -410,9 +413,11 @@ for file in u: if file in files: util.rename(file, file + ".orig") + ui.pushbuffer(True) cmdutil.revert(ui, repo, shelvectx, repo.dirstate.parents(), *pathtofiles(repo, files), **{'no_backup': True}) + ui.popbuffer() finally: ui.quiet = oldquiet @@ -457,7 +462,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 +563,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 +582,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 Sat Aug 30 15:13:02 2014 +0200 +++ b/hgext/strip.py Sat Aug 30 18:44:59 2014 +0200 @@ -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 Sat Aug 30 15:13:02 2014 +0200 +++ b/hgext/transplant.py Sat Aug 30 18:44:59 2014 +0200 @@ -86,7 +86,10 @@ self.opener = scmutil.opener(self.path) self.transplants = transplants(self.path, 'transplants', opener=self.opener) - self.editor = cmdutil.getcommiteditor(**opts) + def getcommiteditor(): + editform = cmdutil.mergeeditform(repo[None], 'transplant') + return cmdutil.getcommiteditor(editform=editform, **opts) + self.getcommiteditor = getcommiteditor def applied(self, repo, node, parent): '''returns True if a node is already an ancestor of parent @@ -286,7 +289,7 @@ m = match.exact(repo.root, '', files) n = repo.commit(message, user, date, extra=extra, match=m, - editor=self.editor) + editor=self.getcommiteditor()) if not n: self.ui.warn(_('skipping emptied changeset %s\n') % short(node)) return None @@ -342,7 +345,7 @@ if merge: repo.setparents(p1, parents[1]) n = repo.commit(message, user, date, extra=extra, - editor=self.editor) + editor=self.getcommiteditor()) if not n: raise util.Abort(_('commit failed')) if not merge:
--- a/i18n/check-translation.py Sat Aug 30 15:13:02 2014 +0200 +++ b/i18n/check-translation.py Sat Aug 30 18:44:59 2014 +0200 @@ -7,7 +7,7 @@ checkers = [] -def checker(level, msgidpat): +def levelchecker(level, msgidpat): def decorator(func): if msgidpat: match = re.compile(msgidpat).search @@ -33,7 +33,7 @@ #################### def fatalchecker(msgidpat=None): - return checker('fatal', msgidpat) + return levelchecker('fatal', msgidpat) @fatalchecker(r'\$\$') def promptchoice(pe): @@ -64,7 +64,7 @@ #################### def warningchecker(msgidpat=None): - return checker('warning', msgidpat) + return levelchecker('warning', msgidpat) @warningchecker() def taildoublecolons(pe):
--- a/mercurial/ancestor.py Sat Aug 30 15:13:02 2014 +0200 +++ b/mercurial/ancestor.py Sat Aug 30 18:44:59 2014 +0200 @@ -246,6 +246,14 @@ else: self._containsseen = set() + def __nonzero__(self): + """False if the set is empty, True otherwise.""" + try: + iter(self).next() + return True + except StopIteration: + return False + def __iter__(self): """Generate the ancestors of _initrevs in reverse topological order.
--- a/mercurial/branchmap.py Sat Aug 30 15:13:02 2014 +0200 +++ b/mercurial/branchmap.py Sat Aug 30 18:44:59 2014 +0200 @@ -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 Sat Aug 30 15:13:02 2014 +0200 +++ b/mercurial/changegroup.py Sat Aug 30 18:44:59 2014 +0200 @@ -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 Sat Aug 30 15:13:02 2014 +0200 +++ b/mercurial/cmdutil.py Sat Aug 30 18:44:59 2014 +0200 @@ -109,7 +109,25 @@ (logfile, inst.strerror)) return message -def getcommiteditor(edit=False, finishdesc=None, extramsg=None, **opts): +def mergeeditform(ctxorbool, baseform): + """build appropriate editform from ctxorbool and baseform + + 'cxtorbool' is one of a ctx to be committed, or a bool whether + merging is committed. + + This returns editform 'baseform' with '.merge' if merging is + committed, or one with '.normal' suffix otherwise. + """ + if isinstance(ctxorbool, bool): + if ctxorbool: + return baseform + ".merge" + elif 1 < len(ctxorbool.parents()): + return baseform + ".merge" + + return baseform + ".normal" + +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 +140,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 +150,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 +610,6 @@ tmpname, message, user, date, branch, nodeid, p1, p2 = \ patch.extract(ui, hunk) - editor = getcommiteditor(**opts) update = not opts.get('bypass') strip = opts["strip"] sim = float(opts.get('similarity') or 0) @@ -667,6 +690,11 @@ m = None else: m = scmutil.matchfiles(repo, files or []) + editform = mergeeditform(repo[None], 'import.normal') + if opts.get('exact'): + editor = None + else: + editor = getcommiteditor(editform=editform, **opts) n = repo.commit(message, opts.get('user') or user, opts.get('date') or date, match=m, editor=editor, force=partial) @@ -683,12 +711,16 @@ files, eolmode=None) except patch.PatchError, e: raise util.Abort(str(e)) + if opts.get('exact'): + editor = None + else: + 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() @@ -1180,9 +1212,14 @@ for repl in marker.succnodes(): ui.write(' ') ui.write(hex(repl)) - ui.write(' %X ' % marker._data[2]) + ui.write(' %X ' % marker.flags()) + parents = marker.parentnodes() + if parents is not None: + ui.write('{%s} ' % ', '.join(hex(p) for p in parents)) + ui.write('(%s) ' % util.datestr(marker.date())) ui.write('{%s}' % (', '.join('%r: %r' % t for t in - sorted(marker.metadata().items())))) + sorted(marker.metadata().items()) + if t[0] != 'date'))) ui.write('\n') def finddate(ui, repo, date): @@ -1578,8 +1615,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 @@ -1603,9 +1646,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 @@ -1637,7 +1677,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 = _makefollowlogfilematcher(repo, match.files(), @@ -2091,7 +2134,7 @@ copied=copied.get(path)) return mctx except KeyError: - raise IOError + return None else: ui.note(_('copying changeset %s to %s\n') % (old, base)) @@ -2100,13 +2143,14 @@ try: return old.filectx(path) except KeyError: - raise IOError + return None user = opts.get('user') or old.user() date = opts.get('date') or old.date() - editor = getcommiteditor(**opts) + editform = mergeeditform(old, '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() @@ -2180,24 +2224,31 @@ 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) # run editor in the repository root olddir = os.getcwd() os.chdir(repo.root) - text = repo.ui.edit(committext, ctx.user(), ctx.extra()) + text = repo.ui.edit(committext, ctx.user(), ctx.extra(), editform=editform) text = re.sub("(?m)^HG:.*(\n|$)", "", text) os.chdir(olddir) @@ -2217,6 +2268,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 @@ -2351,17 +2406,89 @@ # get the list of subrepos that must be reverted targetsubs = sorted(s for s in ctx.substate if m(s)) - # Find status of all file in `names`. (Against working directory parent) + # Find status of all file in `names`. m = scmutil.matchfiles(repo, names) - changes = repo.status(node1=parent, match=m)[:4] - modified, added, removed, deleted = map(set, changes) + + changes = repo.status(node1=node, match=m, + unknown=True, ignored=True, clean=True) + modified = set(changes[0]) + added = set(changes[1]) + removed = set(changes[2]) + _deleted = set(changes[3]) + unknown = set(changes[4]) + unknown.update(changes[5]) + clean = set(changes[6]) + + # split between files known in target manifest and the others + smf = set(mf) + + # determine the exact nature of the deleted changesets + _deletedadded = _deleted - smf + _deletedmodified = _deleted - _deletedadded + added |= _deletedadded + modified |= _deletedmodified + + # We need to account for the state of file in the dirstate + # + # Even, when we revert agains something else than parent. this will + # slightly alter the behavior of revert (doing back up or not, delete + # or just forget etc) + if parent == node: + dsmodified = modified + dsadded = added + dsremoved = removed + modified, added, removed = set(), set(), set() + else: + changes = repo.status(node1=parent, match=m) + dsmodified = set(changes[0]) + dsadded = set(changes[1]) + dsremoved = set(changes[2]) + + # only take into account for removes between wc and target + clean |= dsremoved - removed + dsremoved &= removed + # distinct between dirstate remove and other + removed -= dsremoved + + # tell newly modified apart. + dsmodified &= modified + dsmodified |= modified & dsadded # dirstate added may needs backup + modified -= dsmodified + + # There are three categories of added files + # + # 1. addition that just happened in the dirstate + # (should be forgotten) + # 2. file is added since target revision and has local changes + # (should be backed up and removed) + # 3. file is added since target revision and is clean + # (should be removed) + # + # However we do not need to split them yet. The current revert code + # will automatically recognize (1) when performing operation. And + # the backup system is currently unabled to handle (2). + # + # So we just put them all in the same group. + dsadded = added + + # in case of merge, files that are actually added can be reported as + # modified, we need to post process the result + if p2 != nullid: + if pmf is None: + # only need parent manifest in the merge case, + # so do not read by default + pmf = repo[parent].manifest() + mergeadd = dsmodified - set(pmf) + dsadded |= mergeadd + dsmodified -= mergeadd # if f is a rename, update `names` to also revert the source cwd = repo.getcwd() - for f in added: + for f in dsadded: src = repo.dirstate.copied(f) + # XXX should we check for rename down to target node? if src and src not in names and repo.dirstate[src] == 'r': - removed.add(src) + dsremoved.add(src) names[src] = (repo.pathto(src, cwd), True) ## computation of the action to performs on `names` content. @@ -2376,86 +2503,56 @@ actions = {'revert': ([], _('reverting %s\n')), 'add': ([], _('adding %s\n')), 'remove': ([], removeforget), - 'undelete': ([], _('undeleting %s\n'))} + 'undelete': ([], _('undeleting %s\n')), + 'noop': (None, _('no changes needed to %s\n')), + 'unknown': (None, _('file not managed: %s\n')), + } + + + # should we do a backup? + backup = not opts.get('no_backup') + discard = False disptable = ( # dispatch table: # file state - # action if in target manifest - # action if not in target manifest - # make backup if in target manifest - # make backup if not in target manifest - (modified, (actions['revert'], True), - (actions['remove'], True)), - (added, (actions['revert'], True), - (actions['remove'], False)), - (removed, (actions['undelete'], True), - (None, False)), - (deleted, (actions['revert'], False), - (actions['remove'], False)), + # action + # make backup + (modified, actions['revert'], discard), + (dsmodified, actions['revert'], backup), + (dsadded, actions['remove'], backup), + (removed, actions['add'], backup), + (dsremoved, actions['undelete'], backup), + (clean, actions['noop'], discard), + (unknown, actions['unknown'], discard), ) for abs, (rel, exact) in sorted(names.items()): - # hash on file in target manifest (or None if missing from target) - mfentry = mf.get(abs) # target file to be touch on disk (relative to cwd) target = repo.wjoin(abs) - def handle(xlist, dobackup): - xlist[0].append(abs) - if (dobackup and not opts.get('no_backup') and - os.path.lexists(target) and - abs in ctx and repo[None][abs].cmp(ctx[abs])): - bakname = "%s.orig" % rel - ui.note(_('saving current version of %s as %s\n') % - (rel, bakname)) - if not opts.get('dry_run'): - util.rename(target, bakname) - if ui.verbose or not exact: - msg = xlist[1] - if not isinstance(msg, basestring): - msg = msg(abs) - ui.status(msg % rel) # search the entry in the dispatch table. - # if the file is in any of this sets, it was touched in the working + # if the file is in any of these sets, it was touched in the working # directory parent and we are sure it needs to be reverted. - for table, hit, miss in disptable: + for table, (xlist, msg), dobackup in disptable: if abs not in table: continue - # file has changed in dirstate - if mfentry: - handle(*hit) - elif miss[0] is not None: - handle(*miss) + if xlist is not None: + xlist.append(abs) + if (dobackup and os.path.lexists(target) and + abs in ctx and repo[None][abs].cmp(ctx[abs])): + bakname = "%s.orig" % rel + ui.note(_('saving current version of %s as %s\n') % + (rel, bakname)) + if not opts.get('dry_run'): + util.rename(target, bakname) + if ui.verbose or not exact: + if not isinstance(msg, basestring): + msg = msg(abs) + ui.status(msg % rel) + elif exact: + ui.warn(msg % rel) break - else: - # Not touched in current dirstate. - - # file is unknown in parent, restore older version or ignore. - if abs not in repo.dirstate: - if mfentry: - handle(actions['add'], True) - elif exact: - ui.warn(_('file not managed: %s\n') % rel) - continue - # parent is target, no changes mean no changes - if node == parent: - if exact: - ui.warn(_('no changes needed to %s\n') % rel) - continue - # no change in dirstate but parent and target may differ - if pmf is None: - # only need parent manifest in this unlikely case, - # so do not read by default - pmf = repo[parent].manifest() - if abs in pmf and mfentry: - # if version of file is same in parent and target - # manifests, do nothing - if (pmf[abs] != mfentry or - pmf.flags(abs) != mf.flags(abs)): - handle(actions['revert'], False) - else: - handle(actions['remove'], False) if not opts.get('dry_run'): _performrevert(repo, parents, ctx, actions)
--- a/mercurial/commands.py Sat Aug 30 15:13:02 2014 +0200 +++ b/mercurial/commands.py Sat Aug 30 18:44:59 2014 +0200 @@ -260,6 +260,9 @@ Returns 0 on success. """ + if not pats: + raise util.Abort(_('at least one filename or pattern is required')) + if opts.get('follow'): # --follow is deprecated and now just an alias for -f/--file # to mimic the behavior of Mercurial before version 1.5 @@ -267,10 +270,6 @@ datefunc = ui.quiet and util.shortdate or util.datestr getdate = util.cachefunc(lambda x: datefunc(x[0].date())) - - if not pats: - raise util.Abort(_('at least one filename or pattern is required')) - hexfn = ui.debugflag and hex or short opmap = [('user', ' ', lambda x: ui.shortuser(x[0].user())), @@ -505,11 +504,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 +1385,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 +1438,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 = cmdutil.mergeeditform(repo[None], '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) @@ -1905,8 +1905,8 @@ revs = set((int(r) for r in revs)) def events(): for r in rlog: - yield 'n', (r, list(set(p for p in rlog.parentrevs(r) - if p != -1))) + yield 'n', (r, list(p for p in rlog.parentrevs(r) + if p != -1)) if r in revs: yield 'l', (r, "r%i" % r) elif repo: @@ -1925,8 +1925,8 @@ if newb != b: yield 'a', newb b = newb - yield 'n', (r, list(set(p for p in cl.parentrevs(r) - if p != -1))) + yield 'n', (r, list(p for p in cl.parentrevs(r) + if p != -1)) if tags: ls = labels.get(r) if ls: @@ -2308,6 +2308,9 @@ @command('debugobsolete', [('', 'flags', 0, _('markers flag')), + ('', 'record-parents', False, + _('record parent information for the precursor')), + ('r', 'rev', [], _('display markers relevant to REV')), ] + commitopts2, _('[OBSOLETED [REPLACEMENT] [REPL... ]')) def debugobsolete(ui, repo, precursor=None, *successors, **opts): @@ -2329,9 +2332,9 @@ 'node identifiers') if precursor is not None: + if opts['rev']: + raise util.Abort('cannot select revision when creating marker') metadata = {} - if 'date' in opts: - metadata['date'] = opts['date'] metadata['user'] = opts['user'] or ui.username() succs = tuple(parsenodeid(succ) for succ in successors) l = repo.lock() @@ -2339,8 +2342,22 @@ tr = repo.transaction('debugobsolete') try: try: - repo.obsstore.create(tr, parsenodeid(precursor), succs, - opts['flags'], metadata) + date = opts.get('date') + if date: + date = util.parsedate(date) + else: + date = None + prec = parsenodeid(precursor) + parents = None + if opts['record_parents']: + if prec not in repo.unfiltered(): + raise util.Abort('cannot used --record-parents on ' + 'unknown changesets') + parents = repo.unfiltered()[prec].parents() + parents = tuple(p.node() for p in parents) + repo.obsstore.create(tr, prec, succs, opts['flags'], + parents=parents, date=date, + metadata=metadata) tr.close() except ValueError, exc: raise util.Abort(_('bad obsmarker input: %s') % exc) @@ -2349,7 +2366,15 @@ finally: l.release() else: - for m in obsolete.allmarkers(repo): + if opts['rev']: + revs = scmutil.revrange(repo, opts['rev']) + nodes = [repo[r].node() for r in revs] + markers = list(obsolete.getmarkers(repo, nodes=nodes)) + markers.sort(key=lambda x: x._data) + else: + markers = obsolete.getmarkers(repo) + + for m in markers: cmdutil.showmarker(ui, m) @command('debugpathcomplete', @@ -2511,24 +2536,36 @@ if opts.get("dump"): numrevs = len(r) ui.write("# rev p1rev p2rev start end deltastart base p1 p2" - " rawsize totalsize compression heads\n") + " rawsize totalsize compression heads chainlen\n") ts = 0 heads = set() + rindex = r.index + + def chainbaseandlen(rev): + clen = 0 + base = rindex[rev][3] + while base != rev: + clen += 1 + rev = base + base = rindex[rev][3] + return base, clen + for rev in xrange(numrevs): dbase = r.deltaparent(rev) if dbase == -1: dbase = rev - cbase = r.chainbase(rev) + cbase, clen = chainbaseandlen(rev) p1, p2 = r.parentrevs(rev) rs = r.rawsize(rev) ts = ts + rs heads -= set(r.parentrevs(rev)) heads.add(rev) - ui.write("%5d %5d %5d %5d %5d %10d %4d %4d %4d %7d %9d %11d %5d\n" % + ui.write("%5d %5d %5d %5d %5d %10d %4d %4d %4d %7d %9d " + "%11d %5d %8d\n" % (rev, p1, p2, r.start(rev), r.end(rev), r.start(dbase), r.start(cbase), r.start(p1), r.start(p2), - rs, ts, ts / r.end(rev), len(heads))) + rs, ts, ts / r.end(rev), len(heads), clen)) return 0 v = r.version @@ -3057,6 +3094,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, @@ -3080,6 +3118,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 @@ -3087,7 +3129,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 @@ -3124,7 +3167,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']: @@ -3153,61 +3196,68 @@ 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: - try: - r = repo[n].rev() - except error.RepoLookupError: - r = None - 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: + try: + r = repo[n].rev() + except error.RepoLookupError: + r = None + if r in revs: + ui.warn(_('skipping revision %s (already grafted to %s)\n') + % (r, rev)) + revs.remove(r) + elif ids[n] in revs: + if r is None: + ui.warn(_('skipping already grafted revision %s ' + '(%s also has unknown origin %s)\n') + % (ids[n], rev, n)) + else: + 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: - if r is None: - ui.warn(_('skipping already grafted revision %s ' - '(%s also has unknown origin %s)\n') - % (ids[n], rev, n)) - else: - 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: @@ -3851,6 +3901,8 @@ raise util.Abort(_('similarity must be between 0 and 100')) if sim and not update: raise util.Abort(_('cannot use --similarity with --bypass')) + if opts.get('exact') and opts.get('edit'): + raise util.Abort(_('cannot use --exact with --edit')) if update: cmdutil.checkunfinished(repo) @@ -4039,11 +4091,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: @@ -4572,17 +4624,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 @@ -5586,7 +5643,7 @@ ui.write(_('commit: %s\n') % t.strip()) # all ancestors of branch heads - all ancestors of parent = new csets - new = len(repo.changelog.findmissing([ctx.node() for ctx in parents], + new = len(repo.changelog.findmissing([pctx.node() for pctx in parents], bheads)) if new == 0: @@ -5797,7 +5854,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 Sat Aug 30 15:13:02 2014 +0200 +++ b/mercurial/config.py Sat Aug 30 18:44:59 2014 +0200 @@ -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 Sat Aug 30 15:13:02 2014 +0200 +++ b/mercurial/context.py Sat Aug 30 18:44:59 2014 +0200 @@ -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, @@ -347,7 +347,10 @@ def makememctx(repo, parents, text, user, date, branch, files, store, editor=None): def getfilectx(repo, memctx, path): - data, (islink, isexec), copied = store.getfile(path) + data, mode, copied = store.getfile(path) + if data is None: + return None + islink, isexec = mode return memfilectx(repo, path, data, islink=islink, isexec=isexec, copied=copied, memctx=memctx) extra = {} @@ -600,6 +603,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 @@ -713,6 +719,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 @@ -730,9 +740,9 @@ return True def parents(self): - p = self._path + _path = self._path fl = self._filelog - pl = [(p, n, fl) for n in self._filelog.parents(self._filenode)] + pl = [(_path, n, fl) for n in self._filelog.parents(self._filenode)] r = self._filelog.renamed(self._filenode) if r: @@ -762,19 +772,16 @@ this returns fixed value(False is used) as linenumber, if "linenumber" parameter is "False".''' - def decorate_compat(text, rev): - return ([rev] * len(text.splitlines()), text) - - def without_linenumber(text, rev): - return ([(rev, False)] * len(text.splitlines()), text) - - def with_linenumber(text, rev): - size = len(text.splitlines()) - return ([(rev, i) for i in xrange(1, size + 1)], text) - - decorate = (((linenumber is None) and decorate_compat) or - (linenumber and with_linenumber) or - without_linenumber) + if linenumber is None: + def decorate(text, rev): + return ([rev] * len(text.splitlines()), text) + elif linenumber: + def decorate(text, rev): + size = len(text.splitlines()) + return ([(rev, i) for i in xrange(1, size + 1)], text) + else: + def decorate(text, rev): + return ([(rev, False)] * len(text.splitlines()), text) def pair(parent, child): blocks = mdiff.allblocks(parent[1], child[1], opts=diffopts, @@ -1146,6 +1153,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]): @@ -1548,6 +1558,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(). @@ -1575,6 +1593,12 @@ supported by util.parsedate() and defaults to current date, extra is a dictionary of metadata or is left empty. """ + + # Mercurial <= 3.1 expects the filectxfn to raise IOError for missing files. + # Extensions that need to retain compatibility across Mercurial 3.1 can use + # this field to determine what to do in filectxfn. + _returnnoneformissingfiles = True + def __init__(self, repo, parents, text, files, filectxfn, user=None, date=None, extra=None, editor=False): super(memctx, self).__init__(repo, text, user, date, extra) @@ -1588,6 +1612,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' @@ -1597,7 +1635,9 @@ self._repo.savecommitmessage(self._text) def filectx(self, path, filelog=None): - """get a file context from the working directory""" + """get a file context from the working directory + + Returns None if file doesn't exist and should be removed.""" return self._filectxfn(self._repo, self, path) def commit(self): @@ -1615,7 +1655,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: @@ -1652,9 +1692,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 Sat Aug 30 15:13:02 2014 +0200 +++ b/mercurial/dirstate.py Sat Aug 30 18:44:59 2014 +0200 @@ -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/dispatch.py Sat Aug 30 15:13:02 2014 +0200 +++ b/mercurial/dispatch.py Sat Aug 30 18:44:59 2014 +0200 @@ -58,6 +58,8 @@ if len(inst.args) > 1: ferr.write(_("hg: parse error at %s: %s\n") % (inst.args[1], inst.args[0])) + if (inst.args[0][0] == ' '): + ferr.write(_("unexpected leading whitespace\n")) else: ferr.write(_("hg: parse error: %s\n") % inst.args[0]) return -1 @@ -155,6 +157,8 @@ if len(inst.args) > 1: ui.warn(_("hg: parse error at %s: %s\n") % (inst.args[1], inst.args[0])) + if (inst.args[0][0] == ' '): + ui.warn(_("unexpected leading whitespace\n")) else: ui.warn(_("hg: parse error: %s\n") % inst.args[0]) return -1 @@ -331,17 +335,40 @@ args = shlex.split(cmd) return args + givenargs +def aliasinterpolate(name, args, cmd): + '''interpolate args into cmd for shell aliases + + This also handles $0, $@ and "$@". + ''' + # util.interpolate can't deal with "$@" (with quotes) because it's only + # built to match prefix + patterns. + replacemap = dict(('$%d' % (i + 1), arg) for i, arg in enumerate(args)) + replacemap['$0'] = name + replacemap['$$'] = '$' + replacemap['$@'] = ' '.join(args) + # Typical Unix shells interpolate "$@" (with quotes) as all the positional + # parameters, separated out into words. Emulate the same behavior here by + # quoting the arguments individually. POSIX shells will then typically + # tokenize each argument into exactly one word. + replacemap['"$@"'] = ' '.join(util.shellquote(arg) for arg in args) + # escape '\$' for regex + regex = '|'.join(replacemap.keys()).replace('$', r'\$') + r = re.compile(regex) + return r.sub(lambda x: replacemap[x.group()], cmd) + class cmdalias(object): def __init__(self, name, definition, cmdtable): self.name = self.cmd = name self.cmdname = '' self.definition = definition + self.fn = None self.args = [] self.opts = [] self.help = '' self.norepo = True self.optionalrepo = False - self.badalias = False + self.badalias = None + self.unknowncmd = False try: aliases, entry = cmdutil.findcmd(self.name, cmdtable) @@ -354,11 +381,7 @@ self.shadows = False if not self.definition: - def fn(ui, *args): - ui.warn(_("no definition for alias '%s'\n") % self.name) - return -1 - self.fn = fn - self.badalias = True + self.badalias = _("no definition for alias '%s'") % self.name return if self.definition.startswith('!'): @@ -376,10 +399,7 @@ % (int(m.groups()[0]), self.name)) return '' cmd = re.sub(r'\$(\d+|\$)', _checkvar, self.definition[1:]) - replace = dict((str(i + 1), arg) for i, arg in enumerate(args)) - replace['0'] = self.name - replace['@'] = ' '.join(args) - cmd = util.interpolate(r'\$', replace, cmd, escape_prefix=True) + cmd = aliasinterpolate(self.name, args, cmd) return util.system(cmd, environ=env, out=ui.fout) self.fn = fn return @@ -387,26 +407,17 @@ try: args = shlex.split(self.definition) except ValueError, inst: - def fn(ui, *args): - ui.warn(_("error in definition for alias '%s': %s\n") - % (self.name, inst)) - return -1 - self.fn = fn - self.badalias = True + self.badalias = (_("error in definition for alias '%s': %s") + % (self.name, inst)) return self.cmdname = cmd = args.pop(0) args = map(util.expandpath, args) for invalidarg in ("--cwd", "-R", "--repository", "--repo", "--config"): if _earlygetopt([invalidarg], args): - def fn(ui, *args): - ui.warn(_("error in definition for alias '%s': %s may only " - "be given on the command line\n") - % (self.name, invalidarg)) - return -1 - - self.fn = fn - self.badalias = True + self.badalias = (_("error in definition for alias '%s': %s may " + "only be given on the command line") + % (self.name, invalidarg)) return try: @@ -427,26 +438,24 @@ self.__doc__ = self.fn.__doc__ except error.UnknownCommand: - def fn(ui, *args): - ui.warn(_("alias '%s' resolves to unknown command '%s'\n") \ - % (self.name, cmd)) + self.badalias = (_("alias '%s' resolves to unknown command '%s'") + % (self.name, cmd)) + self.unknowncmd = True + except error.AmbiguousCommand: + self.badalias = (_("alias '%s' resolves to ambiguous command '%s'") + % (self.name, cmd)) + + def __call__(self, ui, *args, **opts): + if self.badalias: + hint = None + if self.unknowncmd: try: # check if the command is in a disabled extension - commands.help_(ui, cmd, unknowncmd=True) + cmd, ext = extensions.disabledcmd(ui, self.cmdname)[:2] + hint = _("'%s' is provided by '%s' extension") % (cmd, ext) except error.UnknownCommand: pass - return -1 - self.fn = fn - self.badalias = True - except error.AmbiguousCommand: - def fn(ui, *args): - ui.warn(_("alias '%s' resolves to ambiguous command '%s'\n") \ - % (self.name, cmd)) - return -1 - self.fn = fn - self.badalias = True - - def __call__(self, ui, *args, **opts): + raise util.Abort(self.badalias, hint=hint) if self.shadows: ui.debug("alias '%s' shadows command '%s'\n" % (self.name, self.cmdname))
--- a/mercurial/exchange.py Sat Aug 30 15:13:02 2014 +0200 +++ b/mercurial/exchange.py Sat Aug 30 18:44:59 2014 +0200 @@ -77,8 +77,59 @@ 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() + # outgoing bookmarks + self.outbookmarks = [] + + @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,9 +187,9 @@ and pushop.remote.capable('bundle2-exp')): _pushbundle2(pushop) _pushchangeset(pushop) - _pushcomputecommonheads(pushop) _pushsyncphase(pushop) _pushobsolete(pushop) + _pushbookmark(pushop) finally: if lock is not None: lock.release() @@ -146,11 +197,41 @@ if locallock is not None: locallock.release() - _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 +243,66 @@ 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): + if (obsolete._enabled + and pushop.repo.obsstore + and 'obsolete' in pushop.remote.listkeys('namespaces')): + pushop.outobsmarkers = pushop.repo.obsstore + +@pushdiscovery('bookmarks') +def _pushdiscoverybookmarks(pushop): + ui = pushop.ui + repo = pushop.repo.unfiltered() + remote = pushop.remote + ui.debug("checking for updated bookmarks\n") + ancestors = () + if pushop.revs: + revnums = map(repo.changelog.rev, pushop.revs) + ancestors = repo.changelog.ancestors(revnums, inclusive=True) + remotebookmark = remote.listkeys('bookmarks') + + comp = bookmarks.compare(repo, repo._bookmarks, remotebookmark, srchex=hex) + addsrc, adddst, advsrc, advdst, diverge, differ, invalid = comp + for b, scid, dcid in advsrc: + if not ancestors or repo[scid].rev() in ancestors: + pushop.outbookmarks.append((b, dcid, scid)) + def _pushcheckoutgoing(pushop): outgoing = pushop.outgoing unfi = pushop.repo.unfiltered() @@ -201,6 +342,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 @@ -210,7 +376,6 @@ return pushop.stepsdone.add('changesets') # Send known heads to the server for race detection. - pushop.stepsdone.add('changesets') if not _pushcheckoutgoing(pushop): return pushop.repo.prepushoutgoinghooks(pushop.repo, @@ -227,8 +392,71 @@ 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 + +@b2partsgenerator('bookmarks') +def _pushb2bookmarks(pushop, bundler): + """handle phase push through bundle2""" + if 'bookmarks' in pushop.stepsdone: + return + b2caps = bundle2.bundle2caps(pushop.remote) + if 'b2x:pushkey' not in b2caps: + return + pushop.stepsdone.add('bookmarks') + part2book = [] + enc = pushkey.encode + for book, old, new in pushop.outbookmarks: + part = bundler.newpart('b2x:pushkey') + part.addparam('namespace', enc('bookmarks')) + part.addparam('key', enc(book)) + part.addparam('old', enc(old)) + part.addparam('new', enc(new)) + part2book.append((part.id, book)) + def handlereply(op): + for partid, book in part2book: + partrep = op.records.getreplies(partid) + results = partrep['pushkey'] + assert len(results) <= 1 + if not results: + pushop.ui.warn(_('server ignored bookmark %s update\n') % book) + else: + ret = int(results[0]['return']) + if ret: + pushop.ui.status(_("updating bookmark %s\n") % book) + else: + pushop.ui.warn(_('updating bookmark %s failed!\n') % book) + return handlereply + def _pushbundle2(pushop): """push data to the remote using bundle2 @@ -240,7 +468,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 +536,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 +570,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 +631,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 +649,15 @@ 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 - if (obsolete._enabled and repo.obsstore and - 'obsolete' in remote.listkeys('namespaces')): + pushop.stepsdone.add('obsmarkers') + if (pushop.outobsmarkers): 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] @@ -461,20 +668,13 @@ def _pushbookmark(pushop): """Update bookmark position on remote""" + if pushop.ret == 0 or 'bookmarks' in pushop.stepsdone: + return + pushop.stepsdone.add('bookmarks') ui = pushop.ui - repo = pushop.repo.unfiltered() remote = pushop.remote - ui.debug("checking for updated bookmarks\n") - revnums = map(repo.changelog.rev, pushop.revs or []) - ancestors = [a for a in repo.changelog.ancestors(revnums, inclusive=True)] - (addsrc, adddst, advsrc, advdst, diverge, differ, invalid - ) = bookmarks.compare(repo, repo._bookmarks, remote.listkeys('bookmarks'), - srchex=hex) - - for b, scid, dcid in advsrc: - if ancestors and repo[scid].rev() not in ancestors: - continue - if remote.pushkey('bookmarks', b, dcid, scid): + for b, old, new in pushop.outbookmarks: + if remote.pushkey('bookmarks', b, old, new): ui.status(_("updating bookmark %s\n") % b) else: ui.warn(_('updating bookmark %s failed!\n') % b) @@ -673,14 +873,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 +941,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 Sat Aug 30 15:13:02 2014 +0200 +++ b/mercurial/filemerge.py Sat Aug 30 18:44:59 2014 +0200 @@ -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.py Sat Aug 30 15:13:02 2014 +0200 +++ b/mercurial/help.py Sat Aug 30 18:44:59 2014 +0200 @@ -31,7 +31,7 @@ doc = ''.join(rst) return doc -def optrst(options, verbose): +def optrst(header, options, verbose): data = [] multioccur = False for option in options: @@ -59,10 +59,11 @@ data.append((so, lo, desc)) - rst = minirst.maketable(data, 1) + if multioccur: + header += (_(" ([+] can be repeated)")) - if multioccur: - rst.append(_("\n[+] marked option can be specified multiple times\n")) + rst = ['\n%s:\n\n' % header] + rst.extend(minirst.maketable(data, 1)) return ''.join(rst) @@ -234,11 +235,13 @@ rst = [] # check if it's an invalid alias and display its error if it is - if getattr(entry[0], 'badalias', False): - if not unknowncmd: - ui.pushbuffer() - entry[0](ui) - rst.append(ui.popbuffer()) + if getattr(entry[0], 'badalias', None): + rst.append(entry[0].badalias + '\n') + if entry[0].unknowncmd: + try: + rst.extend(helpextcmd(entry[0].cmdname)) + except error.UnknownCommand: + pass return rst # synopsis @@ -276,31 +279,27 @@ mod = extensions.find(name) doc = gettext(mod.__doc__) or '' if '\n' in doc.strip(): - msg = _('use "hg help -e %s" to show help for ' - 'the %s extension') % (name, name) + msg = _('(use "hg help -e %s" to show help for ' + 'the %s extension)') % (name, name) rst.append('\n%s\n' % msg) except KeyError: pass # options if not ui.quiet and entry[1]: - rst.append('\n%s\n\n' % _("options:")) - rst.append(optrst(entry[1], ui.verbose)) + rst.append(optrst(_("options"), entry[1], ui.verbose)) if ui.verbose: - rst.append('\n%s\n\n' % _("global options:")) - rst.append(optrst(commands.globalopts, ui.verbose)) + rst.append(optrst(_("global options"), + commands.globalopts, ui.verbose)) if not ui.verbose: if not full: - rst.append(_('\nuse "hg help %s" to show the full help text\n') + rst.append(_('\n(use "hg %s -h" to show more help)\n') % name) elif not ui.quiet: - omitted = _('use "hg -v help %s" to show more complete' - ' help and the global options') % name - notomitted = _('use "hg -v help %s" to show' - ' the global options') % name - indicateomitted(rst, omitted, notomitted) + rst.append(_('\n(some details hidden, use --verbose ' + 'to show complete help)')) return rst @@ -366,30 +365,25 @@ for t, desc in topics: rst.append(" :%s: %s\n" % (t, desc)) - optlist = [] - if not ui.quiet: - if ui.verbose: - optlist.append((_("global options:"), commands.globalopts)) - if name == 'shortlist': - optlist.append((_('use "hg help" for the full list ' - 'of commands'), ())) + if ui.quiet: + pass + elif ui.verbose: + rst.append('\n%s\n' % optrst(_("global options"), + commands.globalopts, ui.verbose)) + if name == 'shortlist': + rst.append(_('\n(use "hg help" for the full list ' + 'of commands)\n')) + else: + if name == 'shortlist': + rst.append(_('\n(use "hg help" for the full list of commands ' + 'or "hg -v" for details)\n')) + elif name and not full: + rst.append(_('\n(use "hg help %s" to show the full help ' + 'text)\n') % name) else: - if name == 'shortlist': - msg = _('use "hg help" for the full list of commands ' - 'or "hg -v" for details') - elif name and not full: - msg = _('use "hg help %s" to show the full help ' - 'text') % name - else: - msg = _('use "hg -v help%s" to show builtin aliases and ' - 'global options') % (name and " " + name or "") - optlist.append((msg, ())) - - if optlist: - for title, options in optlist: - rst.append('\n%s\n' % title) - if options: - rst.append('\n%s\n' % optrst(options, ui.verbose)) + rst.append(_('\n(use "hg help -v%s" to show built-in aliases ' + 'and global options)\n') + % (name and " " + name or "")) return rst def helptopic(name): @@ -408,8 +402,8 @@ rst += [" %s\n" % l for l in doc().splitlines()] if not ui.verbose: - omitted = (_('use "hg help -v %s" to show more complete help') % - name) + omitted = _('(some details hidden, use --verbose' + ' to show complete help)') indicateomitted(rst, omitted) try: @@ -440,8 +434,8 @@ rst.append('\n') if not ui.verbose: - omitted = (_('use "hg help -v %s" to show more complete help') % - name) + omitted = _('(some details hidden, use --verbose' + ' to show complete help)') indicateomitted(rst, omitted) if mod: @@ -452,8 +446,8 @@ modcmds = set([c.split('|', 1)[0] for c in ct]) rst.extend(helplist(modcmds.__contains__)) else: - rst.append(_('use "hg help extensions" for information on enabling ' - 'extensions\n')) + rst.append(_('(use "hg help extensions" for information on enabling' + ' extensions)\n')) return rst def helpextcmd(name): @@ -464,8 +458,8 @@ rst = listexts(_("'%s' is provided by the following " "extension:") % cmd, {ext: doc}, indent=4) rst.append('\n') - rst.append(_('use "hg help extensions" for information on enabling ' - 'extensions\n')) + rst.append(_('(use "hg help extensions" for information on enabling ' + 'extensions)\n')) return rst
--- a/mercurial/help/config.txt Sat Aug 30 15:13:02 2014 +0200 +++ b/mercurial/help/config.txt Sat Aug 30 18:44:59 2014 +0200 @@ -229,8 +229,9 @@ Positional arguments like ``$1``, ``$2``, etc. in the alias definition expand to the command arguments. Unmatched arguments are removed. ``$0`` expands to the alias name and ``$@`` expands to all -arguments separated by a space. These expansions happen before the -command is passed to the shell. +arguments separated by a space. ``"$@"`` (with quotes) expands to all +arguments quoted individually and separated by a space. These expansions +happen before the command is passed to the shell. Shell aliases are executed in an environment where ``$HG`` expands to the path of the Mercurial that was used to execute the alias. This is @@ -388,6 +389,57 @@ - :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.merge`` for :hg:`commit --amend` on merges +- ``changeset.commit.amend.normal`` for :hg:`commit --amend` on other +- ``changeset.commit.normal.merge`` for :hg:`commit` on merges +- ``changeset.commit.normal.normal`` for :hg:`commit` on other +- ``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.merge`` for :hg:`import` on merges +- ``changeset.import.normal.normal`` for :hg:`import` on other +- ``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.merge`` for :hg:`rebase` on merges +- ``changeset.rebase.normal`` for :hg:`rebase` on other +- ``changeset.shelve.shelve`` for :hg:`shelve` +- ``changeset.tag.add`` for :hg:`tag` without ``--remove`` +- ``changeset.tag.remove`` for :hg:`tag --remove` +- ``changeset.transplant.merge`` for :hg:`transplant` on merges +- ``changeset.transplant.normal`` for :hg:`transplant` on other + +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. + +At the external editor invocation for committing, corresponding +dot-separated list of names without ``changeset.`` prefix +(e.g. ``commit.normal.normal``) is in ``HGEDITFORM`` environment variable. + +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 +964,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/hg.py Sat Aug 30 15:13:02 2014 +0200 +++ b/mercurial/hg.py Sat Aug 30 18:44:59 2014 +0200 @@ -11,7 +11,7 @@ from node import hex, nullid import localrepo, bundlerepo, unionrepo, httppeer, sshpeer, statichttprepo import bookmarks, lock, util, extensions, error, node, scmutil, phases, url -import cmdutil, discovery +import cmdutil, discovery, repoview import merge as mergemod import verify as verifymod import errno, os, shutil @@ -366,13 +366,20 @@ # Recomputing branch cache might be slow on big repos, # so just copy it + def copybranchcache(fname): + srcbranchcache = srcrepo.join('cache/%s' % fname) + dstbranchcache = os.path.join(dstcachedir, fname) + if os.path.exists(srcbranchcache): + if not os.path.exists(dstcachedir): + os.mkdir(dstcachedir) + util.copyfile(srcbranchcache, dstbranchcache) + dstcachedir = os.path.join(destpath, 'cache') - srcbranchcache = srcrepo.sjoin('cache/branch2') - dstbranchcache = os.path.join(dstcachedir, 'branch2') - if os.path.exists(srcbranchcache): - if not os.path.exists(dstcachedir): - os.mkdir(dstcachedir) - util.copyfile(srcbranchcache, dstbranchcache) + # In local clones we're copying all nodes, not just served + # ones. Therefore copy all branchcaches over. + copybranchcache('branch2') + for cachename in repoview.filtertable: + copybranchcache('branch2-%s' % cachename) # we need to re-init the repo after manually copying the data # into it
--- a/mercurial/hgweb/hgweb_mod.py Sat Aug 30 15:13:02 2014 +0200 +++ b/mercurial/hgweb/hgweb_mod.py Sat Aug 30 18:44:59 2014 +0200 @@ -110,7 +110,7 @@ # compare changelog size in addition to mtime to catch # rollbacks made less than a second ago if st.st_mtime != self.mtime or st.st_size != self.size: - r = hg.repository(self.repo.baseui, self.repo.root) + r = hg.repository(self.repo.baseui, self.repo.url()) self.repo = self._getview(r) self.maxchanges = int(self.config("web", "maxchanges", 10)) self.stripecount = int(self.config("web", "stripes", 1)) @@ -392,5 +392,5 @@ } def check_perm(self, req, op): - for hook in permhooks: - hook(self, req, op) + for permhook in permhooks: + permhook(self, req, op)
--- a/mercurial/hgweb/webcommands.py Sat Aug 30 15:13:02 2014 +0200 +++ b/mercurial/hgweb/webcommands.py Sat Aug 30 18:44:59 2014 +0200 @@ -1069,7 +1069,7 @@ topicname = req.form.get('node', [None])[0] if not topicname: def topics(**map): - for entries, summary, _ in helpmod.helptable: + for entries, summary, _doc in helpmod.helptable: yield {'topic': entries[0], 'summary': summary} early, other = [], []
--- a/mercurial/i18n.py Sat Aug 30 15:13:02 2014 +0200 +++ b/mercurial/i18n.py Sat Aug 30 18:44:59 2014 +0200 @@ -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 Sat Aug 30 15:13:02 2014 +0200 +++ b/mercurial/localrepo.py Sat Aug 30 18:44:59 2014 +0200 @@ -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 @@ -674,8 +676,7 @@ if not self._tagscache.tagslist: l = [] for t, n in self.tags().iteritems(): - r = self.changelog.rev(n) - l.append((r, t, n)) + l.append((self.changelog.rev(n), t, n)) self._tagscache.tagslist = [(t, n) for r, t, n in sorted(l)] return self._tagscache.tagslist @@ -1087,8 +1088,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 @@ -1395,9 +1394,12 @@ self.ui.note(f + "\n") try: fctx = ctx[f] - new[f] = self._filecommit(fctx, m1, m2, linkrev, trp, - changed) - m1.set(f, fctx.flags()) + if fctx is None: + removed.append(f) + else: + new[f] = self._filecommit(fctx, m1, m2, linkrev, + trp, changed) + m1.set(f, fctx.flags()) except OSError, inst: self.ui.warn(_("trouble committing %s!\n") % f) raise @@ -1405,9 +1407,7 @@ errcode = getattr(inst, 'errno', errno.ENOENT) if error or errcode and errcode != errno.ENOENT: self.ui.warn(_("trouble committing %s!\n") % f) - raise - else: - removed.append(f) + raise # update manifest m1.update(new) @@ -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/merge.py Sat Aug 30 15:13:02 2014 +0200 +++ b/mercurial/merge.py Sat Aug 30 18:44:59 2014 +0200 @@ -10,7 +10,7 @@ from node import nullid, nullrev, hex, bin from i18n import _ from mercurial import obsolete -import error, util, filemerge, copies, subrepo, worker, dicthelpers +import error as errormod, util, filemerge, copies, subrepo, worker, dicthelpers import errno, os, shutil _pack = struct.pack @@ -1011,7 +1011,7 @@ # but currently we are only checking the branch tips. try: node = repo.branchtip(wc.branch()) - except error.RepoLookupError: + except errormod.RepoLookupError: if wc.branch() == "default": # no default branch! node = repo.lookup("tip") # update to tip else:
--- a/mercurial/obsolete.py Sat Aug 30 15:13:02 2014 +0200 +++ b/mercurial/obsolete.py Sat Aug 30 18:44:59 2014 +0200 @@ -168,7 +168,34 @@ 'short, %d bytes expected, got %d') % (mdsize, len(metadata))) off += mdsize - yield (pre, sucs, flags, metadata) + meta = decodemeta(metadata) + try: + when, offset = decodemeta(metadata).pop('date', '0 0').split(' ') + date = float(when), int(offset) + except ValueError: + date = (0., 0) + parents = None + if 'p2' in meta: + parents = (meta.pop('p1', None), meta.pop('p2', None)) + elif 'p1' in meta: + parents = (meta.pop('p1', None),) + elif 'p0' in meta: + parents = () + if parents is not None: + try: + parents = tuple(node.bin(p) for p in parents) + # if parent content is not a nodeid, drop the data + for p in parents: + if len(p) != 20: + parents = None + break + except TypeError: + # if content cannot be translated to nodeid drop the data. + parents = None + + metadata = encodemeta(meta) + + yield (pre, sucs, flags, metadata, date, parents) def encodemeta(meta): """Return encoded metadata string to string mapping. @@ -215,6 +242,10 @@ """List of successor changesets node identifiers""" return self._data[1] + def parentnodes(self): + """Parents of the precursors (None if not recorded)""" + return self._data[5] + def metadata(self): """Decoded metadata dictionary""" if self._decodedmeta is None: @@ -223,8 +254,11 @@ def date(self): """Creation date as (unixtime, offset)""" - parts = self.metadata()['date'].split(' ') - return (float(parts[0]), int(parts[1])) + return self._data[4] + + def flags(self): + """The flags field of the marker""" + return self._data[2] class obsstore(object): """Store obsolete markers @@ -232,15 +266,25 @@ Markers can be accessed with two mappings: - precursors[x] -> set(markers on precursors edges of x) - successors[x] -> set(markers on successors edges of x) + - children[x] -> set(markers on precursors edges of children(x) """ + fields = ('prec', 'succs', 'flag', 'meta', 'date', 'parents') + # prec: nodeid, precursor changesets + # succs: tuple of nodeid, successor changesets (0-N length) + # flag: integer, flag field carrying modifier for the markers (see doc) + # meta: binary blob, encoded metadata dictionary + # date: (float, int) tuple, date of marker creation + # parents: (tuple of nodeid) or None, parents of precursors + # None is used when no data has been recorded + def __init__(self, sopener): # caches for various obsolescence related cache self.caches = {} self._all = [] - # new markers to serialize self.precursors = {} self.successors = {} + self.children = {} self.sopener = sopener data = sopener.tryread('obsstore') if data: @@ -255,7 +299,8 @@ def __nonzero__(self): return bool(self._all) - def create(self, transaction, prec, succs=(), flag=0, metadata=None): + def create(self, transaction, prec, succs=(), flag=0, parents=None, + date=None, metadata=None): """obsolete: add a new obsolete marker * ensuring it is hashable @@ -270,8 +315,12 @@ """ if metadata is None: metadata = {} - if 'date' not in metadata: - metadata['date'] = "%d %d" % util.makedate() + if date is None: + if 'date' in metadata: + # as a courtesy for out-of-tree extensions + date = util.parsedate(metadata.pop('date')) + else: + date = util.makedate() if len(prec) != 20: raise ValueError(prec) for succ in succs: @@ -279,7 +328,8 @@ raise ValueError(succ) if prec in succs: raise ValueError(_('in-marker cycle with %s') % node.hex(prec)) - marker = (str(prec), tuple(succs), int(flag), encodemeta(metadata)) + marker = (str(prec), tuple(succs), int(flag), encodemeta(metadata), + date, parents) return bool(self.add(transaction, [marker])) def add(self, transaction, markers): @@ -329,9 +379,41 @@ self.successors.setdefault(pre, set()).add(mark) for suc in sucs: self.precursors.setdefault(suc, set()).add(mark) + parents = mark[5] + if parents is not None: + for p in parents: + self.children.setdefault(p, set()).add(mark) if node.nullid in self.precursors: raise util.Abort(_('bad obsolescence marker detected: ' 'invalid successors nullid')) + def relevantmarkers(self, nodes): + """return a set of all obsolescence markers relevant to a set of nodes. + + "relevant" to a set of nodes mean: + + - marker that use this changeset as successor + - prune marker of direct children on this changeset + - recursive application of the two rules on precursors of these markers + + It is a set so you cannot rely on order.""" + + pendingnodes = set(nodes) + seenmarkers = set() + seennodes = set(pendingnodes) + precursorsmarkers = self.precursors + children = self.children + while pendingnodes: + direct = set() + for current in pendingnodes: + direct.update(precursorsmarkers.get(current, ())) + pruned = [m for m in children.get(current, ()) if not m[1]] + direct.update(pruned) + direct -= seenmarkers + pendingnodes = set([m[0] for m in direct]) + seenmarkers |= direct + pendingnodes -= seennodes + seennodes |= pendingnodes + return seenmarkers def _encodemarkers(markers, addheader=False): # Kept separate from flushmarkers(), it will be reused for @@ -343,7 +425,16 @@ def _encodeonemarker(marker): - pre, sucs, flags, metadata = marker + pre, sucs, flags, metadata, date, parents = marker + metadata = decodemeta(metadata) + metadata['date'] = '%d %i' % date + if parents is not None: + if not parents: + # mark that we explicitly recorded no parents + metadata['p0'] = '' + for i, p in enumerate(parents): + metadata['p%i' % (i + 1)] = node.hex(p) + metadata = encodemeta(metadata) nbsuc = len(sucs) format = _fmfixed + (_fmnode * nbsuc) data = [nbsuc, len(metadata), flags, pre] @@ -404,11 +495,25 @@ finally: lock.release() -def allmarkers(repo): - """all obsolete markers known in a repository""" - for markerdata in repo.obsstore: +def getmarkers(repo, nodes=None): + """returns markers known in a repository + + If <nodes> is specified, only markers "relevant" to those nodes are are + returned""" + if nodes is None: + rawmarkers = repo.obsstore + else: + rawmarkers = repo.obsstore.relevantmarkers(nodes) + + for markerdata in rawmarkers: yield marker(repo, markerdata) +def relevantmarkers(repo, node): + """all obsolete markers relevant to some revision""" + for markerdata in repo.obsstore.relevantmarkers(node): + yield marker(repo, markerdata) + + def precursormarkers(ctx): """obsolete marker marking this changeset as a successors""" for data in ctx._repo.obsstore.precursors.get(ctx.node(), ()): @@ -750,8 +855,8 @@ obs = set() getrev = repo.changelog.nodemap.get getphase = repo._phasecache.phase - for node in repo.obsstore.successors: - rev = getrev(node) + for n in repo.obsstore.successors: + rev = getrev(n) if rev is not None and getphase(repo, rev): obs.add(rev) return obs @@ -825,7 +930,7 @@ return divergent -def createmarkers(repo, relations, flag=0, metadata=None): +def createmarkers(repo, relations, flag=0, date=None, metadata=None): """Add obsolete markers between changesets in a repo <relations> must be an iterable of (<old>, (<new>, ...)[,{metadata}]) @@ -844,8 +949,6 @@ # prepare metadata if metadata is None: metadata = {} - if 'date' not in metadata: - metadata['date'] = '%i %i' % util.makedate() if 'user' not in metadata: metadata['user'] = repo.ui.username() tr = repo.transaction('add-obsolescence-marker') @@ -862,9 +965,13 @@ % prec) nprec = prec.node() nsucs = tuple(s.node() for s in sucs) + npare = None + if not nsucs: + npare = tuple(p.node() for p in prec.parents()) if nprec in nsucs: raise util.Abort("changeset %s cannot obsolete itself" % prec) - repo.obsstore.create(tr, nprec, nsucs, flag, localmetadata) + repo.obsstore.create(tr, nprec, nsucs, flag, parents=npare, + date=date, metadata=localmetadata) repo.filteredrevcache.clear() tr.close() finally:
--- a/mercurial/patch.py Sat Aug 30 15:13:02 2014 +0200 +++ b/mercurial/patch.py Sat Aug 30 18:44:59 2014 +0200 @@ -382,7 +382,7 @@ def getfile(self, fname): """Return target file data and flags as a (data, (islink, - isexec)) tuple. + isexec)) tuple. Data is None if file is missing/deleted. """ raise NotImplementedError @@ -426,7 +426,12 @@ except OSError, e: if e.errno != errno.ENOENT: raise - return (self.opener.read(fname), (False, isexec)) + try: + return (self.opener.read(fname), (False, isexec)) + except IOError, e: + if e.errno != errno.ENOENT: + raise + return None, None def setfile(self, fname, data, mode, copysource): islink, isexec = mode @@ -528,7 +533,7 @@ if fname in self.data: return self.data[fname] if not self.opener or fname not in self.files: - raise IOError + return None, None, None fn, mode, copied = self.files[fname] return self.opener.read(fn), mode, copied @@ -554,7 +559,7 @@ try: fctx = self.ctx[fname] except error.LookupError: - raise IOError + return None, None flags = fctx.flags() return fctx.data(), ('l' in flags, 'x' in flags) @@ -597,13 +602,12 @@ self.copysource = gp.oldpath self.create = gp.op in ('ADD', 'COPY', 'RENAME') self.remove = gp.op == 'DELETE' - try: - if self.copysource is None: - data, mode = backend.getfile(self.fname) - self.exists = True - else: - data, mode = store.getfile(self.copysource)[:2] - self.exists = backend.exists(self.fname) + if self.copysource is None: + data, mode = backend.getfile(self.fname) + else: + data, mode = store.getfile(self.copysource)[:2] + if data is not None: + self.exists = self.copysource is None or backend.exists(self.fname) self.missing = False if data: self.lines = mdiff.splitnewlines(data) @@ -622,7 +626,7 @@ l = l[:-2] + '\n' nlines.append(l) self.lines = nlines - except IOError: + else: if self.create: self.missing = False if self.mode is None: @@ -1380,6 +1384,8 @@ data, mode = None, None if gp.op in ('RENAME', 'COPY'): data, mode = store.getfile(gp.oldpath)[:2] + # FIXME: failing getfile has never been handled here + assert data is not None if gp.mode: mode = gp.mode if gp.op == 'ADD': @@ -1404,15 +1410,13 @@ elif state == 'git': for gp in values: path = pstrip(gp.oldpath) - try: - data, mode = backend.getfile(path) - except IOError, e: - if e.errno != errno.ENOENT: - raise + data, mode = backend.getfile(path) + if data is None: # The error ignored here will trigger a getfile() # error in a place more appropriate for error # handling, and will not interrupt the patching # process. + pass else: store.setfile(path, data, mode) else:
--- a/mercurial/phases.py Sat Aug 30 15:13:02 2014 +0200 +++ b/mercurial/phases.py Sat Aug 30 18:44:59 2014 +0200 @@ -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/posix.py Sat Aug 30 15:13:02 2014 +0200 +++ b/mercurial/posix.py Sat Aug 30 18:44:59 2014 +0200 @@ -8,6 +8,7 @@ from i18n import _ import encoding import os, sys, errno, stat, getpass, pwd, grp, socket, tempfile, unicodedata +import fcntl posixfile = open normpath = os.path.normpath @@ -432,7 +433,7 @@ def termwidth(): try: - import termios, array, fcntl + import termios, array for dev in (sys.stderr, sys.stdout, sys.stdin): try: try: @@ -567,3 +568,27 @@ def statisexec(st): '''check whether a stat result is an executable file''' return st and (st.st_mode & 0100 != 0) + +def readpipe(pipe): + """Read all available data from a pipe.""" + # We can't fstat() a pipe because Linux will always report 0. + # So, we set the pipe to non-blocking mode and read everything + # that's available. + flags = fcntl.fcntl(pipe, fcntl.F_GETFL) + flags |= os.O_NONBLOCK + oldflags = fcntl.fcntl(pipe, fcntl.F_SETFL, flags) + + try: + chunks = [] + while True: + try: + s = pipe.read() + if not s: + break + chunks.append(s) + except IOError: + break + + return ''.join(chunks) + finally: + fcntl.fcntl(pipe, fcntl.F_SETFL, oldflags)
--- a/mercurial/repair.py Sat Aug 30 15:13:02 2014 +0200 +++ b/mercurial/repair.py Sat Aug 30 18:44:59 2014 +0200 @@ -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/repoview.py Sat Aug 30 15:13:02 2014 +0200 +++ b/mercurial/repoview.py Sat Aug 30 18:44:59 2014 +0200 @@ -7,11 +7,13 @@ # GNU General Public License version 2 or any later version. import copy +import error import phases import util import obsolete +import struct import tags as tagsmod - +from mercurial.i18n import _ def hideablerevs(repo): """Revisions candidates to be hidden @@ -19,13 +21,14 @@ This is a standalone function to help extensions to wrap it.""" return obsolete.getrevs(repo, 'obsolete') -def _gethiddenblockers(repo): - """Get revisions that will block hidden changesets from being filtered +def _getstaticblockers(repo): + """Cacheable revisions blocking hidden changesets from being filtered. + Additional non-cached hidden blockers are computed in _getdynamicblockers. This is a standalone function to help extensions to wrap it.""" assert not repo.changelog.filteredrevs hideable = hideablerevs(repo) - blockers = [] + blockers = set() if hideable: # We use cl to avoid recursive lookup from repo[xxx] cl = repo.changelog @@ -33,29 +36,124 @@ revs = cl.revs(start=firsthideable) tofilter = repo.revs( '(%ld) and children(%ld)', list(revs), list(hideable)) - blockers = [r for r in tofilter if r not in hideable] - for par in repo[None].parents(): - blockers.append(par.rev()) - for bm in repo._bookmarks.values(): - blockers.append(cl.rev(bm)) - tags = {} - tagsmod.readlocaltags(repo.ui, repo, tags, {}) - if tags: - rev, nodemap = cl.rev, cl.nodemap - blockers.extend(rev(t[0]) for t in tags.values() if t[0] in nodemap) + blockers.update([r for r in tofilter if r not in hideable]) + return blockers + +def _getdynamicblockers(repo): + """Non-cacheable revisions blocking hidden changesets from being filtered. + + Get revisions that will block hidden changesets and are likely to change, + but unlikely to create hidden blockers. They won't be cached, so be careful + with adding additional computation.""" + + cl = repo.changelog + blockers = set() + blockers.update([par.rev() for par in repo[None].parents()]) + blockers.update([cl.rev(bm) for bm in repo._bookmarks.values()]) + + tags = {} + tagsmod.readlocaltags(repo.ui, repo, tags, {}) + if tags: + rev, nodemap = cl.rev, cl.nodemap + blockers.update(rev(t[0]) for t in tags.values() if t[0] in nodemap) return blockers +cacheversion = 1 +cachefile = 'cache/hidden' + +def cachehash(repo, hideable): + """return sha1 hash of repository data to identify a valid cache. + + We calculate a sha1 of repo heads and the content of the obsstore and write + it to the cache. Upon reading we can easily validate by checking the hash + against the stored one and discard the cache in case the hashes don't match. + """ + h = util.sha1() + h.update(''.join(repo.heads())) + h.update(str(hash(frozenset(hideable)))) + return h.digest() + +def trywritehiddencache(repo, hideable, hidden): + """write cache of hidden changesets to disk + + Will not write the cache if a wlock cannot be obtained lazily. + The cache consists of a head of 22byte: + 2 byte version number of the cache + 20 byte sha1 to validate the cache + n*4 byte hidden revs + """ + wlock = fh = None + try: + try: + wlock = repo.wlock(wait=False) + # write cache to file + newhash = cachehash(repo, hideable) + sortedset = sorted(hidden) + data = struct.pack('>%ii' % len(sortedset), *sortedset) + fh = repo.vfs.open(cachefile, 'w+b', atomictemp=True) + fh.write(struct.pack(">H", cacheversion)) + fh.write(newhash) + fh.write(data) + except (IOError, OSError): + repo.ui.debug('error writing hidden changesets cache') + except error.LockHeld: + repo.ui.debug('cannot obtain lock to write hidden changesets cache') + finally: + if fh: + fh.close() + if wlock: + wlock.release() + +def tryreadcache(repo, hideable): + """read a cache if the cache exists and is valid, otherwise returns None.""" + hidden = fh = None + try: + if repo.vfs.exists(cachefile): + fh = repo.vfs.open(cachefile, 'rb') + version, = struct.unpack(">H", fh.read(2)) + oldhash = fh.read(20) + newhash = cachehash(repo, hideable) + if (cacheversion, oldhash) == (version, newhash): + # cache is valid, so we can start reading the hidden revs + data = fh.read() + count = len(data) / 4 + hidden = frozenset(struct.unpack('>%ii' % count, data)) + return hidden + finally: + if fh: + fh.close() + def computehidden(repo): """compute the set of hidden revision to filter During most operation hidden should be filtered.""" assert not repo.changelog.filteredrevs + + hidden = frozenset() hideable = hideablerevs(repo) if hideable: cl = repo.changelog - blocked = cl.ancestors(_gethiddenblockers(repo), inclusive=True) - return frozenset(r for r in hideable if r not in blocked) - return frozenset() + hidden = tryreadcache(repo, hideable) + if hidden is None: + blocked = cl.ancestors(_getstaticblockers(repo), inclusive=True) + hidden = frozenset(r for r in hideable if r not in blocked) + trywritehiddencache(repo, hideable, hidden) + elif repo.ui.configbool('experimental', 'verifyhiddencache', True): + blocked = cl.ancestors(_getstaticblockers(repo), inclusive=True) + computed = frozenset(r for r in hideable if r not in blocked) + if computed != hidden: + trywritehiddencache(repo, hideable, computed) + repo.ui.warn(_('Cache inconsistency detected. Please ' + + 'open an issue on http://bz.selenic.com.\n')) + hidden = computed + + # check if we have wd parents, bookmarks or tags pointing to hidden + # changesets and remove those. + dynamic = hidden & _getdynamicblockers(repo) + if dynamic: + blocked = cl.ancestors(dynamic, inclusive=True) + hidden = frozenset(r for r in hidden if r not in blocked) + return hidden def computeunserved(repo): """compute the set of revision that should be filtered when used a server
--- a/mercurial/revlog.py Sat Aug 30 15:13:02 2014 +0200 +++ b/mercurial/revlog.py Sat Aug 30 18:44:59 2014 +0200 @@ -306,6 +306,8 @@ def rev(self, node): try: return self._nodecache[node] + except TypeError: + raise except RevlogError: # parsers.c radix tree lookup failed raise LookupError(node, self.indexfile, _('no node'))
--- a/mercurial/simplemerge.py Sat Aug 30 15:13:02 2014 +0200 +++ b/mercurial/simplemerge.py Sat Aug 30 18:44:59 2014 +0200 @@ -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/sshpeer.py Sat Aug 30 15:13:02 2014 +0200 +++ b/mercurial/sshpeer.py Sat Aug 30 18:44:59 2014 +0200 @@ -103,13 +103,8 @@ return self._caps def readerr(self): - while True: - size = util.fstat(self.pipee).st_size - if size == 0: - break - s = self.pipee.read(size) - if not s: - break + s = util.readpipe(self.pipee) + if s: for l in s.splitlines(): self.ui.status(_("remote: "), l, '\n')
--- a/mercurial/tagmerge.py Sat Aug 30 15:13:02 2014 +0200 +++ b/mercurial/tagmerge.py Sat Aug 30 18:44:59 2014 +0200 @@ -71,7 +71,7 @@ # - put blocks whose nodes come all from p2 first # - write the tag blocks in the sorted order -import tags +import tags as tagsmod import util from node import nullid, hex from i18n import _ @@ -85,8 +85,8 @@ with each tag. Rhis is done because only the line numbers of the first parent are useful for merging ''' - filetags = tags._readtaghist(ui, repo, lines, fn=fn, recode=None, - calcnodelines=True)[1] + filetags = tagsmod._readtaghist(ui, repo, lines, fn=fn, recode=None, + calcnodelines=True)[1] for tagname, taginfo in filetags.items(): if not keeplinenums: for el in taginfo:
--- a/mercurial/templater.py Sat Aug 30 15:13:02 2014 +0200 +++ b/mercurial/templater.py Sat Aug 30 18:44:59 2014 +0200 @@ -8,6 +8,7 @@ from i18n import _ import sys, os, re import util, config, templatefilters, templatekw, parser, error +import revset as revsetmod import types import minirst @@ -370,16 +371,20 @@ ctx = mapping['ctx'] repo = ctx._repo + def query(expr): + m = revsetmod.match(repo.ui, expr) + return m(repo, revsetmod.spanset(repo)) + if len(args) > 1: formatargs = list([a[0](context, mapping, a[1]) for a in args[1:]]) - revs = repo.revs(raw, *formatargs) + revs = query(revsetmod.formatspec(raw, *formatargs)) revs = list([str(r) for r in revs]) else: revsetcache = mapping['cache'].setdefault("revsetcache", {}) if raw in revsetcache: revs = revsetcache[raw] else: - revs = repo.revs(raw) + revs = query(raw) revs = list([str(r) for r in revs]) revsetcache[raw] = revs
--- a/mercurial/transaction.py Sat Aug 30 15:13:02 2014 +0200 +++ b/mercurial/transaction.py Sat Aug 30 18:44:59 2014 +0200 @@ -24,7 +24,7 @@ return _active def _playback(journal, report, opener, entries, backupentries, unlink=True): - for f, o, ignore in entries: + for f, o, _ignore in entries: if o or not unlink: try: fp = opener(f, 'a') @@ -41,7 +41,7 @@ raise backupfiles = [] - for f, b, ignore in backupentries: + for f, b, _ignore in backupentries: filepath = opener.join(f) backuppath = opener.join(b) try: @@ -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() @@ -112,10 +115,10 @@ offsets = [] backups = [] - for f, o, _ in q[0]: + for f, o, _data in q[0]: offsets.append((f, o)) - for f, b, _ in q[1]: + for f, b, _data in q[1]: backups.append((f, b)) d = ''.join(['%s\0%d\n' % (f, o) for f, o in offsets]) @@ -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() @@ -228,7 +265,7 @@ self.opener.unlink(self.journal) if self.opener.isfile(self.backupjournal): self.opener.unlink(self.backupjournal) - for f, b, _ in self.backupentries: + for _f, b, _ignore in self.backupentries: self.opener.unlink(b) self.backupentries = [] self.journal = None
--- a/mercurial/ui.py Sat Aug 30 15:13:02 2014 +0200 +++ b/mercurial/ui.py Sat Aug 30 18:44:59 2014 +0200 @@ -626,6 +626,8 @@ oldout = sys.stdout sys.stdin = self.fin sys.stdout = self.fout + # prompt ' ' must exist; otherwise readline may delete entire line + # - http://bugs.python.org/issue12833 line = raw_input(' ') sys.stdin = oldin sys.stdout = oldout @@ -728,7 +730,7 @@ if self.debugflag: opts['label'] = opts.get('label', '') + ' ui.debug' self.write(*msg, **opts) - def edit(self, text, user, extra={}): + def edit(self, text, user, extra={}, editform=None): (fd, name) = tempfile.mkstemp(prefix="hg-editor-", suffix=".txt", text=True) try: @@ -743,6 +745,8 @@ if label in extra: environ.update({'HGREVISION': extra[label]}) break + if editform: + environ.update({'HGEDITFORM': editform}) editor = self.geteditor()
--- a/mercurial/util.py Sat Aug 30 15:13:02 2014 +0200 +++ b/mercurial/util.py Sat Aug 30 18:44:59 2014 +0200 @@ -53,6 +53,7 @@ popen = platform.popen posixfile = platform.posixfile quotecommand = platform.quotecommand +readpipe = platform.readpipe rename = platform.rename samedevice = platform.samedevice samefile = platform.samefile
--- a/mercurial/windows.py Sat Aug 30 15:13:02 2014 +0200 +++ b/mercurial/windows.py Sat Aug 30 18:44:59 2014 +0200 @@ -336,3 +336,18 @@ def statisexec(st): '''check whether a stat result is an executable file''' return False + +def readpipe(pipe): + """Read all available data from a pipe.""" + chunks = [] + while True: + size = os.fstat(pipe.fileno()).st_size + if not size: + break + + s = pipe.read(size) + if not s: + break + chunks.append(s) + + return ''.join(chunks)
--- a/mercurial/wireproto.py Sat Aug 30 15:13:02 2014 +0200 +++ b/mercurial/wireproto.py Sat Aug 30 18:44:59 2014 +0200 @@ -203,7 +203,8 @@ gboptsmap = {'heads': 'nodes', 'common': 'nodes', 'bundlecaps': 'csv', - 'listkeys': 'csv'} + 'listkeys': 'csv', + 'cg': 'boolean'} # client side @@ -248,7 +249,7 @@ yield {'nodes': encodelist(nodes)}, f d = f.value try: - yield [bool(int(f)) for f in d] + yield [bool(int(b)) for b in d] except ValueError: self._abort(error.ResponseError(_("unexpected response:"), d)) @@ -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/mercurial/worker.py Sat Aug 30 15:13:02 2014 +0200 +++ b/mercurial/worker.py Sat Aug 30 18:44:59 2014 +0200 @@ -105,7 +105,7 @@ if err.errno != errno.ESRCH: raise def waitforworkers(): - for _ in pids: + for _pid in pids: st = _exitstatus(os.wait()[1]) if st and not problem[0]: problem[0] = st
--- a/setup.py Sat Aug 30 15:13:02 2014 +0200 +++ b/setup.py Sat Aug 30 18:44:59 2014 +0200 @@ -33,12 +33,14 @@ except ImportError: try: import sha + sha.sha # silence unused import warning except ImportError: raise SystemExit( "Couldn't import standard hashlib (incomplete Python install).") try: import zlib + zlib.compressobj # silence unused import warning except ImportError: raise SystemExit( "Couldn't import standard zlib (incomplete Python install).") @@ -56,6 +58,7 @@ else: try: import bz2 + bz2.BZ2Compressor # silence unused import warning except ImportError: raise SystemExit( "Couldn't import standard bz2 (incomplete Python install).") @@ -129,6 +132,7 @@ # py2exe needs to be installed to work try: import py2exe + py2exe.Distribution # silence unused import warning py2exeloaded = True # import py2exe's patched Distribution class from distutils.core import Distribution
--- a/tests/hghave.py Sat Aug 30 15:13:02 2014 +0200 +++ b/tests/hghave.py Sat Aug 30 18:44:59 2014 +0200 @@ -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,22 +144,28 @@ finally: os.remove(path) +@check("lsprof", "python lsprof module") def has_lsprof(): try: import _lsprof + _lsprof.Profiler # silence unused import warning return True 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 + publish_cmdline # silence unused import return True except ImportError: return False @@ -146,16 +176,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 +200,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 +217,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 +233,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,51 +258,64 @@ 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 + pygments.highlight # silence unused import warning return True 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 + ssl.wrap_socket # silence unused import warning import OpenSSL OpenSSL.SSL.Context return True 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 +324,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 Sat Aug 30 15:13:02 2014 +0200 +++ b/tests/run-tests.py Sat Aug 30 18:44:59 2014 +0200 @@ -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: @@ -522,7 +546,7 @@ missing, failed = TTest.parsehghaveoutput(out) if not missing: - missing = ['irrelevant'] + missing = ['skipped'] if failed: self.fail('hg have failed checking for %s' % failed[-1]) @@ -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') @@ -1041,7 +1073,7 @@ output = re.sub(s, r, output) return ret, output.splitlines(True) -iolock = threading.Lock() +iolock = threading.RLock() class SkipTest(Exception): """Raised to indicate that a test is to be skipped.""" @@ -1077,46 +1109,59 @@ 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)) - iolock.acquire() 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('!') self.stream.flush() - iolock.release() + iolock.release() - def addError(self, *args, **kwargs): - super(TestResult, self).addError(*args, **kwargs) + def addSuccess(self, test): + iolock.acquire() + super(TestResult, self).addSuccess(test) + iolock.release() + 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)) - + iolock.acquire() if self.showAll: self.stream.writeln('skipped %s' % reason) else: self.stream.write('s') self.stream.flush() + iolock.release() def addIgnore(self, test, reason): self.ignored.append((test, reason)) - + iolock.acquire() if self.showAll: self.stream.writeln('ignored %s' % reason) else: - if reason != 'not retesting': + if reason != 'not retesting' and reason != "doesn't match keyword": self.stream.write('i') + else: + self.testsRun += 1 self.stream.flush() + iolock.release() def addWarn(self, test, reason): self.warned.append((test, reason)) @@ -1124,16 +1169,20 @@ if self._options.first: self.stop() + iolock.acquire() if self.showAll: self.stream.writeln('warned %s' % reason) else: self.stream.write('~') self.stream.flush() + iolock.release() def addOutputMismatch(self, test, ret, got, expected): """Record a mismatch in test output for a particular test.""" accepted = False + failed = False + lines = [] iolock.acquire() if self._options.nodiff: @@ -1162,7 +1211,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 @@ -1170,17 +1220,30 @@ 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: + iolock.acquire() self.stream.writeln('INTERRUPTED: %s (after %d seconds)' % ( - test.name, self.times[-1][1])) + test.name, self.times[-1][3])) + iolock.release() class TestSuite(unittest.TestSuite): """Custom unitest TestSuite that knows how to execute Mercurial tests.""" @@ -1314,6 +1377,7 @@ skipped = len(result.skipped) ignored = len(result.ignored) + iolock.acquire() self.stream.writeln('') if not self._runner.options.noskips: @@ -1326,20 +1390,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' % @@ -1347,15 +1430,19 @@ if self._runner.options.time: self.printtimes(result.times) + iolock.release() + return result def printtimes(self, times): + # iolock held by run 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 Sat Aug 30 15:13:02 2014 +0200 +++ b/tests/test-acl.t Sat Aug 30 18:44:59 2014 +0200 @@ -82,6 +82,9 @@ query 1; heads searching for changes all remote heads known locally + listing keys for "phases" + checking for updated bookmarks + listing keys for "bookmarks" listing keys for "bookmarks" 3 changesets found list of changesets: @@ -119,8 +122,6 @@ updating the branch cache listing keys for "phases" try to push obsolete markers to remote - checking for updated bookmarks - listing keys for "bookmarks" repository tip rolled back to revision 0 (undo push) 0:6675d58eff77 @@ -140,6 +141,9 @@ query 1; heads searching for changes all remote heads known locally + listing keys for "phases" + checking for updated bookmarks + listing keys for "bookmarks" invalid branchheads cache (served): tip differs listing keys for "bookmarks" 3 changesets found @@ -180,8 +184,6 @@ updating the branch cache listing keys for "phases" try to push obsolete markers to remote - checking for updated bookmarks - listing keys for "bookmarks" repository tip rolled back to revision 0 (undo push) 0:6675d58eff77 @@ -202,6 +204,9 @@ query 1; heads searching for changes all remote heads known locally + listing keys for "phases" + checking for updated bookmarks + listing keys for "bookmarks" invalid branchheads cache (served): tip differs listing keys for "bookmarks" 3 changesets found @@ -252,8 +257,6 @@ updating the branch cache listing keys for "phases" try to push obsolete markers to remote - checking for updated bookmarks - listing keys for "bookmarks" repository tip rolled back to revision 0 (undo push) 0:6675d58eff77 @@ -274,6 +277,9 @@ query 1; heads searching for changes all remote heads known locally + listing keys for "phases" + checking for updated bookmarks + listing keys for "bookmarks" invalid branchheads cache (served): tip differs listing keys for "bookmarks" 3 changesets found @@ -341,6 +347,9 @@ query 1; heads searching for changes all remote heads known locally + listing keys for "phases" + checking for updated bookmarks + listing keys for "bookmarks" invalid branchheads cache (served): tip differs listing keys for "bookmarks" 3 changesets found @@ -413,6 +422,9 @@ query 1; heads searching for changes all remote heads known locally + listing keys for "phases" + checking for updated bookmarks + listing keys for "bookmarks" invalid branchheads cache (served): tip differs listing keys for "bookmarks" 3 changesets found @@ -482,6 +494,9 @@ query 1; heads searching for changes all remote heads known locally + listing keys for "phases" + checking for updated bookmarks + listing keys for "bookmarks" invalid branchheads cache (served): tip differs listing keys for "bookmarks" 3 changesets found @@ -556,6 +571,9 @@ query 1; heads searching for changes all remote heads known locally + listing keys for "phases" + checking for updated bookmarks + listing keys for "bookmarks" invalid branchheads cache (served): tip differs listing keys for "bookmarks" 3 changesets found @@ -627,6 +645,9 @@ query 1; heads searching for changes all remote heads known locally + listing keys for "phases" + checking for updated bookmarks + listing keys for "bookmarks" invalid branchheads cache (served): tip differs listing keys for "bookmarks" 3 changesets found @@ -700,6 +721,9 @@ query 1; heads searching for changes all remote heads known locally + listing keys for "phases" + checking for updated bookmarks + listing keys for "bookmarks" invalid branchheads cache (served): tip differs listing keys for "bookmarks" 3 changesets found @@ -750,8 +774,6 @@ updating the branch cache listing keys for "phases" try to push obsolete markers to remote - checking for updated bookmarks - listing keys for "bookmarks" repository tip rolled back to revision 0 (undo push) 0:6675d58eff77 @@ -779,6 +801,9 @@ query 1; heads searching for changes all remote heads known locally + listing keys for "phases" + checking for updated bookmarks + listing keys for "bookmarks" invalid branchheads cache (served): tip differs listing keys for "bookmarks" 3 changesets found @@ -859,6 +884,9 @@ query 1; heads searching for changes all remote heads known locally + listing keys for "phases" + checking for updated bookmarks + listing keys for "bookmarks" invalid branchheads cache (served): tip differs listing keys for "bookmarks" 3 changesets found @@ -896,10 +924,10 @@ added 3 changesets with 3 changes to 3 files calling hook pretxnchangegroup.acl: hgext.acl.hook acl: checking access for user "barney" - error: pretxnchangegroup.acl hook raised an exception: [Errno *] *: '../acl.config' (glob) + error: pretxnchangegroup.acl hook raised an exception: [Errno 2] No such file or directory: '../acl.config' transaction abort! rollback completed - abort: *: ../acl.config (glob) + abort: No such file or directory: ../acl.config no rollback information available 0:6675d58eff77 @@ -934,6 +962,9 @@ query 1; heads searching for changes all remote heads known locally + listing keys for "phases" + checking for updated bookmarks + listing keys for "bookmarks" invalid branchheads cache (served): tip differs listing keys for "bookmarks" 3 changesets found @@ -1020,6 +1051,9 @@ query 1; heads searching for changes all remote heads known locally + listing keys for "phases" + checking for updated bookmarks + listing keys for "bookmarks" invalid branchheads cache (served): tip differs listing keys for "bookmarks" 3 changesets found @@ -1070,8 +1104,6 @@ updating the branch cache listing keys for "phases" try to push obsolete markers to remote - checking for updated bookmarks - listing keys for "bookmarks" repository tip rolled back to revision 0 (undo push) 0:6675d58eff77 @@ -1100,6 +1132,9 @@ query 1; heads searching for changes all remote heads known locally + listing keys for "phases" + checking for updated bookmarks + listing keys for "bookmarks" invalid branchheads cache (served): tip differs listing keys for "bookmarks" 3 changesets found @@ -1150,8 +1185,6 @@ updating the branch cache listing keys for "phases" try to push obsolete markers to remote - checking for updated bookmarks - listing keys for "bookmarks" repository tip rolled back to revision 0 (undo push) 0:6675d58eff77 @@ -1176,6 +1209,9 @@ query 1; heads searching for changes all remote heads known locally + listing keys for "phases" + checking for updated bookmarks + listing keys for "bookmarks" invalid branchheads cache (served): tip differs listing keys for "bookmarks" 3 changesets found @@ -1252,6 +1288,9 @@ query 1; heads searching for changes all remote heads known locally + listing keys for "phases" + checking for updated bookmarks + listing keys for "bookmarks" invalid branchheads cache (served): tip differs listing keys for "bookmarks" 3 changesets found @@ -1303,8 +1342,6 @@ updating the branch cache listing keys for "phases" try to push obsolete markers to remote - checking for updated bookmarks - listing keys for "bookmarks" repository tip rolled back to revision 0 (undo push) 0:6675d58eff77 @@ -1329,6 +1366,9 @@ query 1; heads searching for changes all remote heads known locally + listing keys for "phases" + checking for updated bookmarks + listing keys for "bookmarks" invalid branchheads cache (served): tip differs listing keys for "bookmarks" 3 changesets found @@ -1444,6 +1484,9 @@ query 1; heads searching for changes all remote heads known locally + listing keys for "phases" + checking for updated bookmarks + listing keys for "bookmarks" listing keys for "bookmarks" 4 changesets found list of changesets: @@ -1504,8 +1547,6 @@ updating the branch cache listing keys for "phases" try to push obsolete markers to remote - checking for updated bookmarks - listing keys for "bookmarks" repository tip rolled back to revision 2 (undo push) 2:fb35475503ef @@ -1527,6 +1568,9 @@ query 1; heads searching for changes all remote heads known locally + listing keys for "phases" + checking for updated bookmarks + listing keys for "bookmarks" listing keys for "bookmarks" 4 changesets found list of changesets: @@ -1606,6 +1650,9 @@ query 1; heads searching for changes all remote heads known locally + listing keys for "phases" + checking for updated bookmarks + listing keys for "bookmarks" listing keys for "bookmarks" 4 changesets found list of changesets: @@ -1681,6 +1728,9 @@ query 1; heads searching for changes all remote heads known locally + listing keys for "phases" + checking for updated bookmarks + listing keys for "bookmarks" listing keys for "bookmarks" 4 changesets found list of changesets: @@ -1750,6 +1800,9 @@ query 1; heads searching for changes all remote heads known locally + listing keys for "phases" + checking for updated bookmarks + listing keys for "bookmarks" listing keys for "bookmarks" 4 changesets found list of changesets: @@ -1810,8 +1863,6 @@ updating the branch cache listing keys for "phases" try to push obsolete markers to remote - checking for updated bookmarks - listing keys for "bookmarks" repository tip rolled back to revision 2 (undo push) 2:fb35475503ef @@ -1838,6 +1889,9 @@ query 1; heads searching for changes all remote heads known locally + listing keys for "phases" + checking for updated bookmarks + listing keys for "bookmarks" listing keys for "bookmarks" 4 changesets found list of changesets: @@ -1898,8 +1952,6 @@ updating the branch cache listing keys for "phases" try to push obsolete markers to remote - checking for updated bookmarks - listing keys for "bookmarks" repository tip rolled back to revision 2 (undo push) 2:fb35475503ef @@ -1925,6 +1977,9 @@ query 1; heads searching for changes all remote heads known locally + listing keys for "phases" + checking for updated bookmarks + listing keys for "bookmarks" listing keys for "bookmarks" 4 changesets found list of changesets: @@ -1999,6 +2054,9 @@ query 1; heads searching for changes all remote heads known locally + listing keys for "phases" + checking for updated bookmarks + listing keys for "bookmarks" listing keys for "bookmarks" 4 changesets found list of changesets: @@ -2059,8 +2117,6 @@ updating the branch cache listing keys for "phases" try to push obsolete markers to remote - checking for updated bookmarks - listing keys for "bookmarks" repository tip rolled back to revision 2 (undo push) 2:fb35475503ef @@ -2080,6 +2136,9 @@ query 1; heads searching for changes all remote heads known locally + listing keys for "phases" + checking for updated bookmarks + listing keys for "bookmarks" listing keys for "bookmarks" 4 changesets found list of changesets:
--- a/tests/test-alias.t Sat Aug 30 15:13:02 2014 +0200 +++ b/tests/test-alias.t Sat Aug 30 18:44:59 2014 +0200 @@ -10,6 +10,7 @@ > unknown = bargle > ambiguous = s > recursive = recursive + > disabled = email > nodefinition = > noclosingquotation = ' > no--cwd = status --cwd elsewhere @@ -30,6 +31,7 @@ > echo1 = !printf '\$1\n' > echo2 = !printf '\$2\n' > echo13 = !printf '\$1 \$3\n' + > echotokens = !printf "%s\n" "\$@" > count = !hg log -r "\$@" --template=. | wc -c | sed -e 's/ //g' > mcount = !hg log \$@ --template=. | wc -c | sed -e 's/ //g' > rt = root @@ -60,7 +62,7 @@ unknown $ hg unknown - alias 'unknown' resolves to unknown command 'bargle' + abort: alias 'unknown' resolves to unknown command 'bargle' [255] $ hg help unknown alias 'unknown' resolves to unknown command 'bargle' @@ -69,7 +71,7 @@ ambiguous $ hg ambiguous - alias 'ambiguous' resolves to ambiguous command 's' + abort: alias 'ambiguous' resolves to ambiguous command 's' [255] $ hg help ambiguous alias 'ambiguous' resolves to ambiguous command 's' @@ -78,16 +80,32 @@ recursive $ hg recursive - alias 'recursive' resolves to unknown command 'recursive' + abort: alias 'recursive' resolves to unknown command 'recursive' [255] $ hg help recursive alias 'recursive' resolves to unknown command 'recursive' +disabled + + $ hg disabled + abort: alias 'disabled' resolves to unknown command 'email' + ('email' is provided by 'patchbomb' extension) + [255] + $ hg help disabled + alias 'disabled' resolves to unknown command 'email' + + 'email' is provided by the following extension: + + patchbomb command to send changesets as (a series of) patch emails + + (use "hg help extensions" for information on enabling extensions) + + no definition $ hg nodef - no definition for alias 'nodefinition' + abort: no definition for alias 'nodefinition' [255] $ hg help nodef no definition for alias 'nodefinition' @@ -96,7 +114,7 @@ no closing quotation $ hg noclosing - error in definition for alias 'noclosingquotation': No closing quotation + abort: error in definition for alias 'noclosingquotation': No closing quotation [255] $ hg help noclosing error in definition for alias 'noclosingquotation': No closing quotation @@ -105,27 +123,30 @@ invalid options $ hg no--cwd - error in definition for alias 'no--cwd': --cwd may only be given on the command line + abort: error in definition for alias 'no--cwd': --cwd may only be given on the command line [255] $ hg help no--cwd - error in definition for alias 'no--cwd': --cwd may only be given on the command line + error in definition for alias 'no--cwd': --cwd may only be given on the + command line $ hg no-R - error in definition for alias 'no-R': -R may only be given on the command line + abort: error in definition for alias 'no-R': -R may only be given on the command line [255] $ hg help no-R error in definition for alias 'no-R': -R may only be given on the command line $ hg no--repo - error in definition for alias 'no--repo': --repo may only be given on the command line + abort: error in definition for alias 'no--repo': --repo may only be given on the command line [255] $ hg help no--repo - error in definition for alias 'no--repo': --repo may only be given on the command line + error in definition for alias 'no--repo': --repo may only be given on the + command line $ hg no--repository - error in definition for alias 'no--repository': --repository may only be given on the command line + abort: error in definition for alias 'no--repository': --repository may only be given on the command line [255] $ hg help no--repository - error in definition for alias 'no--repository': --repository may only be given on the command line + error in definition for alias 'no--repository': --repository may only be given + on the command line $ hg no--config - error in definition for alias 'no--config': --config may only be given on the command line + abort: error in definition for alias 'no--config': --config may only be given on the command line [255] optional repository @@ -229,6 +250,10 @@ foo $ hg echoall 'test $2' foo test $2 foo + $ hg echoall 'test $@' foo '$@' + test $@ foo $@ + $ hg echoall 'test "$@"' foo '"$@"' + test "$@" foo "$@" $ hg echo1 foo bar baz foo $ hg echo2 foo bar baz @@ -237,6 +262,22 @@ foo baz $ hg echo2 foo + $ hg echotokens + + $ hg echotokens foo 'bar $1 baz' + foo + bar $1 baz + $ hg echotokens 'test $2' foo + test $2 + foo + $ hg echotokens 'test $@' foo '$@' + test $@ + foo + $@ + $ hg echotokens 'test "$@"' foo '"$@"' + test "$@" + foo + "$@" $ echo bar > bar $ hg commit -qA -m bar $ hg count . @@ -370,7 +411,7 @@ alias for: hg root - use "hg help rt" to show the full help text + (use "hg rt -h" to show more help) [255] invalid global arguments for normal commands, aliases, and shell aliases @@ -399,7 +440,7 @@ summary summarize working directory state update update working directory (or switch revisions) - use "hg help" for the full list of commands or "hg -v" for details + (use "hg help" for the full list of commands or "hg -v" for details) [255] $ hg --invalid mylog hg: option --invalid not recognized @@ -425,7 +466,7 @@ summary summarize working directory state update update working directory (or switch revisions) - use "hg help" for the full list of commands or "hg -v" for details + (use "hg help" for the full list of commands or "hg -v" for details) [255] $ hg --invalid blank hg: option --invalid not recognized @@ -451,7 +492,7 @@ summary summarize working directory state update update working directory (or switch revisions) - use "hg help" for the full list of commands or "hg -v" for details + (use "hg help" for the full list of commands or "hg -v" for details) [255] This should show id:
--- a/tests/test-archive-symlinks.t Sat Aug 30 15:13:02 2014 +0200 +++ b/tests/test-archive-symlinks.t Sat Aug 30 18:44:59 2014 +0200 @@ -1,4 +1,4 @@ - $ "$TESTDIR/hghave" symlink || exit 80 +#require symlink $ origdir=`pwd`
--- a/tests/test-archive.t Sat Aug 30 15:13:02 2014 +0200 +++ b/tests/test-archive.t Sat Aug 30 18:44:59 2014 +0200 @@ -1,4 +1,4 @@ - $ "$TESTDIR/hghave" serve || exit 80 +#require serve $ hg init test $ cd test
--- a/tests/test-bad-pull.t Sat Aug 30 15:13:02 2014 +0200 +++ b/tests/test-bad-pull.t Sat Aug 30 18:44:59 2014 +0200 @@ -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 Sat Aug 30 15:13:02 2014 +0200 +++ b/tests/test-bookmarks-pushpull.t Sat Aug 30 18:44:59 2014 +0200 @@ -1,4 +1,4 @@ - $ "$TESTDIR/hghave" serve || exit 80 +#require serve $ cat << EOF >> $HGRCPATH > [ui]
--- a/tests/test-bundle.t Sat Aug 30 15:13:02 2014 +0200 +++ b/tests/test-bundle.t Sat Aug 30 18:44:59 2014 +0200 @@ -422,7 +422,7 @@ $ rm -r full-clone When cloning from a non-copiable repository into '', do not -recurse infinitely (issue 2528) +recurse infinitely (issue2528) $ hg clone full.hg '' abort: empty destination path is not valid
--- a/tests/test-bundle2.t Sat Aug 30 15:13:02 2014 +0200 +++ b/tests/test-bundle2.t Sat Aug 30 18:44:59 2014 +0200 @@ -191,7 +191,7 @@ > bundle2-exp=True > [ui] > ssh=python "$TESTDIR/dummyssh" - > logtemplate={rev}:{node|short} {phase} {author} {desc|firstline} + > logtemplate={rev}:{node|short} {phase} {author} {bookmarks} {desc|firstline} > [web] > push_ssl = false > allow_push = * @@ -668,23 +668,23 @@ (run 'hg heads' to see heads, 'hg merge' to merge) $ hg log -G - o 8:02de42196ebe draft Nicolas Dumazet <nicdumz.commits@gmail.com> H + o 8:02de42196ebe draft Nicolas Dumazet <nicdumz.commits@gmail.com> H | - | o 7:eea13746799a draft Nicolas Dumazet <nicdumz.commits@gmail.com> G + | o 7:eea13746799a draft Nicolas Dumazet <nicdumz.commits@gmail.com> G |/| - o | 6:24b6387c8c8c draft Nicolas Dumazet <nicdumz.commits@gmail.com> F + o | 6:24b6387c8c8c draft Nicolas Dumazet <nicdumz.commits@gmail.com> F | | - | o 5:9520eea781bc draft Nicolas Dumazet <nicdumz.commits@gmail.com> E + | o 5:9520eea781bc draft Nicolas Dumazet <nicdumz.commits@gmail.com> E |/ - | o 4:32af7686d403 draft Nicolas Dumazet <nicdumz.commits@gmail.com> D + | o 4:32af7686d403 draft Nicolas Dumazet <nicdumz.commits@gmail.com> D | | - | o 3:5fddd98957c8 draft Nicolas Dumazet <nicdumz.commits@gmail.com> C + | o 3:5fddd98957c8 draft Nicolas Dumazet <nicdumz.commits@gmail.com> C | | - | o 2:42ccdea3bb16 draft Nicolas Dumazet <nicdumz.commits@gmail.com> B + | o 2:42ccdea3bb16 draft Nicolas Dumazet <nicdumz.commits@gmail.com> B |/ - o 1:cd010b8cd998 draft Nicolas Dumazet <nicdumz.commits@gmail.com> A + o 1:cd010b8cd998 draft Nicolas Dumazet <nicdumz.commits@gmail.com> A - @ 0:3903775176ed draft test a + @ 0:3903775176ed draft test a $ hg bundle2 --debug --rev '8+7+5+4' ../rev.hg2 @@ -774,9 +774,9 @@ updating to branch default 2 files updated, 0 files merged, 0 files removed, 0 files unresolved $ hg -R other log -G - @ 1:9520eea781bc draft Nicolas Dumazet <nicdumz.commits@gmail.com> E + @ 1:9520eea781bc draft Nicolas Dumazet <nicdumz.commits@gmail.com> E | - o 0:cd010b8cd998 public Nicolas Dumazet <nicdumz.commits@gmail.com> A + o 0:cd010b8cd998 public Nicolas Dumazet <nicdumz.commits@gmail.com> A pull @@ -791,11 +791,11 @@ added 1 changesets with 1 changes to 1 files (+1 heads) (run 'hg heads' to see heads, 'hg merge' to merge) $ hg -R other log -G - o 2:24b6387c8c8c draft Nicolas Dumazet <nicdumz.commits@gmail.com> F + o 2:24b6387c8c8c draft Nicolas Dumazet <nicdumz.commits@gmail.com> F | - | @ 1:9520eea781bc draft Nicolas Dumazet <nicdumz.commits@gmail.com> E + | @ 1:9520eea781bc draft Nicolas Dumazet <nicdumz.commits@gmail.com> E |/ - o 0:cd010b8cd998 public Nicolas Dumazet <nicdumz.commits@gmail.com> A + o 0:cd010b8cd998 public Nicolas Dumazet <nicdumz.commits@gmail.com> A pull empty (with phase movement) @@ -805,11 +805,11 @@ pulling from $TESTTMP/main (glob) no changes found $ hg -R other log -G - o 2:24b6387c8c8c public Nicolas Dumazet <nicdumz.commits@gmail.com> F + o 2:24b6387c8c8c public Nicolas Dumazet <nicdumz.commits@gmail.com> F | - | @ 1:9520eea781bc draft Nicolas Dumazet <nicdumz.commits@gmail.com> E + | @ 1:9520eea781bc draft Nicolas Dumazet <nicdumz.commits@gmail.com> E |/ - o 0:cd010b8cd998 public Nicolas Dumazet <nicdumz.commits@gmail.com> A + o 0:cd010b8cd998 public Nicolas Dumazet <nicdumz.commits@gmail.com> A pull empty @@ -817,82 +817,104 @@ pulling from $TESTTMP/main (glob) no changes found $ hg -R other log -G - o 2:24b6387c8c8c public Nicolas Dumazet <nicdumz.commits@gmail.com> F + o 2:24b6387c8c8c public Nicolas Dumazet <nicdumz.commits@gmail.com> F | - | @ 1:9520eea781bc draft Nicolas Dumazet <nicdumz.commits@gmail.com> E + | @ 1:9520eea781bc draft Nicolas Dumazet <nicdumz.commits@gmail.com> E |/ - o 0:cd010b8cd998 public Nicolas Dumazet <nicdumz.commits@gmail.com> A + o 0:cd010b8cd998 public Nicolas Dumazet <nicdumz.commits@gmail.com> A -push +add extra data to test their exchange during push + + $ hg -R main bookmark --rev eea13746799a book_eea1 + $ hg -R main bookmark --rev 02de42196ebe book_02de + $ hg -R main bookmark --rev 42ccdea3bb16 book_42cc + $ hg -R main bookmark --rev 5fddd98957c8 book_5fdd + $ hg -R main bookmark --rev 32af7686d403 book_32af + + $ hg -R other bookmark --rev cd010b8cd998 book_eea1 + $ hg -R other bookmark --rev cd010b8cd998 book_02de + $ hg -R other bookmark --rev cd010b8cd998 book_42cc + $ hg -R other bookmark --rev cd010b8cd998 book_5fdd + $ hg -R other bookmark --rev cd010b8cd998 book_32af $ hg -R main phase --public eea13746799a - $ hg -R main push other --rev eea13746799a + +push + $ hg -R main push other --rev eea13746799a --bookmark book_eea1 pushing to other searching for changes remote: adding changesets remote: adding manifests remote: adding file changes remote: added 1 changesets with 0 changes to 0 files (-1 heads) + updating bookmark book_eea1 + exporting bookmark book_eea1 $ hg -R other log -G - o 3:eea13746799a public Nicolas Dumazet <nicdumz.commits@gmail.com> G + o 3:eea13746799a public Nicolas Dumazet <nicdumz.commits@gmail.com> book_eea1 G |\ - | o 2:24b6387c8c8c public Nicolas Dumazet <nicdumz.commits@gmail.com> F + | o 2:24b6387c8c8c public Nicolas Dumazet <nicdumz.commits@gmail.com> F | | - @ | 1:9520eea781bc public Nicolas Dumazet <nicdumz.commits@gmail.com> E + @ | 1:9520eea781bc public Nicolas Dumazet <nicdumz.commits@gmail.com> E |/ - o 0:cd010b8cd998 public Nicolas Dumazet <nicdumz.commits@gmail.com> A + o 0:cd010b8cd998 public Nicolas Dumazet <nicdumz.commits@gmail.com> book_02de book_32af book_42cc book_5fdd A pull over ssh - $ hg -R other pull ssh://user@dummy/main -r 02de42196ebe --traceback + $ hg -R other pull ssh://user@dummy/main -r 02de42196ebe --bookmark book_02de pulling from ssh://user@dummy/main searching for changes adding changesets adding manifests adding file changes added 1 changesets with 1 changes to 1 files (+1 heads) + updating bookmark book_02de (run 'hg heads' to see heads, 'hg merge' to merge) + importing bookmark book_02de pull over http $ hg -R main serve -p $HGPORT -d --pid-file=main.pid -E main-error.log $ cat main.pid >> $DAEMON_PIDS - $ hg -R other pull http://localhost:$HGPORT/ -r 42ccdea3bb16 + $ hg -R other pull http://localhost:$HGPORT/ -r 42ccdea3bb16 --bookmark book_42cc pulling from http://localhost:$HGPORT/ searching for changes adding changesets adding manifests adding file changes added 1 changesets with 1 changes to 1 files (+1 heads) + updating bookmark book_42cc (run 'hg heads .' to see heads, 'hg merge' to merge) + importing bookmark book_42cc $ cat main-error.log push over ssh - $ hg -R main push ssh://user@dummy/other -r 5fddd98957c8 + $ hg -R main push ssh://user@dummy/other -r 5fddd98957c8 --bookmark book_5fdd pushing to ssh://user@dummy/other searching for changes remote: adding changesets remote: adding manifests remote: adding file changes remote: added 1 changesets with 1 changes to 1 files + updating bookmark book_5fdd + exporting bookmark book_5fdd $ hg -R other log -G - o 6:5fddd98957c8 draft Nicolas Dumazet <nicdumz.commits@gmail.com> C + o 6:5fddd98957c8 draft Nicolas Dumazet <nicdumz.commits@gmail.com> book_5fdd C | - o 5:42ccdea3bb16 draft Nicolas Dumazet <nicdumz.commits@gmail.com> B + o 5:42ccdea3bb16 draft Nicolas Dumazet <nicdumz.commits@gmail.com> book_42cc B | - | o 4:02de42196ebe draft Nicolas Dumazet <nicdumz.commits@gmail.com> H + | o 4:02de42196ebe draft Nicolas Dumazet <nicdumz.commits@gmail.com> book_02de H | | - | | o 3:eea13746799a public Nicolas Dumazet <nicdumz.commits@gmail.com> G + | | o 3:eea13746799a public Nicolas Dumazet <nicdumz.commits@gmail.com> book_eea1 G | |/| - | o | 2:24b6387c8c8c public Nicolas Dumazet <nicdumz.commits@gmail.com> F + | o | 2:24b6387c8c8c public Nicolas Dumazet <nicdumz.commits@gmail.com> F |/ / - | @ 1:9520eea781bc public Nicolas Dumazet <nicdumz.commits@gmail.com> E + | @ 1:9520eea781bc public Nicolas Dumazet <nicdumz.commits@gmail.com> E |/ - o 0:cd010b8cd998 public Nicolas Dumazet <nicdumz.commits@gmail.com> A + o 0:cd010b8cd998 public Nicolas Dumazet <nicdumz.commits@gmail.com> book_32af A push over http @@ -901,33 +923,35 @@ $ cat other.pid >> $DAEMON_PIDS $ hg -R main phase --public 32af7686d403 - $ hg -R main push http://localhost:$HGPORT2/ -r 32af7686d403 + $ hg -R main push http://localhost:$HGPORT2/ -r 32af7686d403 --bookmark book_32af pushing to http://localhost:$HGPORT2/ searching for changes remote: adding changesets remote: adding manifests remote: adding file changes remote: added 1 changesets with 1 changes to 1 files + updating bookmark book_32af + exporting bookmark book_32af $ cat other-error.log Check final content. $ hg -R other log -G - o 7:32af7686d403 public Nicolas Dumazet <nicdumz.commits@gmail.com> D + o 7:32af7686d403 public Nicolas Dumazet <nicdumz.commits@gmail.com> book_32af D | - o 6:5fddd98957c8 public Nicolas Dumazet <nicdumz.commits@gmail.com> C + o 6:5fddd98957c8 public Nicolas Dumazet <nicdumz.commits@gmail.com> book_5fdd C | - o 5:42ccdea3bb16 public Nicolas Dumazet <nicdumz.commits@gmail.com> B + o 5:42ccdea3bb16 public Nicolas Dumazet <nicdumz.commits@gmail.com> book_42cc B | - | o 4:02de42196ebe draft Nicolas Dumazet <nicdumz.commits@gmail.com> H + | o 4:02de42196ebe draft Nicolas Dumazet <nicdumz.commits@gmail.com> book_02de H | | - | | o 3:eea13746799a public Nicolas Dumazet <nicdumz.commits@gmail.com> G + | | o 3:eea13746799a public Nicolas Dumazet <nicdumz.commits@gmail.com> book_eea1 G | |/| - | o | 2:24b6387c8c8c public Nicolas Dumazet <nicdumz.commits@gmail.com> F + | o | 2:24b6387c8c8c public Nicolas Dumazet <nicdumz.commits@gmail.com> F |/ / - | @ 1:9520eea781bc public Nicolas Dumazet <nicdumz.commits@gmail.com> E + | @ 1:9520eea781bc public Nicolas Dumazet <nicdumz.commits@gmail.com> E |/ - o 0:cd010b8cd998 public Nicolas Dumazet <nicdumz.commits@gmail.com> A + o 0:cd010b8cd998 public Nicolas Dumazet <nicdumz.commits@gmail.com> A Error Handling @@ -964,7 +988,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 Sat Aug 30 15:13:02 2014 +0200 +++ b/tests/test-casecollision-merge.t Sat Aug 30 18:44:59 2014 +0200 @@ -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 Sat Aug 30 15:13:02 2014 +0200 +++ b/tests/test-casecollision.t Sat Aug 30 18:44:59 2014 +0200 @@ -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 Sat Aug 30 15:13:02 2014 +0200 +++ b/tests/test-casefolding.t Sat Aug 30 18:44:59 2014 +0200 @@ -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 Sat Aug 30 15:13:02 2014 +0200 +++ b/tests/test-changelog-exec.t Sat Aug 30 18:44:59 2014 +0200 @@ -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 Sat Aug 30 15:13:02 2014 +0200 +++ b/tests/test-check-code-hg.t Sat Aug 30 18:44:59 2014 +0200 @@ -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 Sat Aug 30 18:44:59 2014 +0200 @@ -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 Sat Aug 30 15:13:02 2014 +0200 +++ b/tests/test-check-pyflakes.t Sat Aug 30 18:44:59 2014 +0200 @@ -1,4 +1,4 @@ -#if test-repo pyflakes +#require test-repo pyflakes $ cd "`dirname "$TESTDIR"`" @@ -7,16 +7,6 @@ $ hg locate 'set:**.py or grep("^!#.*python")' 2>/dev/null \ > | xargs pyflakes 2>/dev/null | "$TESTDIR/filterpyflakes.py" - contrib/win32/hgwebdir_wsgi.py:*: 'win32traceutil' imported but unused (glob) - setup.py:*: 'sha' imported but unused (glob) - setup.py:*: 'zlib' imported but unused (glob) - setup.py:*: 'bz2' imported but unused (glob) - setup.py:*: 'py2exe' imported but unused (glob) - tests/hghave.py:*: '_lsprof' imported but unused (glob) - tests/hghave.py:*: 'publish_cmdline' imported but unused (glob) - tests/hghave.py:*: 'pygments' imported but unused (glob) - tests/hghave.py:*: 'ssl' imported but unused (glob) - 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 Sat Aug 30 15:13:02 2014 +0200 +++ b/tests/test-clone-cgi.t Sat Aug 30 18:44:59 2014 +0200 @@ -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-clone.t Sat Aug 30 15:13:02 2014 +0200 +++ b/tests/test-clone.t Sat Aug 30 18:44:59 2014 +0200 @@ -25,12 +25,25 @@ .hg/store/data/b.d .hg/store/data/b.i +Trigger branchcache creation: + + $ hg branches + default 10:a7949464abda + $ ls .hg/cache + branch2-served + Default operation: $ hg clone . ../b updating to branch default 2 files updated, 0 files merged, 0 files removed, 0 files unresolved $ cd ../b + +Ensure branchcache got copied over: + + $ ls .hg/cache + branch2-served + $ cat a a $ hg verify @@ -58,6 +71,12 @@ listing keys for "bookmarks" #endif $ cd ../c + +Ensure branchcache got copied over: + + $ ls .hg/cache + branch2-served + $ cat a 2>/dev/null || echo "a not present" a not present $ hg verify
--- a/tests/test-command-template.t Sat Aug 30 15:13:02 2014 +0200 +++ b/tests/test-command-template.t Sat Aug 30 18:44:59 2014 +0200 @@ -1834,6 +1834,15 @@ 1 Parents: 0 0 Parents: + $ cat >> .hg/hgrc <<EOF + > [revsetalias] + > myparents(\$1) = parents(\$1) + > EOF + $ hg log --template '{rev} Parents: {revset("myparents(%s)", rev)}\n' + 2 Parents: 1 + 1 Parents: 0 + 0 Parents: + $ hg log --template 'Rev: {rev}\n{revset("::%s", rev) % "Ancestor: {revision}\n"}\n' Rev: 2 Ancestor: 0
--- a/tests/test-commandserver.py.out Sat Aug 30 15:13:02 2014 +0200 +++ b/tests/test-commandserver.py.out Sat Aug 30 18:44:59 2014 +0200 @@ -34,7 +34,7 @@ summary summarize working directory state update update working directory (or switch revisions) -use "hg help" for the full list of commands or "hg -v" for details +(use "hg help" for the full list of commands or "hg -v" for details) runcommand id --quiet 000000000000 runcommand id
--- a/tests/test-commit-amend.t Sat Aug 30 15:13:02 2014 +0200 +++ b/tests/test-commit-amend.t Sat Aug 30 18:44:59 2014 +0200 @@ -145,7 +145,12 @@ Test -u/-d: - $ hg ci --amend -u foo -d '1 0' + $ cat > .hg/checkeditform.sh <<EOF + > env | grep HGEDITFORM + > true + > EOF + $ HGEDITOR="sh .hg/checkeditform.sh" hg ci --amend -u foo -d '1 0' + HGEDITFORM=commit.amend.normal saved backup bundle to $TESTTMP/.hg/strip-backup/1cd866679df8-amend-backup.hg (glob) $ echo a >> a $ hg ci --amend -u foo -d '1 0' @@ -619,7 +624,8 @@ zz renamed from z:69a1b67522704ec122181c0890bd16e9d3e7516a $ hg debugrename cc cc not renamed - $ hg ci --amend -m 'merge bar (amend message)' + $ HGEDITOR="sh .hg/checkeditform.sh" hg ci --amend -m 'merge bar (amend message)' --edit + HGEDITFORM=commit.amend.merge $ hg log --config diff.git=1 -pr . changeset: 24:832b50f2c271 tag: tip
--- a/tests/test-commit.t Sat Aug 30 15:13:02 2014 +0200 +++ b/tests/test-commit.t Sat Aug 30 18:44:59 2014 +0200 @@ -4,7 +4,12 @@ $ cd test $ echo foo > foo $ hg add foo - $ HGEDITOR=true hg commit -m "" + $ cat > $TESTTMP/checkeditform.sh <<EOF + > env | grep HGEDITFORM + > true + > EOF + $ HGEDITOR="sh $TESTTMP/checkeditform.sh" hg commit -m "" + HGEDITFORM=commit.normal.normal abort: empty commit message [255] $ hg commit -d '0 0' -m commit-1 @@ -277,7 +282,8 @@ should succeed - $ hg ci -mmerge + $ HGEDITOR="sh $TESTTMP/checkeditform.sh" hg ci -mmerge --edit + HGEDITFORM=commit.normal.merge $ cd .. @@ -359,6 +365,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 +393,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 +401,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 Sat Aug 30 15:13:02 2014 +0200 +++ b/tests/test-completion.t Sat Aug 30 18:44:59 2014 +0200 @@ -244,7 +244,7 @@ debuginstall: debugknown: debuglabelcomplete: - debugobsolete: flags, date, user + debugobsolete: flags, record-parents, rev, date, user debugpathcomplete: full, normal, added, removed debugpushkey: debugpvec: @@ -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-config.t Sat Aug 30 15:13:02 2014 +0200 +++ b/tests/test-config.t Sat Aug 30 18:44:59 2014 +0200 @@ -1,6 +1,47 @@ hide outer repo $ hg init +Invalid syntax: no value + + $ cat > .hg/hgrc << EOF + > novaluekey + > EOF + $ hg showconfig + hg: parse error at $TESTTMP/.hg/hgrc:1: novaluekey + [255] + +Invalid syntax: no key + + $ cat > .hg/hgrc << EOF + > =nokeyvalue + > EOF + $ hg showconfig + hg: parse error at $TESTTMP/.hg/hgrc:1: =nokeyvalue + [255] + +Test hint about invalid syntax from leading white space + + $ cat > .hg/hgrc << EOF + > key=value + > EOF + $ hg showconfig + hg: parse error at $TESTTMP/.hg/hgrc:1: key=value + unexpected leading whitespace + [255] + + $ cat > .hg/hgrc << EOF + > [section] + > key=value + > EOF + $ hg showconfig + hg: parse error at $TESTTMP/.hg/hgrc:1: [section] + unexpected leading whitespace + [255] + +Reset hgrc + + $ echo > .hg/hgrc + Test case sensitive configuration $ echo '[Section]' >> $HGRCPATH
--- a/tests/test-conflict.t Sat Aug 30 15:13:02 2014 +0200 +++ b/tests/test-conflict.t Sat Aug 30 18:44:59 2014 +0200 @@ -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 Sat Aug 30 15:13:02 2014 +0200 +++ b/tests/test-contrib.t Sat Aug 30 18:44:59 2014 +0200 @@ -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 Sat Aug 30 15:13:02 2014 +0200 +++ b/tests/test-convert-baz.t Sat Aug 30 18:44:59 2014 +0200 @@ -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 Sat Aug 30 15:13:02 2014 +0200 +++ b/tests/test-convert-bzr-114.t Sat Aug 30 18:44:59 2014 +0200 @@ -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 Sat Aug 30 15:13:02 2014 +0200 +++ b/tests/test-convert-cvs-branch.t Sat Aug 30 18:44:59 2014 +0200 @@ -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 Sat Aug 30 15:13:02 2014 +0200 +++ b/tests/test-convert-cvs-detectmerge.t Sat Aug 30 18:44:59 2014 +0200 @@ -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 Sat Aug 30 15:13:02 2014 +0200 +++ b/tests/test-convert-cvs-synthetic.t Sat Aug 30 18:44:59 2014 +0200 @@ -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 Sat Aug 30 15:13:02 2014 +0200 +++ b/tests/test-convert-cvs.t Sat Aug 30 18:44:59 2014 +0200 @@ -1,5 +1,5 @@ +#require cvs - $ "$TESTDIR/hghave" cvs || exit 80 $ cvscall() > { > cvs -f "$@"
--- a/tests/test-convert-cvsnt-mergepoints.t Sat Aug 30 15:13:02 2014 +0200 +++ b/tests/test-convert-cvsnt-mergepoints.t Sat Aug 30 18:44:59 2014 +0200 @@ -1,5 +1,5 @@ +#require cvs - $ "$TESTDIR/hghave" cvs || exit 80 $ filterpath() > { > eval "$@" | sed "s:$CVSROOT:*REPO*:g"
--- a/tests/test-convert-darcs.t Sat Aug 30 15:13:02 2014 +0200 +++ b/tests/test-convert-darcs.t Sat Aug 30 18:44:59 2014 +0200 @@ -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 Sat Aug 30 15:13:02 2014 +0200 +++ b/tests/test-convert-git.t Sat Aug 30 18:44:59 2014 +0200 @@ -1,5 +1,5 @@ +#require git - $ "$TESTDIR/hghave" git || exit 80 $ echo "[core]" >> $HOME/.gitconfig $ echo "autocrlf = false" >> $HOME/.gitconfig $ echo "[core]" >> $HOME/.gitconfig @@ -33,8 +33,7 @@ $ git add a d $ commit -a -m t1 -Remove the directory, then try to replace it with a file -(issue 754) +Remove the directory, then try to replace it with a file (issue754) $ git rm -f d/b rm 'd/b' @@ -206,7 +205,7 @@ 9277c9cc8dd4576fc01a17939b4351e5ada93466 644 foo 88dfeab657e8cf2cef3dec67b914f49791ae76b1 644 quux -test binary conversion (issue 1359) +test binary conversion (issue1359) $ mkdir git-repo3 $ cd git-repo3
--- a/tests/test-convert-hg-sink.t Sat Aug 30 15:13:02 2014 +0200 +++ b/tests/test-convert-hg-sink.t Sat Aug 30 18:44:59 2014 +0200 @@ -537,3 +537,16 @@ | o 0 0 (a-only f) +Convert with --full adds and removes files that didn't change + + $ echo f >> 0/f + $ hg -R 0 ci -m "f" + $ hg convert --filemap filemap-b --full 0 a --config convert.hg.revs=1:: + scanning source... + sorting... + converting... + 0 f + $ hg -R a status --change tip + M f + A b-only + R a-only
--- a/tests/test-convert-hg-svn.t Sat Aug 30 15:13:02 2014 +0200 +++ b/tests/test-convert-hg-svn.t Sat Aug 30 18:44:59 2014 +0200 @@ -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 Sat Aug 30 15:13:02 2014 +0200 +++ b/tests/test-convert-mtn.t Sat Aug 30 18:44:59 2014 +0200 @@ -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 Sat Aug 30 15:13:02 2014 +0200 +++ b/tests/test-convert-p4-filetypes.t Sat Aug 30 18:44:59 2014 +0200 @@ -1,4 +1,4 @@ - $ "$TESTDIR/hghave" p4 execbit symlink || exit 80 +#require p4 execbit symlink $ echo "[extensions]" >> $HGRCPATH $ echo "convert = " >> $HGRCPATH @@ -8,7 +8,7 @@ $ P4AUDIT=$P4ROOT/audit; export P4AUDIT $ P4JOURNAL=$P4ROOT/journal; export P4JOURNAL $ P4LOG=$P4ROOT/log; export P4LOG - $ P4PORT=localhost:16661; export P4PORT + $ P4PORT=localhost:$HGPORT; export P4PORT $ P4DEBUG=1; export P4DEBUG $ P4CHARSET=utf8; export P4CHARSET
--- a/tests/test-convert-p4.t Sat Aug 30 15:13:02 2014 +0200 +++ b/tests/test-convert-p4.t Sat Aug 30 18:44:59 2014 +0200 @@ -1,4 +1,4 @@ - $ "$TESTDIR/hghave" p4 || exit 80 +#require p4 $ echo "[extensions]" >> $HGRCPATH $ echo "convert = " >> $HGRCPATH @@ -8,7 +8,7 @@ $ P4AUDIT=$P4ROOT/audit; export P4AUDIT $ P4JOURNAL=$P4ROOT/journal; export P4JOURNAL $ P4LOG=$P4ROOT/log; export P4LOG - $ P4PORT=localhost:16661; export P4PORT + $ P4PORT=localhost:$HGPORT; export P4PORT $ P4DEBUG=1; export P4DEBUG start the p4 server
--- a/tests/test-convert-svn-branches.t Sat Aug 30 15:13:02 2014 +0200 +++ b/tests/test-convert-svn-branches.t Sat Aug 30 18:44:59 2014 +0200 @@ -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 Sat Aug 30 15:13:02 2014 +0200 +++ b/tests/test-convert-svn-encoding.t Sat Aug 30 18:44:59 2014 +0200 @@ -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 Sat Aug 30 15:13:02 2014 +0200 +++ b/tests/test-convert-svn-move.t Sat Aug 30 18:44:59 2014 +0200 @@ -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 Sat Aug 30 15:13:02 2014 +0200 +++ b/tests/test-convert-svn-sink.t Sat Aug 30 18:44:59 2014 +0200 @@ -1,4 +1,4 @@ - $ "$TESTDIR/hghave" svn13 || exit 80 +#require svn13 $ svnupanddisplay() > { @@ -247,6 +247,31 @@ #endif +Convert with --full adds and removes files that didn't change + + $ touch a/f + $ hg -R a ci -Aqmf + $ echo "rename c d" > filemap + $ hg convert -d svn a --filemap filemap --full + assuming destination a-hg + initializing svn working copy 'a-hg-wc' + scanning source... + sorting... + converting... + 0 f + $ svnupanddisplay a-hg-wc 1 + 9 9 test . + 9 9 test d + 9 9 test f + revision: 9 + author: test + msg: f + D /c + A /d + D /d1 + A /f + D /newlink + $ rm -rf a a-hg a-hg-wc
--- a/tests/test-convert-svn-source.t Sat Aug 30 15:13:02 2014 +0200 +++ b/tests/test-convert-svn-source.t Sat Aug 30 18:44:59 2014 +0200 @@ -1,5 +1,4 @@ - - $ "$TESTDIR/hghave" svn svn-bindings || exit 80 +#require svn svn-bindings $ cat >> $HGRCPATH <<EOF > [extensions] @@ -169,6 +168,27 @@ | o 0 second letter files: letter2.txt +Convert with --full adds and removes files that didn't change + + $ cd B + $ echo >> "letter .txt" + $ svn ci -m 'nothing' + Sending letter .txt + Transmitting file data . + Committed revision 9. + $ cd .. + + $ echo 'rename letter2.txt letter3.txt' > filemap + $ hg convert --filemap filemap --full "$SVNREPOURL/proj%20B/mytrunk" fmap + scanning source... + sorting... + converting... + 0 nothing + $ hg -R fmap st --change tip + A letter .txt + A letter3.txt + R letter2.txt + test invalid splicemap1 $ cat > splicemap <<EOF
--- a/tests/test-convert-svn-startrev.t Sat Aug 30 15:13:02 2014 +0200 +++ b/tests/test-convert-svn-startrev.t Sat Aug 30 18:44:59 2014 +0200 @@ -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 Sat Aug 30 15:13:02 2014 +0200 +++ b/tests/test-convert-svn-tags.t Sat Aug 30 18:44:59 2014 +0200 @@ -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 Sat Aug 30 15:13:02 2014 +0200 +++ b/tests/test-convert-tagsbranch-topology.t Sat Aug 30 18:44:59 2014 +0200 @@ -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 Sat Aug 30 15:13:02 2014 +0200 +++ b/tests/test-convert-tla.t Sat Aug 30 18:44:59 2014 +0200 @@ -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-convert.t Sat Aug 30 15:13:02 2014 +0200 +++ b/tests/test-convert.t Sat Aug 30 18:44:59 2014 +0200 @@ -91,6 +91,13 @@ directory if it is converted. To rename from a subdirectory into the root of the repository, use "." as the path to rename to. + "--full" will make sure the converted changesets contain exactly the right + files with the right content. It will make a full conversion of all files, + not just the ones that have changed. Files that already are correct will + not be changed. This can be used to apply filemap changes when converting + incrementally. This is currently only supported for Mercurial and + Subversion. + The splicemap is a file that allows insertion of synthetic history, letting you specify the parents of a revision. This is useful if you want to e.g. give a Subversion merge two parents, or graft two disconnected @@ -265,6 +272,7 @@ -r --rev REV import up to source revision REV -A --authormap FILE remap usernames using this file --filemap FILE remap file names using contents of file + --full apply filemap changes by converting all files again --splicemap FILE splice synthesized history into place --branchmap FILE change branch names while converting --branchsort try to sort changesets by branches @@ -272,7 +280,7 @@ --sourcesort preserve source changesets order --closesort try to reorder closed revisions - use "hg -v help convert" to show the global options + (some details hidden, use --verbose to show complete help) $ hg init a $ cd a $ echo a > a
--- a/tests/test-diff-upgrade.t Sat Aug 30 15:13:02 2014 +0200 +++ b/tests/test-diff-upgrade.t Sat Aug 30 18:44:59 2014 +0200 @@ -1,4 +1,4 @@ - $ "$TESTDIR/hghave" execbit || exit 80 +#require execbit $ echo "[extensions]" >> $HGRCPATH $ echo "autodiff=$TESTDIR/autodiff.py" >> $HGRCPATH
--- a/tests/test-dispatch.t Sat Aug 30 15:13:02 2014 +0200 +++ b/tests/test-dispatch.t Sat Aug 30 18:44:59 2014 +0200 @@ -19,7 +19,7 @@ output the current or given revision of files - options: + options ([+] can be repeated): -o --output FORMAT print output to file with formatted name -r --rev REV print the given revision @@ -27,9 +27,7 @@ -I --include PATTERN [+] include names matching the given patterns -X --exclude PATTERN [+] exclude names matching the given patterns - [+] marked option can be specified multiple times - - use "hg help cat" to show the full help text + (use "hg cat -h" to show more help) [255] [defaults]
--- a/tests/test-encoding-align.t Sat Aug 30 15:13:02 2014 +0200 +++ b/tests/test-encoding-align.t Sat Aug 30 18:44:59 2014 +0200 @@ -58,7 +58,7 @@ \xe9\x95\xb7\xe3\x81\x84\xe9\x95\xb7\xe3\x81\x84\xe5\x90\x8d\xe5\x89\x8d \xe9\x95\xb7\xe3\x81\x84\xe9\x95\xb7\xe3\x81\x84\xe5\x90\x8d\xe5\x89\x8d \xe9\x95\xb7\xe3\x81\x84\xe9\x95\xb7\xe3\x81\x84\xe5\x90\x8d\xe5\x89\x8d \xe9\x95\xb7\xe3\x81\x84\xe9\x95\xb7\xe3\x81\x84\xe5\x90\x8d\xe5\x89\x8d (esc) \xe9\x95\xb7\xe3\x81\x84\xe9\x95\xb7\xe3\x81\x84\xe5\x90\x8d\xe5\x89\x8d (esc) - use "hg -v help showoptlist" to show the global options + (some details hidden, use --verbose to show complete help) $ rm -f s; touch s
--- a/tests/test-encoding-textwrap.t Sat Aug 30 15:13:02 2014 +0200 +++ b/tests/test-encoding-textwrap.t Sat Aug 30 18:44:59 2014 +0200 @@ -69,7 +69,7 @@ \x82\xa0\x82\xa2\x82\xa4\x82\xa6\x82\xa8\x82\xa9\x82\xab\x82\xad\x82\xaf\x82\xa0\x82\xa2\x82\xa4\x82\xa6\x82\xa8\x82\xa9\x82\xab\x82\xad\x82\xaf\x82\xa0\x82\xa2\x82\xa4\x82\xa6\x82\xa8\x82\xa9\x82\xab\x82\xad\x82\xaf (esc) \x82\xa0\x82\xa2\x82\xa4\x82\xa6\x82\xa8\x82\xa9\x82\xab\x82\xad\x82\xaf (esc) - use "hg -v help show_full_ja" to show the global options + (some details hidden, use --verbose to show complete help) (1-2) display Japanese full-width characters in utf-8 @@ -84,7 +84,7 @@ \xe3\x81\x82\xe3\x81\x84\xe3\x81\x86\xe3\x81\x88\xe3\x81\x8a\xe3\x81\x8b\xe3\x81\x8d\xe3\x81\x8f\xe3\x81\x91\xe3\x81\x82\xe3\x81\x84\xe3\x81\x86\xe3\x81\x88\xe3\x81\x8a\xe3\x81\x8b\xe3\x81\x8d\xe3\x81\x8f\xe3\x81\x91\xe3\x81\x82\xe3\x81\x84\xe3\x81\x86\xe3\x81\x88\xe3\x81\x8a\xe3\x81\x8b\xe3\x81\x8d\xe3\x81\x8f\xe3\x81\x91 (esc) \xe3\x81\x82\xe3\x81\x84\xe3\x81\x86\xe3\x81\x88\xe3\x81\x8a\xe3\x81\x8b\xe3\x81\x8d\xe3\x81\x8f\xe3\x81\x91 (esc) - use "hg -v help show_full_ja" to show the global options + (some details hidden, use --verbose to show complete help) (1-3) display Japanese half-width characters in cp932 @@ -100,7 +100,7 @@ \xb1\xb2\xb3\xb4\xb5\xb6\xb7\xb8\xb9\xb1\xb2\xb3\xb4\xb5\xb6\xb7\xb8\xb9\xb1\xb2\xb3\xb4\xb5\xb6\xb7\xb8\xb9\xb1\xb2\xb3\xb4\xb5\xb6\xb7\xb8\xb9\xb1\xb2\xb3\xb4\xb5\xb6\xb7\xb8\xb9\xb1\xb2\xb3\xb4\xb5\xb6\xb7\xb8\xb9 (esc) \xb1\xb2\xb3\xb4\xb5\xb6\xb7\xb8\xb9\xb1\xb2\xb3\xb4\xb5\xb6\xb7\xb8\xb9 (esc) - use "hg -v help show_half_ja" to show the global options + (some details hidden, use --verbose to show complete help) (1-4) display Japanese half-width characters in utf-8 @@ -115,7 +115,7 @@ \xef\xbd\xb1\xef\xbd\xb2\xef\xbd\xb3\xef\xbd\xb4\xef\xbd\xb5\xef\xbd\xb6\xef\xbd\xb7\xef\xbd\xb8\xef\xbd\xb9\xef\xbd\xb1\xef\xbd\xb2\xef\xbd\xb3\xef\xbd\xb4\xef\xbd\xb5\xef\xbd\xb6\xef\xbd\xb7\xef\xbd\xb8\xef\xbd\xb9\xef\xbd\xb1\xef\xbd\xb2\xef\xbd\xb3\xef\xbd\xb4\xef\xbd\xb5\xef\xbd\xb6\xef\xbd\xb7\xef\xbd\xb8\xef\xbd\xb9\xef\xbd\xb1\xef\xbd\xb2\xef\xbd\xb3\xef\xbd\xb4\xef\xbd\xb5\xef\xbd\xb6\xef\xbd\xb7\xef\xbd\xb8\xef\xbd\xb9\xef\xbd\xb1\xef\xbd\xb2\xef\xbd\xb3\xef\xbd\xb4\xef\xbd\xb5\xef\xbd\xb6\xef\xbd\xb7\xef\xbd\xb8\xef\xbd\xb9\xef\xbd\xb1\xef\xbd\xb2\xef\xbd\xb3\xef\xbd\xb4\xef\xbd\xb5\xef\xbd\xb6\xef\xbd\xb7\xef\xbd\xb8\xef\xbd\xb9 (esc) \xef\xbd\xb1\xef\xbd\xb2\xef\xbd\xb3\xef\xbd\xb4\xef\xbd\xb5\xef\xbd\xb6\xef\xbd\xb7\xef\xbd\xb8\xef\xbd\xb9\xef\xbd\xb1\xef\xbd\xb2\xef\xbd\xb3\xef\xbd\xb4\xef\xbd\xb5\xef\xbd\xb6\xef\xbd\xb7\xef\xbd\xb8\xef\xbd\xb9 (esc) - use "hg -v help show_half_ja" to show the global options + (some details hidden, use --verbose to show complete help) @@ -136,7 +136,7 @@ \x83\xbf\x83\xc0\x83\xc1\x83\xc2\x83\xd2\x83\xc4\x83\xc5\x83\xc6\x81\x9b\x83\xbf\x83\xc0\x83\xc1\x83\xc2\x83\xd2\x83\xc4\x83\xc5\x83\xc6\x81\x9b\x83\xbf\x83\xc0\x83\xc1\x83\xc2\x83\xd2\x83\xc4\x83\xc5\x83\xc6\x81\x9b\x83\xbf\x83\xc0\x83\xc1\x83\xc2\x83\xd2\x83\xc4\x83\xc5\x83\xc6\x81\x9b\x83\xbf\x83\xc0\x83\xc1\x83\xc2\x83\xd2\x83\xc4\x83\xc5\x83\xc6\x81\x9b\x83\xbf\x83\xc0\x83\xc1\x83\xc2\x83\xd2\x83\xc4\x83\xc5\x83\xc6\x81\x9b (esc) \x83\xbf\x83\xc0\x83\xc1\x83\xc2\x83\xd2\x83\xc4\x83\xc5\x83\xc6\x81\x9b (esc) - use "hg -v help show_ambig_ja" to show the global options + (some details hidden, use --verbose to show complete help) (2-1-2) display Japanese ambiguous-width characters in utf-8 @@ -151,7 +151,7 @@ \xce\xb1\xce\xb2\xce\xb3\xce\xb4\xcf\x85\xce\xb6\xce\xb7\xce\xb8\xe2\x97\x8b\xce\xb1\xce\xb2\xce\xb3\xce\xb4\xcf\x85\xce\xb6\xce\xb7\xce\xb8\xe2\x97\x8b\xce\xb1\xce\xb2\xce\xb3\xce\xb4\xcf\x85\xce\xb6\xce\xb7\xce\xb8\xe2\x97\x8b\xce\xb1\xce\xb2\xce\xb3\xce\xb4\xcf\x85\xce\xb6\xce\xb7\xce\xb8\xe2\x97\x8b\xce\xb1\xce\xb2\xce\xb3\xce\xb4\xcf\x85\xce\xb6\xce\xb7\xce\xb8\xe2\x97\x8b\xce\xb1\xce\xb2\xce\xb3\xce\xb4\xcf\x85\xce\xb6\xce\xb7\xce\xb8\xe2\x97\x8b (esc) \xce\xb1\xce\xb2\xce\xb3\xce\xb4\xcf\x85\xce\xb6\xce\xb7\xce\xb8\xe2\x97\x8b (esc) - use "hg -v help show_ambig_ja" to show the global options + (some details hidden, use --verbose to show complete help) (2-1-3) display Russian ambiguous-width characters in cp1251 @@ -166,7 +166,7 @@ \xcd\xe0\xf1\xf2\xf0\xee\xe9\xea\xe8\xcd\xe0\xf1\xf2\xf0\xee\xe9\xea\xe8\xcd\xe0\xf1\xf2\xf0\xee\xe9\xea\xe8\xcd\xe0\xf1\xf2\xf0\xee\xe9\xea\xe8\xcd\xe0\xf1\xf2\xf0\xee\xe9\xea\xe8\xcd\xe0\xf1\xf2\xf0\xee\xe9\xea\xe8 (esc) \xcd\xe0\xf1\xf2\xf0\xee\xe9\xea\xe8 (esc) - use "hg -v help show_ambig_ru" to show the global options + (some details hidden, use --verbose to show complete help) (2-1-4) display Russian ambiguous-width characters in utf-8 @@ -181,7 +181,7 @@ \xd0\x9d\xd0\xb0\xd1\x81\xd1\x82\xd1\x80\xd0\xbe\xd0\xb9\xd0\xba\xd0\xb8\xd0\x9d\xd0\xb0\xd1\x81\xd1\x82\xd1\x80\xd0\xbe\xd0\xb9\xd0\xba\xd0\xb8\xd0\x9d\xd0\xb0\xd1\x81\xd1\x82\xd1\x80\xd0\xbe\xd0\xb9\xd0\xba\xd0\xb8\xd0\x9d\xd0\xb0\xd1\x81\xd1\x82\xd1\x80\xd0\xbe\xd0\xb9\xd0\xba\xd0\xb8\xd0\x9d\xd0\xb0\xd1\x81\xd1\x82\xd1\x80\xd0\xbe\xd0\xb9\xd0\xba\xd0\xb8\xd0\x9d\xd0\xb0\xd1\x81\xd1\x82\xd1\x80\xd0\xbe\xd0\xb9\xd0\xba\xd0\xb8 (esc) \xd0\x9d\xd0\xb0\xd1\x81\xd1\x82\xd1\x80\xd0\xbe\xd0\xb9\xd0\xba\xd0\xb8 (esc) - use "hg -v help show_ambig_ru" to show the global options + (some details hidden, use --verbose to show complete help) (2-2) treat width of ambiguous characters as wide @@ -202,7 +202,7 @@ \x83\xbf\x83\xc0\x83\xc1\x83\xc2\x83\xd2\x83\xc4\x83\xc5\x83\xc6\x81\x9b\x83\xbf\x83\xc0\x83\xc1\x83\xc2\x83\xd2\x83\xc4\x83\xc5\x83\xc6\x81\x9b\x83\xbf\x83\xc0\x83\xc1\x83\xc2\x83\xd2\x83\xc4\x83\xc5\x83\xc6\x81\x9b (esc) \x83\xbf\x83\xc0\x83\xc1\x83\xc2\x83\xd2\x83\xc4\x83\xc5\x83\xc6\x81\x9b (esc) - use "hg -v help show_ambig_ja" to show the global options + (some details hidden, use --verbose to show complete help) (2-2-2) display Japanese ambiguous-width characters in utf-8 @@ -220,7 +220,7 @@ \xce\xb1\xce\xb2\xce\xb3\xce\xb4\xcf\x85\xce\xb6\xce\xb7\xce\xb8\xe2\x97\x8b\xce\xb1\xce\xb2\xce\xb3\xce\xb4\xcf\x85\xce\xb6\xce\xb7\xce\xb8\xe2\x97\x8b\xce\xb1\xce\xb2\xce\xb3\xce\xb4\xcf\x85\xce\xb6\xce\xb7\xce\xb8\xe2\x97\x8b (esc) \xce\xb1\xce\xb2\xce\xb3\xce\xb4\xcf\x85\xce\xb6\xce\xb7\xce\xb8\xe2\x97\x8b (esc) - use "hg -v help show_ambig_ja" to show the global options + (some details hidden, use --verbose to show complete help) (2-2-3) display Russian ambiguous-width characters in cp1251 @@ -238,7 +238,7 @@ \xcd\xe0\xf1\xf2\xf0\xee\xe9\xea\xe8\xcd\xe0\xf1\xf2\xf0\xee\xe9\xea\xe8\xcd\xe0\xf1\xf2\xf0\xee\xe9\xea\xe8 (esc) \xcd\xe0\xf1\xf2\xf0\xee\xe9\xea\xe8 (esc) - use "hg -v help show_ambig_ru" to show the global options + (some details hidden, use --verbose to show complete help) (2-2-4) display Russian ambiguous-width characters in utf-8 @@ -256,6 +256,6 @@ \xd0\x9d\xd0\xb0\xd1\x81\xd1\x82\xd1\x80\xd0\xbe\xd0\xb9\xd0\xba\xd0\xb8\xd0\x9d\xd0\xb0\xd1\x81\xd1\x82\xd1\x80\xd0\xbe\xd0\xb9\xd0\xba\xd0\xb8\xd0\x9d\xd0\xb0\xd1\x81\xd1\x82\xd1\x80\xd0\xbe\xd0\xb9\xd0\xba\xd0\xb8 (esc) \xd0\x9d\xd0\xb0\xd1\x81\xd1\x82\xd1\x80\xd0\xbe\xd0\xb9\xd0\xba\xd0\xb8 (esc) - use "hg -v help show_ambig_ru" to show the global options + (some details hidden, use --verbose to show complete help) $ cd ..
--- a/tests/test-eolfilename.t Sat Aug 30 15:13:02 2014 +0200 +++ b/tests/test-eolfilename.t Sat Aug 30 18:44:59 2014 +0200 @@ -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 Sat Aug 30 15:13:02 2014 +0200 +++ b/tests/test-execute-bit.t Sat Aug 30 18:44:59 2014 +0200 @@ -1,4 +1,4 @@ - $ "$TESTDIR/hghave" execbit || exit 80 +#require execbit $ hg init $ echo a > a
--- a/tests/test-extdiff.t Sat Aug 30 15:13:02 2014 +0200 +++ b/tests/test-extdiff.t Sat Aug 30 18:44:59 2014 +0200 @@ -37,7 +37,7 @@ compared to the working directory, and, when no revisions are specified, the working directory files are compared to its parent. - options: + options ([+] can be repeated): -o --option OPT [+] pass option to comparison program -r --rev REV [+] revision @@ -45,9 +45,7 @@ -I --include PATTERN [+] include names matching the given patterns -X --exclude PATTERN [+] exclude names matching the given patterns - [+] marked option can be specified multiple times - - use "hg -v help falabala" to show the global options + (some details hidden, use --verbose to show complete help) $ hg ci -d '0 0' -mtest1
--- a/tests/test-extension.t Sat Aug 30 15:13:02 2014 +0200 +++ b/tests/test-extension.t Sat Aug 30 18:44:59 2014 +0200 @@ -301,7 +301,7 @@ foo yet another foo command - global options: + global options ([+] can be repeated): -R --repository REPO repository root directory or name of overlay bundle file @@ -321,8 +321,6 @@ --version output version information and exit -h --help display help and exit --hidden consider hidden changesets - - [+] marked option can be specified multiple times @@ -337,7 +335,7 @@ debugfoobar yet another debug command foo yet another foo command - global options: + global options ([+] can be repeated): -R --repository REPO repository root directory or name of overlay bundle file @@ -357,8 +355,6 @@ --version output version information and exit -h --help display help and exit --hidden consider hidden changesets - - [+] marked option can be specified multiple times @@ -388,9 +384,9 @@ compared to the working directory, and, when no revisions are specified, the working directory files are compared to its parent. - use "hg help -e extdiff" to show help for the extdiff extension + (use "hg help -e extdiff" to show help for the extdiff extension) - options: + options ([+] can be repeated): -p --program CMD comparison program to run -o --option OPT [+] pass option to comparison program @@ -399,9 +395,7 @@ -I --include PATTERN [+] include names matching the given patterns -X --exclude PATTERN [+] exclude names matching the given patterns - [+] marked option can be specified multiple times - - use "hg -v help extdiff" to show the global options + (some details hidden, use --verbose to show complete help) @@ -469,7 +463,7 @@ extdiff use external program to diff repository (or selected files) - use "hg -v help extdiff" to show builtin aliases and global options + (use "hg help -v extdiff" to show built-in aliases and global options) @@ -533,7 +527,7 @@ multirevs command - use "hg -v help multirevs" to show the global options + (some details hidden, use --verbose to show complete help) @@ -543,7 +537,7 @@ multirevs command - use "hg help multirevs" to show the full help text + (use "hg multirevs -h" to show more help) [255] @@ -588,7 +582,7 @@ patchbomb command to send changesets as (a series of) patch emails - use "hg help extensions" for information on enabling extensions + (use "hg help extensions" for information on enabling extensions) $ hg qdel @@ -597,7 +591,7 @@ mq manage a stack of patches - use "hg help extensions" for information on enabling extensions + (use "hg help extensions" for information on enabling extensions) [255] @@ -607,7 +601,7 @@ churn command to display statistics about repository history - use "hg help extensions" for information on enabling extensions + (use "hg help extensions" for information on enabling extensions) [255] @@ -617,12 +611,12 @@ $ hg help churn churn extension - command to display statistics about repository history - use "hg help extensions" for information on enabling extensions + (use "hg help extensions" for information on enabling extensions) $ hg help patchbomb patchbomb extension - command to send changesets as (a series of) patch emails - use "hg help extensions" for information on enabling extensions + (use "hg help extensions" for information on enabling extensions) Broken disabled extension and command: @@ -642,7 +636,7 @@ $ hg --config extensions.path=./path.py help broken broken extension - (no help text available) - use "hg help extensions" for information on enabling extensions + (use "hg help extensions" for information on enabling extensions) $ cat > hgext/forest.py <<EOF
--- a/tests/test-fetch.t Sat Aug 30 15:13:02 2014 +0200 +++ b/tests/test-fetch.t Sat Aug 30 18:44:59 2014 +0200 @@ -1,4 +1,4 @@ - $ "$TESTDIR/hghave" serve || exit 80 +#require serve $ echo "[extensions]" >> $HGRCPATH $ echo "fetch=" >> $HGRCPATH
--- a/tests/test-flags.t Sat Aug 30 15:13:02 2014 +0200 +++ b/tests/test-flags.t Sat Aug 30 18:44:59 2014 +0200 @@ -1,4 +1,4 @@ - $ "$TESTDIR/hghave" execbit || exit 80 +#require execbit $ umask 027
--- a/tests/test-gendoc.t Sat Aug 30 15:13:02 2014 +0200 +++ b/tests/test-gendoc.t Sat Aug 30 18:44:59 2014 +0200 @@ -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 Sat Aug 30 15:13:02 2014 +0200 +++ b/tests/test-getbundle.t Sat Aug 30 18:44:59 2014 +0200 @@ -1,4 +1,4 @@ - $ "$TESTDIR/hghave" serve || exit 80 +#require serve = Test the getbundle() protocol function =
--- a/tests/test-globalopts.t Sat Aug 30 15:13:02 2014 +0200 +++ b/tests/test-globalopts.t Sat Aug 30 18:44:59 2014 +0200 @@ -357,7 +357,7 @@ templating Template Usage urls URL Paths - use "hg -v help" to show builtin aliases and global options + (use "hg help -v" to show built-in aliases and global options) @@ -439,7 +439,7 @@ templating Template Usage urls URL Paths - use "hg -v help" to show builtin aliases and global options + (use "hg help -v" to show built-in aliases and global options) Not tested: --debugger
--- a/tests/test-glog.t Sat Aug 30 15:13:02 2014 +0200 +++ b/tests/test-glog.t Sat Aug 30 18:44:59 2014 +0200 @@ -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 Sat Aug 30 15:13:02 2014 +0200 +++ b/tests/test-gpg.t Sat Aug 30 18:44:59 2014 +0200 @@ -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 Sat Aug 30 15:13:02 2014 +0200 +++ b/tests/test-graft.t Sat Aug 30 18:44:59 2014 +0200 @@ -632,6 +632,52 @@ 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 Continue testing same origin policy, using revision numbers from test above but do some destructive editing of the repo:
--- a/tests/test-hardlinks.t Sat Aug 30 15:13:02 2014 +0200 +++ b/tests/test-hardlinks.t Sat Aug 30 18:44:59 2014 +0200 @@ -1,4 +1,4 @@ - $ "$TESTDIR/hghave" hardlink || exit 80 +#require hardlink $ cat > nlinks.py <<EOF > import sys
--- a/tests/test-help.t Sat Aug 30 15:13:02 2014 +0200 +++ b/tests/test-help.t Sat Aug 30 18:44:59 2014 +0200 @@ -23,7 +23,7 @@ summary summarize working directory state update update working directory (or switch revisions) - use "hg help" for the full list of commands or "hg -v" for details + (use "hg help" for the full list of commands or "hg -v" for details) $ hg -q add add the specified files on the next commit @@ -122,7 +122,7 @@ templating Template Usage urls URL Paths - use "hg -v help" to show builtin aliases and global options + (use "hg help -v" to show built-in aliases and global options) $ hg -q help add add the specified files on the next commit @@ -305,7 +305,7 @@ update, up, checkout, co update working directory (or switch revisions) - global options: + global options ([+] can be repeated): -R --repository REPO repository root directory or name of overlay bundle file @@ -326,9 +326,7 @@ -h --help display help and exit --hidden consider hidden changesets - [+] marked option can be specified multiple times - - use "hg help" for the full list of commands + (use "hg help" for the full list of commands) $ hg add -h hg add [OPTION]... [FILE]... @@ -344,16 +342,14 @@ Returns 0 if all files are successfully added. - options: + options ([+] can be repeated): -I --include PATTERN [+] include names matching the given patterns -X --exclude PATTERN [+] exclude names matching the given patterns -S --subrepos recurse into subrepositories -n --dry-run do not perform actions, just print output - [+] marked option can be specified multiple times - - use "hg -v help add" to show more complete help and the global options + (some details hidden, use --verbose to show complete help) Verbose help for add @@ -383,16 +379,14 @@ Returns 0 if all files are successfully added. - options: + options ([+] can be repeated): -I --include PATTERN [+] include names matching the given patterns -X --exclude PATTERN [+] exclude names matching the given patterns -S --subrepos recurse into subrepositories -n --dry-run do not perform actions, just print output - [+] marked option can be specified multiple times - - global options: + global options ([+] can be repeated): -R --repository REPO repository root directory or name of overlay bundle file @@ -412,8 +406,6 @@ --version output version information and exit -h --help display help and exit --hidden consider hidden changesets - - [+] marked option can be specified multiple times Test help option with version option @@ -431,16 +423,14 @@ add the specified files on the next commit - options: + options ([+] can be repeated): -I --include PATTERN [+] include names matching the given patterns -X --exclude PATTERN [+] exclude names matching the given patterns -S --subrepos recurse into subrepositories -n --dry-run do not perform actions, just print output - [+] marked option can be specified multiple times - - use "hg help add" to show the full help text + (use "hg add -h" to show more help) [255] Test ambiguous command help @@ -451,7 +441,7 @@ add add the specified files on the next commit addremove add all new files, delete all missing files - use "hg -v help ad" to show builtin aliases and global options + (use "hg help -v ad" to show built-in aliases and global options) Test command without options @@ -472,7 +462,7 @@ Returns 0 on success, 1 if errors are encountered. - use "hg -v help verify" to show the global options + (some details hidden, use --verbose to show complete help) $ hg help diff hg diff [OPTION]... ([-c REV] | [-r REV1 [-r REV2]]) [FILE]... @@ -505,7 +495,7 @@ Returns 0 on success. - options: + options ([+] can be repeated): -r --rev REV [+] revision -c --change REV change made by revision @@ -523,9 +513,7 @@ -X --exclude PATTERN [+] exclude names matching the given patterns -S --subrepos recurse into subrepositories - [+] marked option can be specified multiple times - - use "hg -v help diff" to show more complete help and the global options + (some details hidden, use --verbose to show complete help) $ hg help status hg status [OPTION]... [FILE]... @@ -567,7 +555,7 @@ Returns 0 on success. - options: + options ([+] can be repeated): -A --all show status of all files -m --modified show only modified files @@ -586,9 +574,7 @@ -X --exclude PATTERN [+] exclude names matching the given patterns -S --subrepos recurse into subrepositories - [+] marked option can be specified multiple times - - use "hg -v help status" to show more complete help and the global options + (some details hidden, use --verbose to show complete help) $ hg -q help status hg status [OPTION]... [FILE]... @@ -624,7 +610,7 @@ summary summarize working directory state update update working directory (or switch revisions) - use "hg help" for the full list of commands or "hg -v" for details + (use "hg help" for the full list of commands or "hg -v" for details) [255] @@ -663,7 +649,7 @@ -n -- normal desc --newline VALUE line1 line2 - use "hg -v help nohelp" to show the global options + (some details hidden, use --verbose to show complete help) $ hg help -k nohelp Commands: @@ -758,7 +744,7 @@ templating Template Usage urls URL Paths - use "hg -v help" to show builtin aliases and global options + (use "hg help -v" to show built-in aliases and global options) Test list of internal help commands @@ -820,7 +806,7 @@ debugwireargs (no help text available) - use "hg -v help debug" to show builtin aliases and global options + (use "hg help -v debug" to show built-in aliases and global options) Test list of commands with command with no help text @@ -832,7 +818,7 @@ nohelp (no help text available) - use "hg -v help helpext" to show builtin aliases and global options + (use "hg help -v helpext" to show built-in aliases and global options) test deprecated option is hidden in command help @@ -843,7 +829,7 @@ options: - use "hg -v help debugoptDEP" to show the global options + (some details hidden, use --verbose to show complete help) test deprecated option is shown with -v $ hg help -v debugoptDEP | grep dopt @@ -857,9 +843,9 @@ (*) (glob) - flaggor: + options: - *"hg -v help debugoptDEP"* (glob) + (some details hidden, use --verbose to show complete help) #endif Test commands that collide with topics (issue4240) @@ -1030,7 +1016,7 @@ This paragraph is never omitted, too (for extension) - use "hg help -v addverboseitems" to show more complete help + (some details hidden, use --verbose to show complete help) no commands defined $ hg help -v addverboseitems @@ -1051,7 +1037,7 @@ This paragraph is never omitted, too (for topic) - use "hg help -v topic-containing-verbose" to show more complete help + (some details hidden, use --verbose to show complete help) $ hg help -v topic-containing-verbose This is the topic to test omit indicating. """""""""""""""""""""""""""""""""""""""""" @@ -1715,7 +1701,7 @@ Returns 0 if all files are successfully added. </p> <p> - options: + options ([+] can be repeated): </p> <table> <tr><td>-I</td> @@ -1732,10 +1718,7 @@ <td>do not perform actions, just print output</td></tr> </table> <p> - [+] marked option can be specified multiple times - </p> - <p> - global options: + global options ([+] can be repeated): </p> <table> <tr><td>-R</td> @@ -1787,9 +1770,6 @@ <td>--hidden</td> <td>consider hidden changesets</td></tr> </table> - <p> - [+] marked option can be specified multiple times - </p> </div> </div> @@ -1911,7 +1891,7 @@ Returns 0 on success, 1 if any warnings encountered. </p> <p> - options: + options ([+] can be repeated): </p> <table> <tr><td>-A</td> @@ -1928,10 +1908,7 @@ <td>exclude names matching the given patterns</td></tr> </table> <p> - [+] marked option can be specified multiple times - </p> - <p> - global options: + global options ([+] can be repeated): </p> <table> <tr><td>-R</td> @@ -1983,9 +1960,6 @@ <td>--hidden</td> <td>consider hidden changesets</td></tr> </table> - <p> - [+] marked option can be specified multiple times - </p> </div> </div>
--- a/tests/test-hgrc.t Sat Aug 30 15:13:02 2014 +0200 +++ b/tests/test-hgrc.t Sat Aug 30 18:44:59 2014 +0200 @@ -43,6 +43,7 @@ $ echo ' x = y' >> $HGRC $ hg version hg: parse error at $TESTTMP/hgrc:2: x = y + unexpected leading whitespace [255] $ python -c "print '[foo]\nbar = a\n b\n c \n de\n fg \nbaz = bif cb \n'" \
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tests/test-hgweb-bundle.t Sat Aug 30 18:44:59 2014 +0200 @@ -0,0 +1,37 @@ +#require serve + + $ hg init server + $ cd server + $ cat >> .hg/hgrc << EOF + > [extensions] + > strip= + > EOF + + $ echo 1 > foo + $ hg commit -A -m 'first' + adding foo + $ echo 2 > bar + $ hg commit -A -m 'second' + adding bar + +Produce a bundle to use + + $ hg strip -r 1 + 0 files updated, 0 files merged, 1 files removed, 0 files unresolved + saved backup bundle to $TESTTMP/server/.hg/strip-backup/ed602e697e0f-backup.hg (glob) + +Serve from a bundle file + + $ hg serve -R .hg/strip-backup/ed602e697e0f-backup.hg -d -p $HGPORT --pid-file=hg.pid + $ cat hg.pid >> $DAEMON_PIDS + +Ensure we're serving from the bundle + + $ ("$TESTDIR/get-with-headers.py" localhost:$HGPORT 'file/tip/?style=raw') + 200 Script output follows + + + -rw-r--r-- 2 bar + -rw-r--r-- 2 foo + +
--- a/tests/test-hgweb-commands.t Sat Aug 30 15:13:02 2014 +0200 +++ b/tests/test-hgweb-commands.t Sat Aug 30 18:44:59 2014 +0200 @@ -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 Sat Aug 30 15:13:02 2014 +0200 +++ b/tests/test-hgweb-descend-empties.t Sat Aug 30 18:44:59 2014 +0200 @@ -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 Sat Aug 30 15:13:02 2014 +0200 +++ b/tests/test-hgweb-diffs.t Sat Aug 30 18:44:59 2014 +0200 @@ -1,4 +1,4 @@ - $ "$TESTDIR/hghave" serve || exit 80 +#require serve setting up repo
--- a/tests/test-hgweb-empty.t Sat Aug 30 15:13:02 2014 +0200 +++ b/tests/test-hgweb-empty.t Sat Aug 30 18:44:59 2014 +0200 @@ -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 Sat Aug 30 15:13:02 2014 +0200 +++ b/tests/test-hgweb-filelog.t Sat Aug 30 18:44:59 2014 +0200 @@ -1,4 +1,4 @@ - $ "$TESTDIR/hghave" serve || exit 80 +#require serve $ hg init test $ cd test
--- a/tests/test-hgweb-raw.t Sat Aug 30 15:13:02 2014 +0200 +++ b/tests/test-hgweb-raw.t Sat Aug 30 18:44:59 2014 +0200 @@ -1,4 +1,4 @@ - $ "$TESTDIR/hghave" serve || exit 80 +#require serve Test raw style of hgweb
--- a/tests/test-hgweb-removed.t Sat Aug 30 15:13:02 2014 +0200 +++ b/tests/test-hgweb-removed.t Sat Aug 30 18:44:59 2014 +0200 @@ -1,4 +1,4 @@ - $ "$TESTDIR/hghave" serve || exit 80 +#require serve setting up repo
--- a/tests/test-hgweb.t Sat Aug 30 15:13:02 2014 +0200 +++ b/tests/test-hgweb.t Sat Aug 30 18:44:59 2014 +0200 @@ -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 Sat Aug 30 15:13:02 2014 +0200 +++ b/tests/test-hgwebdir.t Sat Aug 30 18:44:59 2014 +0200 @@ -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 Sat Aug 30 15:13:02 2014 +0200 +++ b/tests/test-hgwebdirsym.t Sat Aug 30 18:44:59 2014 +0200 @@ -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 Sat Aug 30 15:13:02 2014 +0200 +++ b/tests/test-highlight.t Sat Aug 30 18:44:59 2014 +0200 @@ -1,5 +1,5 @@ +#require pygments serve - $ "$TESTDIR/hghave" pygments serve || exit 80 $ cat <<EOF >> $HGRCPATH > [extensions] > highlight =
--- a/tests/test-histedit-arguments.t Sat Aug 30 15:13:02 2014 +0200 +++ b/tests/test-histedit-arguments.t Sat Aug 30 18:44:59 2014 +0200 @@ -57,6 +57,7 @@ # p, pick = use commit # e, edit = use commit, but stop for amending # f, fold = use commit, but combine it with the one above + # r, roll = like fold, but discard this commit's description # d, drop = remove commit from history # m, mess = edit message without changing commit content # @@ -255,6 +256,7 @@ # p, pick = use commit # e, edit = use commit, but stop for amending # f, fold = use commit, but combine it with the one above + # r, roll = like fold, but discard this commit's description # d, drop = remove commit from history # m, mess = edit message without changing commit content #
--- a/tests/test-histedit-bookmark-motion.t Sat Aug 30 15:13:02 2014 +0200 +++ b/tests/test-histedit-bookmark-motion.t Sat Aug 30 18:44:59 2014 +0200 @@ -73,6 +73,7 @@ # p, pick = use commit # e, edit = use commit, but stop for amending # f, fold = use commit, but combine it with the one above + # r, roll = like fold, but discard this commit's description # d, drop = remove commit from history # m, mess = edit message without changing commit content # @@ -133,6 +134,7 @@ # p, pick = use commit # e, edit = use commit, but stop for amending # f, fold = use commit, but combine it with the one above + # r, roll = like fold, but discard this commit's description # d, drop = remove commit from history # m, mess = edit message without changing commit content #
--- a/tests/test-histedit-commute.t Sat Aug 30 15:13:02 2014 +0200 +++ b/tests/test-histedit-commute.t Sat Aug 30 18:44:59 2014 +0200 @@ -67,6 +67,7 @@ # p, pick = use commit # e, edit = use commit, but stop for amending # f, fold = use commit, but combine it with the one above + # r, roll = like fold, but discard this commit's description # d, drop = remove commit from history # m, mess = edit message without changing commit content # @@ -344,6 +345,7 @@ # p, pick = use commit # e, edit = use commit, but stop for amending # f, fold = use commit, but combine it with the one above + # r, roll = like fold, but discard this commit's description # d, drop = remove commit from history # m, mess = edit message without changing commit content #
--- a/tests/test-histedit-fold-non-commute.t Sat Aug 30 15:13:02 2014 +0200 +++ b/tests/test-histedit-fold-non-commute.t Sat Aug 30 18:44:59 2014 +0200 @@ -183,3 +183,165 @@ f $ cd .. + +Repeat test using "roll", not "fold". "roll" folds in changes but drops message + + $ initrepo r2 + $ cd r2 + +Initial generation of the command files + + $ EDITED="$TESTTMP/editedhistory.2" + $ hg log --template 'pick {node|short} {rev} {desc}\n' -r 3 >> $EDITED + $ hg log --template 'pick {node|short} {rev} {desc}\n' -r 4 >> $EDITED + $ hg log --template 'roll {node|short} {rev} {desc}\n' -r 7 >> $EDITED + $ hg log --template 'pick {node|short} {rev} {desc}\n' -r 5 >> $EDITED + $ hg log --template 'pick {node|short} {rev} {desc}\n' -r 6 >> $EDITED + $ cat $EDITED + pick 65a9a84f33fd 3 c + pick 00f1c5383965 4 d + roll 39522b764e3d 7 does not commute with e + pick 7b4e2f4b7bcd 5 e + pick 500cac37a696 6 f + +log before edit + $ hg log --graph + @ changeset: 7:39522b764e3d + | tag: tip + | user: test + | date: Thu Jan 01 00:00:00 1970 +0000 + | summary: does not commute with e + | + o changeset: 6:500cac37a696 + | user: test + | date: Thu Jan 01 00:00:00 1970 +0000 + | summary: f + | + o changeset: 5:7b4e2f4b7bcd + | user: test + | date: Thu Jan 01 00:00:00 1970 +0000 + | summary: e + | + o changeset: 4:00f1c5383965 + | user: test + | date: Thu Jan 01 00:00:00 1970 +0000 + | summary: d + | + o changeset: 3:65a9a84f33fd + | user: test + | date: Thu Jan 01 00:00:00 1970 +0000 + | summary: c + | + o changeset: 2:da6535b52e45 + | user: test + | date: Thu Jan 01 00:00:00 1970 +0000 + | summary: b + | + o changeset: 1:c1f09da44841 + | user: test + | date: Thu Jan 01 00:00:00 1970 +0000 + | summary: a + | + o changeset: 0:1715188a53c7 + user: test + date: Thu Jan 01 00:00:00 1970 +0000 + summary: Initial commit + + +edit the history + $ hg histedit 3 --commands $EDITED 2>&1 | fixbundle + 2 files updated, 0 files merged, 0 files removed, 0 files unresolved + merging e + warning: conflicts during merge. + merging e incomplete! (edit conflicts, then use 'hg resolve --mark') + Fix up the change and run hg histedit --continue + +fix up + $ echo 'I can haz no commute' > e + $ hg resolve --mark e + (no more unresolved files) + $ hg histedit --continue 2>&1 | fixbundle | grep -v '2 files removed' + 2 files updated, 0 files merged, 0 files removed, 0 files unresolved + 2 files updated, 0 files merged, 0 files removed, 0 files unresolved + 0 files updated, 0 files merged, 0 files removed, 0 files unresolved + merging e + warning: conflicts during merge. + merging e incomplete! (edit conflicts, then use 'hg resolve --mark') + Fix up the change and run hg histedit --continue + +just continue this time + $ hg revert -r 'p1()' e + $ hg resolve --mark e + (no more unresolved files) + $ hg histedit --continue 2>&1 | fixbundle + 0 files updated, 0 files merged, 0 files removed, 0 files unresolved + 0 files updated, 0 files merged, 0 files removed, 0 files unresolved + +log after edit + $ hg log --graph + @ changeset: 5:e7c4f5d4eb75 + | tag: tip + | user: test + | date: Thu Jan 01 00:00:00 1970 +0000 + | summary: f + | + o changeset: 4:803d1bb561fc + | user: test + | date: Thu Jan 01 00:00:00 1970 +0000 + | summary: d + | + o changeset: 3:65a9a84f33fd + | user: test + | date: Thu Jan 01 00:00:00 1970 +0000 + | summary: c + | + o changeset: 2:da6535b52e45 + | user: test + | date: Thu Jan 01 00:00:00 1970 +0000 + | summary: b + | + o changeset: 1:c1f09da44841 + | user: test + | date: Thu Jan 01 00:00:00 1970 +0000 + | summary: a + | + o changeset: 0:1715188a53c7 + user: test + date: Thu Jan 01 00:00:00 1970 +0000 + summary: Initial commit + + +contents of e + $ hg cat e + I can haz no commute + +manifest + $ hg manifest + a + b + c + d + e + f + +description is taken from rollup target commit + + $ hg log --debug --rev 4 + changeset: 4:803d1bb561fceac3129ec778db9da249a3106fc3 + phase: draft + parent: 3:65a9a84f33fdeb1ad5679b3941ec885d2b24027b + parent: -1:0000000000000000000000000000000000000000 + manifest: 4:b068a323d969f22af1296ec6a5ea9384cef437ac + user: test + date: Thu Jan 01 00:00:00 1970 +0000 + files: d e + extra: branch=default + extra: histedit_source=00f1c53839651fa5c76d423606811ea5455a79d0,39522b764e3d26103f08bd1fa2ccd3e3d7dbcf4e + description: + d + + + +done with repo r2 + + $ cd ..
--- a/tests/test-histedit-fold.t Sat Aug 30 15:13:02 2014 +0200 +++ b/tests/test-histedit-fold.t Sat Aug 30 18:44:59 2014 +0200 @@ -105,6 +105,50 @@ +rollup will fold without preserving the folded commit's message + + $ hg histedit d2ae7f538514 --commands - 2>&1 <<EOF | fixbundle + > pick d2ae7f538514 b + > roll ee283cb5f2d5 e + > pick 6de59d13424a f + > pick 9c277da72c9b d + > EOF + 0 files updated, 0 files merged, 4 files removed, 0 files unresolved + 0 files updated, 0 files merged, 2 files removed, 0 files unresolved + 2 files updated, 0 files merged, 0 files removed, 0 files unresolved + 0 files updated, 0 files merged, 0 files removed, 0 files unresolved + 0 files updated, 0 files merged, 0 files removed, 0 files unresolved + 0 files updated, 0 files merged, 0 files removed, 0 files unresolved + +log after edit + $ hg logt --graph + @ 3:c4a9eb7989fc d + | + o 2:8e03a72b6f83 f + | + o 1:391ee782c689 b + | + o 0:cb9a9f314b8b a + + +description is taken from rollup target commit + + $ hg log --debug --rev 1 + changeset: 1:391ee782c68930be438ccf4c6a403daedbfbffa5 + phase: draft + parent: 0:cb9a9f314b8b07ba71012fcdbc544b5a4d82ff5b + parent: -1:0000000000000000000000000000000000000000 + manifest: 1:b5e112a3a8354e269b1524729f0918662d847c38 + user: test + date: Thu Jan 01 00:00:00 1970 +0000 + files+: b e + extra: branch=default + extra: histedit_source=d2ae7f538514cd87c17547b0de4cea71fe1af9fb,ee283cb5f2d5955443f23a27b697a04339e9a39a + description: + b + + + check saving last-message.txt $ cat > $TESTTMP/abortfolding.py <<EOF @@ -128,9 +172,9 @@ > EOF $ rm -f .hg/last-message.txt - $ HGEDITOR="sh $TESTTMP/editor.sh" hg histedit 6de59d13424a --commands - 2>&1 <<EOF | fixbundle - > pick 6de59d13424a f - > fold 9c277da72c9b d + $ HGEDITOR="sh $TESTTMP/editor.sh" hg histedit 8e03a72b6f83 --commands - 2>&1 <<EOF | fixbundle + > pick 8e03a72b6f83 f + > fold c4a9eb7989fc d > EOF 0 files updated, 0 files merged, 1 files removed, 0 files unresolved allow non-folding commit
--- a/tests/test-histedit-obsolete.t Sat Aug 30 15:13:02 2014 +0200 +++ b/tests/test-histedit-obsolete.t Sat Aug 30 18:44:59 2014 +0200 @@ -57,6 +57,7 @@ # p, pick = use commit # e, edit = use commit, but stop for amending # f, fold = use commit, but combine it with the one above + # r, roll = like fold, but discard this commit's description # d, drop = remove commit from history # m, mess = edit message without changing commit content # @@ -89,11 +90,11 @@ o 0:cb9a9f314b8b a $ hg debugobsolete - d2ae7f538514cd87c17547b0de4cea71fe1af9fb 0 {'date': '* *', 'user': 'test'} (glob) - 177f92b773850b59254aa5e923436f921b55483b b346ab9a313db8537ecf96fca3ca3ca984ef3bd7 0 {'date': '* *', 'user': 'test'} (glob) - 055a42cdd88768532f9cf79daa407fc8d138de9b 59d9f330561fd6c88b1a6b32f0e45034d88db784 0 {'date': '* *', 'user': 'test'} (glob) - e860deea161a2f77de56603b340ebbb4536308ae 59d9f330561fd6c88b1a6b32f0e45034d88db784 0 {'date': '* *', 'user': 'test'} (glob) - 652413bf663ef2a641cab26574e46d5f5a64a55a cacdfd884a9321ec4e1de275ef3949fa953a1f83 0 {'date': '* *', 'user': 'test'} (glob) + d2ae7f538514cd87c17547b0de4cea71fe1af9fb 0 {cb9a9f314b8b07ba71012fcdbc544b5a4d82ff5b} (*) {'user': 'test'} (glob) + 177f92b773850b59254aa5e923436f921b55483b b346ab9a313db8537ecf96fca3ca3ca984ef3bd7 0 (*) {'user': 'test'} (glob) + 055a42cdd88768532f9cf79daa407fc8d138de9b 59d9f330561fd6c88b1a6b32f0e45034d88db784 0 (*) {'user': 'test'} (glob) + e860deea161a2f77de56603b340ebbb4536308ae 59d9f330561fd6c88b1a6b32f0e45034d88db784 0 (*) {'user': 'test'} (glob) + 652413bf663ef2a641cab26574e46d5f5a64a55a cacdfd884a9321ec4e1de275ef3949fa953a1f83 0 (*) {'user': 'test'} (glob) Ensure hidden revision does not prevent histedit
--- a/tests/test-histedit-outgoing.t Sat Aug 30 15:13:02 2014 +0200 +++ b/tests/test-histedit-outgoing.t Sat Aug 30 18:44:59 2014 +0200 @@ -49,6 +49,7 @@ # p, pick = use commit # e, edit = use commit, but stop for amending # f, fold = use commit, but combine it with the one above + # r, roll = like fold, but discard this commit's description # d, drop = remove commit from history # m, mess = edit message without changing commit content # @@ -80,6 +81,7 @@ # p, pick = use commit # e, edit = use commit, but stop for amending # f, fold = use commit, but combine it with the one above + # r, roll = like fold, but discard this commit's description # d, drop = remove commit from history # m, mess = edit message without changing commit content # @@ -103,6 +105,7 @@ # p, pick = use commit # e, edit = use commit, but stop for amending # f, fold = use commit, but combine it with the one above + # r, roll = like fold, but discard this commit's description # d, drop = remove commit from history # m, mess = edit message without changing commit content #
--- a/tests/test-hook.t Sat Aug 30 15:13:02 2014 +0200 +++ b/tests/test-hook.t Sat Aug 30 18:44:59 2014 +0200 @@ -210,10 +210,11 @@ $ hg push -B baz ../a pushing to ../a searching for changes + listkeys hook: HG_NAMESPACE=phases HG_VALUES={'cb9a9f314b8b07ba71012fcdbc544b5a4d82ff5b': '1', 'publishing': 'True'} + listkeys hook: HG_NAMESPACE=bookmarks HG_VALUES={'bar': '0000000000000000000000000000000000000000', 'foo': '0000000000000000000000000000000000000000'} 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'} - listkeys hook: HG_NAMESPACE=bookmarks HG_VALUES={'bar': '0000000000000000000000000000000000000000', 'foo': '0000000000000000000000000000000000000000'} exporting bookmark baz prepushkey.forbid hook: HG_KEY=baz HG_NAMESPACE=bookmarks HG_NEW=0000000000000000000000000000000000000000 abort: prepushkey hook exited with status 1
--- a/tests/test-http-branchmap.t Sat Aug 30 15:13:02 2014 +0200 +++ b/tests/test-http-branchmap.t Sat Aug 30 18:44:59 2014 +0200 @@ -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 Sat Aug 30 15:13:02 2014 +0200 +++ b/tests/test-http-clone-r.t Sat Aug 30 18:44:59 2014 +0200 @@ -1,4 +1,4 @@ - $ "$TESTDIR/hghave" serve || exit 80 +#require serve creating 'remote
--- a/tests/test-http-proxy.t Sat Aug 30 15:13:02 2014 +0200 +++ b/tests/test-http-proxy.t Sat Aug 30 18:44:59 2014 +0200 @@ -1,4 +1,4 @@ - $ "$TESTDIR/hghave" serve || exit 80 +#require serve $ hg init a $ cd a
--- a/tests/test-http.t Sat Aug 30 15:13:02 2014 +0200 +++ b/tests/test-http.t Sat Aug 30 18:44:59 2014 +0200 @@ -1,4 +1,4 @@ - $ "$TESTDIR/hghave" serve || exit 80 +#require serve $ hg init test $ cd test @@ -261,13 +261,14 @@ "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=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=bookmarks "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 - "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=bookmarks #endif $ cd ..
--- a/tests/test-https.t Sat Aug 30 15:13:02 2014 +0200 +++ b/tests/test-https.t Sat Aug 30 18:44:59 2014 +0200 @@ -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 Sat Aug 30 15:13:02 2014 +0200 +++ b/tests/test-hup.t Sat Aug 30 18:44:59 2014 +0200 @@ -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 Sat Aug 30 15:13:02 2014 +0200 +++ b/tests/test-i18n.t Sat Aug 30 18:44:59 2014 +0200 @@ -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 Sat Aug 30 15:13:02 2014 +0200 +++ b/tests/test-identify.t Sat Aug 30 18:44:59 2014 +0200 @@ -1,4 +1,4 @@ - $ "$TESTDIR/hghave" serve || exit 80 +#require serve #if no-outer-repo
--- a/tests/test-import-bypass.t Sat Aug 30 15:13:02 2014 +0200 +++ b/tests/test-import-bypass.t Sat Aug 30 18:44:59 2014 +0200 @@ -22,10 +22,13 @@ 0 files updated, 0 files merged, 1 files removed, 0 files unresolved Test importing an existing revision -(this also tests that editor is not invoked for '--bypass', if the -patch contains the commit message, regardless of '--edit') +(this also tests that "hg import" disallows combination of '--exact' +and '--edit') - $ HGEDITOR=cat hg import --bypass --exact --edit ../test.diff + $ hg import --bypass --exact --edit ../test.diff + abort: cannot use --exact with --edit + [255] + $ hg import --bypass --exact ../test.diff applying ../test.diff $ shortlog o 1:4e322f7ce8e3 test 0 0 - foo - changea @@ -66,8 +69,10 @@ repository tip rolled back to revision 1 (undo import) Test --import-branch +(this also tests that editor is not invoked for '--bypass', if the +patch contains the commit message, regardless of '--edit') - $ hg import --bypass --import-branch ../test.diff + $ HGEDITOR=cat hg import --bypass --import-branch --edit ../test.diff applying ../test.diff $ shortlog o 1:4e322f7ce8e3 test 0 0 - foo - changea @@ -221,6 +226,25 @@ $ cd .. +Test avoiding editor invocation at applying the patch with --exact +even if commit message is empty + + $ cd repo-options + + $ echo a >> a + $ hg commit -m ' ' + $ hg tip -T "{node}\n" + 1b77bc7d1db9f0e7f1716d515b630516ab386c89 + $ hg export -o ../empty-log.diff . + $ hg update -q -C ".^1" + $ hg --config extensions.strip= strip -q tip + $ HGEDITOR=cat hg import --exact --bypass ../empty-log.diff + applying ../empty-log.diff + $ hg tip -T "{node}\n" + 1b77bc7d1db9f0e7f1716d515b630516ab386c89 + + $ cd .. + #if symlink execbit Test complicated patch with --exact
--- a/tests/test-import-merge.t Sat Aug 30 15:13:02 2014 +0200 +++ b/tests/test-import-merge.t Sat Aug 30 18:44:59 2014 +0200 @@ -30,6 +30,7 @@ (branch merge, don't forget to commit) $ hg ci -m merge $ hg export . > ../merge.diff + $ grep -v '^merge$' ../merge.diff > ../merge.nomsg.diff $ cd .. $ hg clone -r2 repo repo2 adding changesets @@ -52,8 +53,13 @@ $ hg up 1 0 files updated, 0 files merged, 1 files removed, 0 files unresolved - $ hg import ../merge.diff - applying ../merge.diff + $ cat > $TESTTMP/editor.sh <<EOF + > env | grep HGEDITFORM + > echo merge > \$1 + > EOF + $ HGEDITOR="sh $TESTTMP/editor.sh" hg import --edit ../merge.nomsg.diff + applying ../merge.nomsg.diff + HGEDITFORM=import.normal.merge $ tipparents 1:540395c44225 changea 3:102a90ea7b4a addb
--- a/tests/test-import.t Sat Aug 30 15:13:02 2014 +0200 +++ b/tests/test-import.t Sat Aug 30 18:44:59 2014 +0200 @@ -90,8 +90,13 @@ added 1 changesets with 2 changes to 2 files updating to branch default 2 files updated, 0 files merged, 0 files removed, 0 files unresolved - $ HGEDITOR=cat hg --cwd b import ../diffed-tip.patch + $ cat > $TESTTMP/editor.sh <<EOF + > env | grep HGEDITFORM + > cat \$1 + > EOF + $ HGEDITOR="sh $TESTTMP/editor.sh" hg --cwd b import ../diffed-tip.patch applying ../diffed-tip.patch + HGEDITFORM=import.normal.normal HG: Enter commit message. Lines beginning with 'HG:' are removed. @@ -102,6 +107,22 @@ HG: changed a abort: empty commit message [255] + +Test avoiding editor invocation at applying the patch with --exact, +even if commit message is empty + + $ echo a >> b/a + $ hg --cwd b commit -m ' ' + $ hg --cwd b tip -T "{node}\n" + d8804f3f5396d800812f579c8452796a5993bdb2 + $ hg --cwd b export -o ../empty-log.diff . + $ hg --cwd b update -q -C ".^1" + $ hg --cwd b --config extensions.strip= strip -q tip + $ HGEDITOR=cat hg --cwd b import --exact ../empty-log.diff + applying ../empty-log.diff + $ hg --cwd b tip -T "{node}\n" + d8804f3f5396d800812f579c8452796a5993bdb2 + $ rm -r b
--- a/tests/test-incoming-outgoing.t Sat Aug 30 15:13:02 2014 +0200 +++ b/tests/test-incoming-outgoing.t Sat Aug 30 18:44:59 2014 +0200 @@ -1,4 +1,4 @@ - $ "$TESTDIR/hghave" serve || exit 80 +#require serve $ hg init test $ cd test
--- a/tests/test-inherit-mode.t Sat Aug 30 15:13:02 2014 +0200 +++ b/tests/test-inherit-mode.t Sat Aug 30 18:44:59 2014 +0200 @@ -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 Sat Aug 30 15:13:02 2014 +0200 +++ b/tests/test-issue1438.t Sat Aug 30 18:44:59 2014 +0200 @@ -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 Sat Aug 30 15:13:02 2014 +0200 +++ b/tests/test-issue1802.t Sat Aug 30 18:44:59 2014 +0200 @@ -1,4 +1,4 @@ - $ "$TESTDIR/hghave" execbit || exit 80 +#require execbit Create extension that can disable exec checks:
--- a/tests/test-issue3084.t Sat Aug 30 15:13:02 2014 +0200 +++ b/tests/test-issue3084.t Sat Aug 30 18:44:59 2014 +0200 @@ -29,10 +29,10 @@ $ echo "n" | hg merge --config ui.interactive=Yes remote turned local normal file foo into a largefile - use (l)argefile or keep (n)ormal file? 0 files updated, 0 files merged, 1 files removed, 0 files unresolved + use (l)argefile or keep (n)ormal file? getting changed largefiles + 0 largefiles updated, 0 removed + 0 files updated, 0 files merged, 1 files removed, 0 files unresolved (branch merge, don't forget to commit) - getting changed largefiles - 0 largefiles updated, 0 removed $ hg status $ cat foo @@ -43,10 +43,10 @@ $ hg update -q -C $ echo "l" | hg merge --config ui.interactive=Yes remote turned local normal file foo into a largefile - use (l)argefile or keep (n)ormal file? 1 files updated, 0 files merged, 1 files removed, 0 files unresolved + use (l)argefile or keep (n)ormal file? getting changed largefiles + 1 largefiles updated, 0 removed + 1 files updated, 0 files merged, 1 files removed, 0 files unresolved (branch merge, don't forget to commit) - getting changed largefiles - 1 largefiles updated, 0 removed $ hg status M foo @@ -71,10 +71,10 @@ $ hg update -q -C -r 1 $ echo "n" | hg merge --config ui.interactive=Yes remote turned local largefile foo into a normal file - keep (l)argefile or use (n)ormal file? 1 files updated, 0 files merged, 1 files removed, 0 files unresolved + keep (l)argefile or use (n)ormal file? getting changed largefiles + 0 largefiles updated, 0 removed + 1 files updated, 0 files merged, 1 files removed, 0 files unresolved (branch merge, don't forget to commit) - getting changed largefiles - 0 largefiles updated, 0 removed $ hg status M foo @@ -99,10 +99,10 @@ $ hg update -q -C -r 1 $ echo "l" | hg merge --config ui.interactive=Yes remote turned local largefile foo into a normal file - keep (l)argefile or use (n)ormal file? 0 files updated, 0 files merged, 1 files removed, 0 files unresolved + keep (l)argefile or use (n)ormal file? getting changed largefiles + 1 largefiles updated, 0 removed + 0 files updated, 0 files merged, 1 files removed, 0 files unresolved (branch merge, don't forget to commit) - getting changed largefiles - 1 largefiles updated, 0 removed $ hg status @@ -206,10 +206,10 @@ $ hg up -Cqr normal= $ hg merge -r large + getting changed largefiles + 1 largefiles updated, 0 removed 1 files updated, 0 files merged, 1 files removed, 0 files unresolved (branch merge, don't forget to commit) - getting changed largefiles - 1 largefiles updated, 0 removed $ cat f large @@ -217,10 +217,10 @@ $ hg up -Cqr large $ hg merge -r normal= + getting changed largefiles + 0 largefiles updated, 0 removed 1 files updated, 0 files merged, 0 files removed, 0 files unresolved (branch merge, don't forget to commit) - getting changed largefiles - 0 largefiles updated, 0 removed $ cat f large @@ -233,10 +233,10 @@ use (c)hanged version or (d)elete? c remote turned local normal file f into a largefile use (l)argefile or keep (n)ormal file? l + getting changed largefiles + 1 largefiles updated, 0 removed 1 files updated, 0 files merged, 1 files removed, 0 files unresolved (branch merge, don't forget to commit) - getting changed largefiles - 1 largefiles updated, 0 removed $ cat f large @@ -244,20 +244,20 @@ $ ( echo c; echo n ) | hg merge -r large --config ui.interactive=Yes local changed f which remote deleted use (c)hanged version or (d)elete? remote turned local normal file f into a largefile - use (l)argefile or keep (n)ormal file? 0 files updated, 0 files merged, 1 files removed, 0 files unresolved + use (l)argefile or keep (n)ormal file? getting changed largefiles + 0 largefiles updated, 0 removed + 0 files updated, 0 files merged, 1 files removed, 0 files unresolved (branch merge, don't forget to commit) - getting changed largefiles - 0 largefiles updated, 0 removed $ cat f normal2 $ hg up -Cqr normal2 $ echo d | hg merge -r large --config ui.interactive=Yes local changed f which remote deleted - use (c)hanged version or (d)elete? 1 files updated, 0 files merged, 1 files removed, 0 files unresolved + use (c)hanged version or (d)elete? getting changed largefiles + 1 largefiles updated, 0 removed + 1 files updated, 0 files merged, 1 files removed, 0 files unresolved (branch merge, don't forget to commit) - getting changed largefiles - 1 largefiles updated, 0 removed $ cat f large @@ -269,10 +269,10 @@ use (c)hanged version or leave (d)eleted? c remote turned local largefile f into a normal file keep (l)argefile or use (n)ormal file? l + getting changed largefiles + 1 largefiles updated, 0 removed 1 files updated, 0 files merged, 1 files removed, 0 files unresolved (branch merge, don't forget to commit) - getting changed largefiles - 1 largefiles updated, 0 removed $ cat f large @@ -280,20 +280,20 @@ $ ( echo c; echo n ) | hg merge -r normal2 --config ui.interactive=Yes remote changed f which local deleted use (c)hanged version or leave (d)eleted? remote turned local largefile f into a normal file - keep (l)argefile or use (n)ormal file? 2 files updated, 0 files merged, 1 files removed, 0 files unresolved + keep (l)argefile or use (n)ormal file? getting changed largefiles + 0 largefiles updated, 0 removed + 2 files updated, 0 files merged, 1 files removed, 0 files unresolved (branch merge, don't forget to commit) - getting changed largefiles - 0 largefiles updated, 0 removed $ cat f normal2 $ hg up -Cqr large $ echo d | hg merge -r normal2 --config ui.interactive=Yes remote changed f which local deleted - use (c)hanged version or leave (d)eleted? 1 files updated, 0 files merged, 0 files removed, 0 files unresolved + use (c)hanged version or leave (d)eleted? getting changed largefiles + 0 largefiles updated, 0 removed + 1 files updated, 0 files merged, 0 files removed, 0 files unresolved (branch merge, don't forget to commit) - getting changed largefiles - 0 largefiles updated, 0 removed $ cat f large @@ -301,10 +301,10 @@ $ hg up -Cqr large= $ hg merge -r normal + getting changed largefiles + 0 largefiles updated, 0 removed 1 files updated, 0 files merged, 1 files removed, 0 files unresolved (branch merge, don't forget to commit) - getting changed largefiles - 0 largefiles updated, 0 removed $ cat f normal @@ -326,20 +326,20 @@ use (c)hanged version or (d)elete? c remote turned local largefile f into a normal file keep (l)argefile or use (n)ormal file? l + getting changed largefiles + 1 largefiles updated, 0 removed 0 files updated, 0 files merged, 1 files removed, 0 files unresolved (branch merge, don't forget to commit) - getting changed largefiles - 1 largefiles updated, 0 removed $ cat f large2 $ hg up -Cqr large2 $ echo d | hg merge -r normal --config ui.interactive=Yes local changed .hglf/f which remote deleted - use (c)hanged version or (d)elete? 1 files updated, 0 files merged, 1 files removed, 0 files unresolved + use (c)hanged version or (d)elete? getting changed largefiles + 0 largefiles updated, 0 removed + 1 files updated, 0 files merged, 1 files removed, 0 files unresolved (branch merge, don't forget to commit) - getting changed largefiles - 0 largefiles updated, 0 removed $ cat f normal @@ -351,10 +351,10 @@ use (c)hanged version or leave (d)eleted? c remote turned local normal file f into a largefile use (l)argefile or keep (n)ormal file? l + getting changed largefiles + 1 largefiles updated, 0 removed 2 files updated, 0 files merged, 1 files removed, 0 files unresolved (branch merge, don't forget to commit) - getting changed largefiles - 1 largefiles updated, 0 removed $ cat f large2
--- a/tests/test-known.t Sat Aug 30 15:13:02 2014 +0200 +++ b/tests/test-known.t Sat Aug 30 18:44:59 2014 +0200 @@ -1,4 +1,4 @@ - $ "$TESTDIR/hghave" killdaemons || exit 80 +#require killdaemons = Test the known() protocol function =
--- a/tests/test-largefiles-misc.t Sat Aug 30 15:13:02 2014 +0200 +++ b/tests/test-largefiles-misc.t Sat Aug 30 18:44:59 2014 +0200 @@ -659,10 +659,10 @@ R d1/f $ hg merge merging d2/f and d1/f to d2/f + getting changed largefiles + 0 largefiles updated, 0 removed 1 files updated, 1 files merged, 0 files removed, 0 files unresolved (branch merge, don't forget to commit) - getting changed largefiles - 0 largefiles updated, 0 removed $ cd .. @@ -725,10 +725,10 @@ ancestor was 09d2af8dd22201dd8d48e5dcfcaed281ff9422c7 keep (l)ocal e5fa44f2b31c1fb553b6021e7360d07d5d91ff5e or take (o)ther 7448d8798a4380162d4b56f9b452e2f6f9e24e7a? l + getting changed largefiles + 1 largefiles updated, 0 removed 0 files updated, 4 files merged, 0 files removed, 0 files unresolved (branch merge, don't forget to commit) - getting changed largefiles - 1 largefiles updated, 0 removed $ cat f-different 1 $ cat f-same
--- a/tests/test-largefiles-update.t Sat Aug 30 15:13:02 2014 +0200 +++ b/tests/test-largefiles-update.t Sat Aug 30 18:44:59 2014 +0200 @@ -36,10 +36,10 @@ $ cat .hglf/large1 4669e532d5b2c093a78eca010077e708a071bb64 $ hg merge --config debug.dirstate.delaywrite=2 + getting changed largefiles + 1 largefiles updated, 0 removed 2 files updated, 0 files merged, 0 files removed, 0 files unresolved (branch merge, don't forget to commit) - getting changed largefiles - 1 largefiles updated, 0 removed $ hg status -A large1 M large1 $ cat large1 @@ -67,10 +67,10 @@ take (o)ther 58e24f733a964da346e2407a2bee99d9001184f5? merging normal1 warning: conflicts during merge. merging normal1 incomplete! (edit conflicts, then use 'hg resolve --mark') + getting changed largefiles + 1 largefiles updated, 0 removed 0 files updated, 1 files merged, 0 files removed, 1 files unresolved use 'hg resolve' to retry unresolved file merges or 'hg update -C .' to abandon - getting changed largefiles - 1 largefiles updated, 0 removed [1] $ hg status -A large1 M large1 @@ -99,4 +99,421 @@ $ cat .hglf/large1 58e24f733a964da346e2407a2bee99d9001184f5 +Test that "hg rollback" restores status of largefiles correctly + + $ hg update -C -q + $ hg remove large1 + $ test -f .hglf/large1 + [1] + $ hg forget large2 + $ test -f .hglf/large2 + [1] + $ echo largeX > largeX + $ hg add --large largeX + $ cat .hglf/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 + $ test -f .hglf/large1 + [1] + $ hg status -A large2 + R large2 + $ test -f .hglf/large2 + [1] + $ hg status -A largeX + A largeX + $ cat .hglf/largeX + + $ hg status -A largeY + ? largeY + $ test -f .hglf/largeY + [1] + +Test that "hg rollback" restores standins correctly + + $ hg commit -m 'will be rollback-ed soon' + $ hg update -q -C 2 + $ cat large1 + large1 + $ cat .hglf/large1 + 4669e532d5b2c093a78eca010077e708a071bb64 + $ cat large2 + large2 in #2 + $ cat .hglf/large2 + 3cfce6277e7668985707b6887ce56f9f62f6ccd9 + + $ hg rollback -q -f + $ cat large1 + large1 + $ cat .hglf/large1 + 4669e532d5b2c093a78eca010077e708a071bb64 + $ cat large2 + large2 in #2 + $ cat .hglf/large2 + 3cfce6277e7668985707b6887ce56f9f62f6ccd9 + +(rollback the parent of the working directory, when the parent of it +is not branch-tip) + + $ hg update -q -C 1 + $ cat .hglf/large1 + 58e24f733a964da346e2407a2bee99d9001184f5 + $ cat .hglf/large2 + 1deebade43c8c498a3c8daddac0244dc55d1331d + + $ echo normalX > normalX + $ hg add normalX + $ hg commit -m 'will be rollback-ed soon' + $ hg rollback -q + + $ cat .hglf/large1 + 58e24f733a964da346e2407a2bee99d9001184f5 + $ cat .hglf/large2 + 1deebade43c8c498a3c8daddac0244dc55d1331d + +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 + +Test that linear merge can detect modification (and conflict) correctly + +(linear merge without conflict) + + $ echo 'large2 for linear merge (no conflict)' > large2 + $ hg update 3 --config debug.dirstate.delaywrite=2 + getting changed largefiles + 1 largefiles updated, 0 removed + 2 files updated, 0 files merged, 0 files removed, 0 files unresolved + $ hg status -A large2 + M large2 + $ cat large2 + large2 for linear merge (no conflict) + $ cat .hglf/large2 + 9c4bf8f1b33536d6e5f89447e10620cfe52ea710 + +(linear merge with conflict, choosing "other") + + $ hg update -q -C 2 + $ echo 'large1 for linear merge (conflict)' > large1 + $ hg update 3 --config ui.interactive=True <<EOF + > o + > EOF + largefile large1 has a merge conflict + ancestor was 4669e532d5b2c093a78eca010077e708a071bb64 + keep (l)ocal ba94c2efe5b7c5e0af8d189295ce00553b0612b7 or + take (o)ther e5bb990443d6a92aaf7223813720f7566c9dd05b? getting changed largefiles + 1 largefiles updated, 0 removed + 1 files updated, 1 files merged, 0 files removed, 0 files unresolved + $ hg status -A large1 + C large1 + $ cat large1 + large1 in #3 + $ cat .hglf/large1 + e5bb990443d6a92aaf7223813720f7566c9dd05b + +(linear merge with conflict, choosing "local") + + $ hg update -q -C 2 + $ echo 'large1 for linear merge (conflict)' > large1 + $ hg update 3 --config debug.dirstate.delaywrite=2 + largefile large1 has a merge conflict + ancestor was 4669e532d5b2c093a78eca010077e708a071bb64 + keep (l)ocal ba94c2efe5b7c5e0af8d189295ce00553b0612b7 or + take (o)ther e5bb990443d6a92aaf7223813720f7566c9dd05b? l + 1 files updated, 1 files merged, 0 files removed, 0 files unresolved + $ hg status -A large1 + M large1 + $ cat large1 + large1 for linear merge (conflict) + $ cat .hglf/large1 + ba94c2efe5b7c5e0af8d189295ce00553b0612b7 + +Test a linear merge to a revision containing same-name normal file + + $ hg update -q -C 3 + $ hg remove large2 + $ echo 'large2 as normal file' > large2 + $ hg add large2 + $ echo 'large3 as normal file' > large3 + $ hg add large3 + $ hg commit -m '#5' + $ hg manifest + .hglf/large1 + large2 + large3 + normal1 + +(modified largefile is already switched to normal) + + $ hg update -q -C 2 + $ echo 'modified large2 for linear merge' > large2 + $ hg update -q 5 + local changed .hglf/large2 which remote deleted + use (c)hanged version or (d)elete? c + remote turned local largefile large2 into a normal file + keep (l)argefile or use (n)ormal file? l + $ hg debugdirstate --nodates | grep large2 + a 0 -1 .hglf/large2 + r 0 0 large2 + $ hg status -A large2 + A large2 + $ cat large2 + modified large2 for linear merge + +(added largefile is already committed as normal) + + $ hg update -q -C 2 + $ echo 'large3 as large file for linear merge' > large3 + $ hg add --large large3 + $ hg update -q 5 + remote turned local largefile large3 into a normal file + keep (l)argefile or use (n)ormal file? l + $ hg debugdirstate --nodates | grep large3 + a 0 -1 .hglf/large3 + r 0 0 large3 + $ hg status -A large3 + A large3 + $ cat large3 + large3 as large file for linear merge + $ rm -f large3 .hglf/large3 + +Test that the internal linear merging works correctly +(both heads are stripped to keep pairing of revision number and commit log) + + $ hg update -q -C 2 + $ hg strip 3 4 + saved backup bundle to $TESTTMP/repo/.hg/strip-backup/9530e27857f7-backup.hg (glob) + $ mv .hg/strip-backup/9530e27857f7-backup.hg $TESTTMP + +(internal linear merging at "hg pull --update") + + $ echo 'large1 for linear merge (conflict)' > large1 + $ echo 'large2 for linear merge (conflict with normal file)' > large2 + $ hg pull --update --config debug.dirstate.delaywrite=2 $TESTTMP/9530e27857f7-backup.hg + pulling from $TESTTMP/9530e27857f7-backup.hg (glob) + searching for changes + adding changesets + adding manifests + adding file changes + added 3 changesets with 5 changes to 5 files + local changed .hglf/large2 which remote deleted + use (c)hanged version or (d)elete? c + remote turned local largefile large2 into a normal file + keep (l)argefile or use (n)ormal file? l + largefile large1 has a merge conflict + ancestor was 4669e532d5b2c093a78eca010077e708a071bb64 + keep (l)ocal ba94c2efe5b7c5e0af8d189295ce00553b0612b7 or + take (o)ther e5bb990443d6a92aaf7223813720f7566c9dd05b? l + 2 files updated, 1 files merged, 0 files removed, 0 files unresolved + + $ hg status -A large1 + M large1 + $ cat large1 + large1 for linear merge (conflict) + $ cat .hglf/large1 + ba94c2efe5b7c5e0af8d189295ce00553b0612b7 + $ hg status -A large2 + A large2 + $ cat large2 + large2 for linear merge (conflict with normal file) + $ cat .hglf/large2 + d7591fe9be0f6227d90bddf3e4f52ff41fc1f544 + +(internal linear merging at "hg unbundle --update") + + $ hg update -q -C 2 + $ hg rollback -q + + $ echo 'large1 for linear merge (conflict)' > large1 + $ echo 'large2 for linear merge (conflict with normal file)' > large2 + $ hg unbundle --update --config debug.dirstate.delaywrite=2 $TESTTMP/9530e27857f7-backup.hg + adding changesets + adding manifests + adding file changes + added 3 changesets with 5 changes to 5 files + local changed .hglf/large2 which remote deleted + use (c)hanged version or (d)elete? c + remote turned local largefile large2 into a normal file + keep (l)argefile or use (n)ormal file? l + largefile large1 has a merge conflict + ancestor was 4669e532d5b2c093a78eca010077e708a071bb64 + keep (l)ocal ba94c2efe5b7c5e0af8d189295ce00553b0612b7 or + take (o)ther e5bb990443d6a92aaf7223813720f7566c9dd05b? l + 2 files updated, 1 files merged, 0 files removed, 0 files unresolved + + $ hg status -A large1 + M large1 + $ cat large1 + large1 for linear merge (conflict) + $ cat .hglf/large1 + ba94c2efe5b7c5e0af8d189295ce00553b0612b7 + $ hg status -A large2 + A large2 + $ cat large2 + large2 for linear merge (conflict with normal file) + $ cat .hglf/large2 + d7591fe9be0f6227d90bddf3e4f52ff41fc1f544 + +(internal linear merging in subrepo at "hg update") + $ cd .. + $ hg init subparent + $ cd subparent + + $ hg clone -q -u 2 ../repo sub + $ cat > .hgsub <<EOF + > sub = sub + > EOF + $ hg add .hgsub + $ hg commit -m '#0@parent' + $ cat .hgsubstate + f74e50bd9e5594b7cf1e6c5cbab86ddd25f3ca2f sub + $ hg -R sub update -q + $ hg commit -m '#1@parent' + $ cat .hgsubstate + d65e59e952a9638e2ce863b41a420ca723dd3e8d sub + $ hg update -q 0 + + $ echo 'large1 for linear merge (conflict)' > sub/large1 + $ echo 'large2 for linear merge (conflict with normal file)' > sub/large2 + $ hg update --config ui.interactive=True --config debug.dirstate.delaywrite=2 <<EOF + > m + > r + > c + > l + > l + > EOF + subrepository sub diverged (local revision: f74e50bd9e55, remote revision: d65e59e952a9) + (M)erge, keep (l)ocal or keep (r)emote? subrepository sources for sub differ (in checked out version) + use (l)ocal source (f74e50bd9e55) or (r)emote source (d65e59e952a9)? + local changed .hglf/large2 which remote deleted + use (c)hanged version or (d)elete? remote turned local largefile large2 into a normal file + keep (l)argefile or use (n)ormal file? largefile large1 has a merge conflict + ancestor was 4669e532d5b2c093a78eca010077e708a071bb64 + keep (l)ocal ba94c2efe5b7c5e0af8d189295ce00553b0612b7 or + take (o)ther e5bb990443d6a92aaf7223813720f7566c9dd05b? 2 files updated, 1 files merged, 0 files removed, 0 files unresolved + 0 files updated, 0 files merged, 0 files removed, 0 files unresolved + + $ hg -R sub status -A sub/large1 + M sub/large1 + $ cat sub/large1 + large1 for linear merge (conflict) + $ cat sub/.hglf/large1 + ba94c2efe5b7c5e0af8d189295ce00553b0612b7 + $ hg -R sub status -A sub/large2 + A sub/large2 + $ cat sub/large2 + large2 for linear merge (conflict with normal file) + $ cat sub/.hglf/large2 + d7591fe9be0f6227d90bddf3e4f52ff41fc1f544 + + $ cd .. + $ cd repo + +Test that rebase updates largefiles in the working directory even if +it is aborted by conflict. + + $ hg update -q -C 3 + $ cat .hglf/large1 + e5bb990443d6a92aaf7223813720f7566c9dd05b + $ cat large1 + large1 in #3 + $ hg rebase -s 1 -d 3 --keep --config ui.interactive=True <<EOF + > o + > EOF + largefile large1 has a merge conflict + ancestor was 4669e532d5b2c093a78eca010077e708a071bb64 + keep (l)ocal e5bb990443d6a92aaf7223813720f7566c9dd05b or + take (o)ther 58e24f733a964da346e2407a2bee99d9001184f5? merging normal1 + warning: conflicts during merge. + merging normal1 incomplete! (edit conflicts, then use 'hg resolve --mark') + unresolved conflicts (see hg resolve, then hg rebase --continue) + [1] + $ cat .hglf/large1 + 58e24f733a964da346e2407a2bee99d9001184f5 + $ cat large1 + large1 in #1 + + $ hg rebase -q --abort + rebase aborted + +Test that transplant updates largefiles, of which standins are safely +changed, even if it is aborted by conflict of other. + + $ hg update -q -C 5 + $ cat .hglf/large1 + e5bb990443d6a92aaf7223813720f7566c9dd05b + $ cat large1 + large1 in #3 + $ hg diff -c 4 .hglf/largeX | grep '^[+-][0-9a-z]' + +fa44618ea25181aff4f48b70428294790cec9f61 + $ hg transplant 4 + applying 07d6153b5c04 + patching file .hglf/large1 + Hunk #1 FAILED at 0 + 1 out of 1 hunks FAILED -- saving rejects to file .hglf/large1.rej + patch failed to apply + abort: fix up the merge and run hg transplant --continue + [255] + $ hg status -A large1 + C large1 + $ cat .hglf/large1 + e5bb990443d6a92aaf7223813720f7566c9dd05b + $ cat large1 + large1 in #3 + $ hg status -A largeX + A largeX + $ cat .hglf/largeX + fa44618ea25181aff4f48b70428294790cec9f61 + $ cat largeX + largeX + + $ cd ..
--- a/tests/test-largefiles.t Sat Aug 30 15:13:02 2014 +0200 +++ b/tests/test-largefiles.t Sat Aug 30 18:44:59 2014 +0200 @@ -598,7 +598,7 @@ C sub2/large6 C sub2/large7 -Test commit -A (issue 3542) +Test commit -A (issue3542) $ echo large8 > large8 $ hg add --large large8 $ hg ci -Am 'this used to add large8 as normal and commit both' @@ -1496,7 +1496,6 @@ $ cat sub2/large6 large6 $ hg revert --no-backup -C -r '.^' sub2 - reverting .hglf/sub2/large6 (glob) $ hg revert --no-backup sub2 reverting .hglf/sub2/large6 (glob) $ hg status @@ -1604,11 +1603,11 @@ A f created new head $ hg merge -r 6 - 4 files updated, 0 files merged, 0 files removed, 0 files unresolved - (branch merge, don't forget to commit) getting changed largefiles large3: largefile 7838695e10da2bb75ac1156565f40a2595fa2fa0 not available from file:/*/$TESTTMP/d (glob) 1 largefiles updated, 0 removed + 4 files updated, 0 files merged, 0 files removed, 0 files unresolved + (branch merge, don't forget to commit) $ hg rollback -q $ hg up -Cq @@ -1662,10 +1661,10 @@ ancestor was 971fb41e78fea4f8e0ba5244784239371cb00591 keep (l)ocal d846f26643bfa8ec210be40cc93cc6b7ff1128ea or take (o)ther e166e74c7303192238d60af5a9c4ce9bef0b7928? l + getting changed largefiles + 1 largefiles updated, 0 removed 3 files updated, 1 files merged, 0 files removed, 0 files unresolved (branch merge, don't forget to commit) - getting changed largefiles - 1 largefiles updated, 0 removed $ hg commit -m "Merge repos e and f" Invoking status precommit hook M normal3 @@ -1696,10 +1695,10 @@ M normal3 created new head $ hg merge + getting changed largefiles + 1 largefiles updated, 0 removed 1 files updated, 0 files merged, 0 files removed, 0 files unresolved (branch merge, don't forget to commit) - getting changed largefiles - 1 largefiles updated, 0 removed $ hg status M large @@ -1743,7 +1742,7 @@ adding file changes added 1 changesets with 2 changes to 2 files getting changed largefiles - 1 largefiles updated, 0 removed + 0 largefiles updated, 0 removed $ hg log --template '{rev}:{node|short} {desc|firstline}\n' 9:598410d3eb9a modify normal file largefile in repo d 8:a381d2c8c80e modify normal file and largefile in repo b
--- a/tests/test-lock-badness.t Sat Aug 30 15:13:02 2014 +0200 +++ b/tests/test-lock-badness.t Sat Aug 30 18:44:59 2014 +0200 @@ -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 Sat Aug 30 15:13:02 2014 +0200 +++ b/tests/test-log.t Sat Aug 30 18:44:59 2014 +0200 @@ -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 Sat Aug 30 15:13:02 2014 +0200 +++ b/tests/test-merge-tools.t Sat Aug 30 18:44:59 2014 +0200 @@ -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 Sat Aug 30 15:13:02 2014 +0200 +++ b/tests/test-merge-types.t Sat Aug 30 18:44:59 2014 +0200 @@ -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 Sat Aug 30 15:13:02 2014 +0200 +++ b/tests/test-mq-qclone-http.t Sat Aug 30 18:44:59 2014 +0200 @@ -1,4 +1,4 @@ - $ "$TESTDIR/hghave" killdaemons || exit 80 +#require killdaemons hide outer repo $ hg init
--- a/tests/test-mq-qimport.t Sat Aug 30 15:13:02 2014 +0200 +++ b/tests/test-mq-qimport.t Sat Aug 30 18:44:59 2014 +0200 @@ -1,4 +1,4 @@ - $ "$TESTDIR/hghave" killdaemons || exit 80 +#require killdaemons $ cat > writelines.py <<EOF > import sys
--- a/tests/test-mq-qrefresh-interactive.t Sat Aug 30 15:13:02 2014 +0200 +++ b/tests/test-mq-qrefresh-interactive.t Sat Aug 30 18:44:59 2014 +0200 @@ -29,7 +29,7 @@ Returns 0 on success. - options: + options ([+] can be repeated): -e --edit invoke editor on commit messages -g --git use git extended diff format @@ -44,9 +44,7 @@ -m --message TEXT use text as commit message -l --logfile FILE read commit message from file - [+] marked option can be specified multiple times - - use "hg -v help qrefresh" to show the global options + (some details hidden, use --verbose to show complete help) help qrefresh (record) @@ -73,7 +71,7 @@ Returns 0 on success. - options: + options ([+] can be repeated): -e --edit invoke editor on commit messages -g --git use git extended diff format @@ -89,9 +87,7 @@ -l --logfile FILE read commit message from file -i --interactive interactively select changes to refresh - [+] marked option can be specified multiple times - - use "hg -v help qrefresh" to show the global options + (some details hidden, use --verbose to show complete help) $ hg init a $ cd a
--- a/tests/test-mq-qrefresh-replace-log-message.t Sat Aug 30 15:13:02 2014 +0200 +++ b/tests/test-mq-qrefresh-replace-log-message.t Sat Aug 30 18:44:59 2014 +0200 @@ -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 Sat Aug 30 15:13:02 2014 +0200 +++ b/tests/test-mq-subrepo-svn.t Sat Aug 30 18:44:59 2014 +0200 @@ -1,4 +1,4 @@ - $ "$TESTDIR/hghave" svn13 || exit 80 +#require svn13 $ echo "[extensions]" >> $HGRCPATH $ echo "mq=" >> $HGRCPATH
--- a/tests/test-mq-symlinks.t Sat Aug 30 15:13:02 2014 +0200 +++ b/tests/test-mq-symlinks.t Sat Aug 30 18:44:59 2014 +0200 @@ -1,4 +1,4 @@ - $ "$TESTDIR/hghave" symlink || exit 80 +#require symlink $ echo "[extensions]" >> $HGRCPATH $ echo "mq=" >> $HGRCPATH
--- a/tests/test-mq.t Sat Aug 30 15:13:02 2014 +0200 +++ b/tests/test-mq.t Sat Aug 30 18:44:59 2014 +0200 @@ -95,7 +95,7 @@ qtop print the name of the current patch qunapplied print the patches not yet applied - use "hg -v help mq" to show builtin aliases and global options + (use "hg help -v mq" to show built-in aliases and global options) $ hg init a $ cd a
--- a/tests/test-newcgi.t Sat Aug 30 15:13:02 2014 +0200 +++ b/tests/test-newcgi.t Sat Aug 30 18:44:59 2014 +0200 @@ -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 Sat Aug 30 15:13:02 2014 +0200 +++ b/tests/test-newercgi.t Sat Aug 30 18:44:59 2014 +0200 @@ -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 Sat Aug 30 15:13:02 2014 +0200 +++ b/tests/test-no-symlinks.t Sat Aug 30 18:44:59 2014 +0200 @@ -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 Sat Aug 30 15:13:02 2014 +0200 +++ b/tests/test-obsolete.t Sat Aug 30 18:44:59 2014 +0200 @@ -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" @@ -52,17 +54,13 @@ [255] $ hg debugobsolete -d '0 0' `getid kill_me` -u babar $ hg debugobsolete - 97b7c2d76b1845ed3eb988cd612611e72406cef0 0 {'date': '0 0', 'user': 'babar'} + 97b7c2d76b1845ed3eb988cd612611e72406cef0 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'babar'} (test that mercurial is not confused) $ 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 Killing a single changeset with itself should fail @@ -90,13 +88,13 @@ $ hg log -r 'hidden()' --template '{rev}:{node|short} {desc}\n' --hidden 2:245bde4270cd add original_c $ hg debugrevlog -cd - # rev p1rev p2rev start end deltastart base p1 p2 rawsize totalsize compression heads - 0 -1 -1 0 59 0 0 0 0 58 58 0 1 - 1 0 -1 59 118 59 59 0 0 58 116 0 1 - 2 1 -1 118 204 59 59 59 0 76 192 0 1 - 3 1 -1 204 271 204 204 59 0 66 258 0 2 + # rev p1rev p2rev start end deltastart base p1 p2 rawsize totalsize compression heads chainlen + 0 -1 -1 0 59 0 0 0 0 58 58 0 1 0 + 1 0 -1 59 118 59 59 0 0 58 116 0 1 0 + 2 1 -1 118 204 59 59 59 0 76 192 0 1 1 + 3 1 -1 204 271 204 204 59 0 66 258 0 2 0 $ hg debugobsolete - 245bde4270cd1072a27757984f9cda8ba26f08ca cdbce2fbb16313928851e97e0d85413f3f7eb77f C {'date': '56 12', 'user': 'test'} + 245bde4270cd1072a27757984f9cda8ba26f08ca cdbce2fbb16313928851e97e0d85413f3f7eb77f C (Thu Jan 01 00:00:44 1970 -0000) {'user': 'test'} do it again (it read the obsstore before adding new changeset) @@ -106,8 +104,8 @@ created new head $ hg debugobsolete -d '1337 0' `getid new_c` `getid new_2_c` $ hg debugobsolete - 245bde4270cd1072a27757984f9cda8ba26f08ca cdbce2fbb16313928851e97e0d85413f3f7eb77f C {'date': '56 12', 'user': 'test'} - cdbce2fbb16313928851e97e0d85413f3f7eb77f ca819180edb99ed25ceafb3e9584ac287e240b00 0 {'date': '1337 0', 'user': 'test'} + 245bde4270cd1072a27757984f9cda8ba26f08ca cdbce2fbb16313928851e97e0d85413f3f7eb77f C (Thu Jan 01 00:00:44 1970 -0000) {'user': 'test'} + cdbce2fbb16313928851e97e0d85413f3f7eb77f ca819180edb99ed25ceafb3e9584ac287e240b00 0 (Thu Jan 01 00:22:17 1970 +0000) {'user': 'test'} Register two markers with a missing node @@ -118,10 +116,10 @@ $ hg debugobsolete -d '1338 0' `getid new_2_c` 1337133713371337133713371337133713371337 $ hg debugobsolete -d '1339 0' 1337133713371337133713371337133713371337 `getid new_3_c` $ hg debugobsolete - 245bde4270cd1072a27757984f9cda8ba26f08ca cdbce2fbb16313928851e97e0d85413f3f7eb77f C {'date': '56 12', 'user': 'test'} - cdbce2fbb16313928851e97e0d85413f3f7eb77f ca819180edb99ed25ceafb3e9584ac287e240b00 0 {'date': '1337 0', 'user': 'test'} - ca819180edb99ed25ceafb3e9584ac287e240b00 1337133713371337133713371337133713371337 0 {'date': '1338 0', 'user': 'test'} - 1337133713371337133713371337133713371337 5601fb93a350734d935195fee37f4054c529ff39 0 {'date': '1339 0', 'user': 'test'} + 245bde4270cd1072a27757984f9cda8ba26f08ca cdbce2fbb16313928851e97e0d85413f3f7eb77f C (Thu Jan 01 00:00:44 1970 -0000) {'user': 'test'} + cdbce2fbb16313928851e97e0d85413f3f7eb77f ca819180edb99ed25ceafb3e9584ac287e240b00 0 (Thu Jan 01 00:22:17 1970 +0000) {'user': 'test'} + ca819180edb99ed25ceafb3e9584ac287e240b00 1337133713371337133713371337133713371337 0 (Thu Jan 01 00:22:18 1970 +0000) {'user': 'test'} + 1337133713371337133713371337133713371337 5601fb93a350734d935195fee37f4054c529ff39 0 (Thu Jan 01 00:22:19 1970 +0000) {'user': 'test'} Refuse pathological nullid successors $ hg debugobsolete -d '9001 0' 1337133713371337133713371337133713371337 0000000000000000000000000000000000000000 @@ -133,59 +131,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 @@ -212,13 +173,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] @@ -230,27 +185,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 @@ -261,13 +202,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 @@ -297,27 +232,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 @@ -336,28 +257,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) @@ -371,32 +274,32 @@ added 4 changesets with 4 changes to 4 files (+1 heads) (run 'hg heads' to see heads, 'hg merge' to merge) $ hg debugobsolete - 245bde4270cd1072a27757984f9cda8ba26f08ca cdbce2fbb16313928851e97e0d85413f3f7eb77f C {'date': '56 12', 'user': 'test'} - cdbce2fbb16313928851e97e0d85413f3f7eb77f ca819180edb99ed25ceafb3e9584ac287e240b00 0 {'date': '1337 0', 'user': 'test'} - ca819180edb99ed25ceafb3e9584ac287e240b00 1337133713371337133713371337133713371337 0 {'date': '1338 0', 'user': 'test'} - 1337133713371337133713371337133713371337 5601fb93a350734d935195fee37f4054c529ff39 0 {'date': '1339 0', 'user': 'test'} - 5601fb93a350734d935195fee37f4054c529ff39 6f96419950729f3671185b847352890f074f7557 1 {'date': '1338 0', 'user': 'test'} + 245bde4270cd1072a27757984f9cda8ba26f08ca cdbce2fbb16313928851e97e0d85413f3f7eb77f C (Thu Jan 01 00:00:44 1970 -0000) {'user': 'test'} + cdbce2fbb16313928851e97e0d85413f3f7eb77f ca819180edb99ed25ceafb3e9584ac287e240b00 0 (Thu Jan 01 00:22:17 1970 +0000) {'user': 'test'} + ca819180edb99ed25ceafb3e9584ac287e240b00 1337133713371337133713371337133713371337 0 (Thu Jan 01 00:22:18 1970 +0000) {'user': 'test'} + 1337133713371337133713371337133713371337 5601fb93a350734d935195fee37f4054c529ff39 0 (Thu Jan 01 00:22:19 1970 +0000) {'user': 'test'} + 5601fb93a350734d935195fee37f4054c529ff39 6f96419950729f3671185b847352890f074f7557 1 (Thu Jan 01 00:22:18 1970 +0000) {'user': 'test'} Rollback//Transaction support $ hg debugobsolete -d '1340 0' aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb $ hg debugobsolete - 245bde4270cd1072a27757984f9cda8ba26f08ca cdbce2fbb16313928851e97e0d85413f3f7eb77f C {'date': '56 12', 'user': 'test'} - cdbce2fbb16313928851e97e0d85413f3f7eb77f ca819180edb99ed25ceafb3e9584ac287e240b00 0 {'date': '1337 0', 'user': 'test'} - ca819180edb99ed25ceafb3e9584ac287e240b00 1337133713371337133713371337133713371337 0 {'date': '1338 0', 'user': 'test'} - 1337133713371337133713371337133713371337 5601fb93a350734d935195fee37f4054c529ff39 0 {'date': '1339 0', 'user': 'test'} - 5601fb93a350734d935195fee37f4054c529ff39 6f96419950729f3671185b847352890f074f7557 1 {'date': '1338 0', 'user': 'test'} - aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb 0 {'date': '1340 0', 'user': 'test'} + 245bde4270cd1072a27757984f9cda8ba26f08ca cdbce2fbb16313928851e97e0d85413f3f7eb77f C (Thu Jan 01 00:00:44 1970 -0000) {'user': 'test'} + cdbce2fbb16313928851e97e0d85413f3f7eb77f ca819180edb99ed25ceafb3e9584ac287e240b00 0 (Thu Jan 01 00:22:17 1970 +0000) {'user': 'test'} + ca819180edb99ed25ceafb3e9584ac287e240b00 1337133713371337133713371337133713371337 0 (Thu Jan 01 00:22:18 1970 +0000) {'user': 'test'} + 1337133713371337133713371337133713371337 5601fb93a350734d935195fee37f4054c529ff39 0 (Thu Jan 01 00:22:19 1970 +0000) {'user': 'test'} + 5601fb93a350734d935195fee37f4054c529ff39 6f96419950729f3671185b847352890f074f7557 1 (Thu Jan 01 00:22:18 1970 +0000) {'user': 'test'} + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb 0 (Thu Jan 01 00:22:20 1970 +0000) {'user': 'test'} $ hg rollback -n repository tip rolled back to revision 3 (undo debugobsolete) $ hg rollback repository tip rolled back to revision 3 (undo debugobsolete) $ hg debugobsolete - 245bde4270cd1072a27757984f9cda8ba26f08ca cdbce2fbb16313928851e97e0d85413f3f7eb77f C {'date': '56 12', 'user': 'test'} - cdbce2fbb16313928851e97e0d85413f3f7eb77f ca819180edb99ed25ceafb3e9584ac287e240b00 0 {'date': '1337 0', 'user': 'test'} - ca819180edb99ed25ceafb3e9584ac287e240b00 1337133713371337133713371337133713371337 0 {'date': '1338 0', 'user': 'test'} - 1337133713371337133713371337133713371337 5601fb93a350734d935195fee37f4054c529ff39 0 {'date': '1339 0', 'user': 'test'} - 5601fb93a350734d935195fee37f4054c529ff39 6f96419950729f3671185b847352890f074f7557 1 {'date': '1338 0', 'user': 'test'} + 245bde4270cd1072a27757984f9cda8ba26f08ca cdbce2fbb16313928851e97e0d85413f3f7eb77f C (Thu Jan 01 00:00:44 1970 -0000) {'user': 'test'} + cdbce2fbb16313928851e97e0d85413f3f7eb77f ca819180edb99ed25ceafb3e9584ac287e240b00 0 (Thu Jan 01 00:22:17 1970 +0000) {'user': 'test'} + ca819180edb99ed25ceafb3e9584ac287e240b00 1337133713371337133713371337133713371337 0 (Thu Jan 01 00:22:18 1970 +0000) {'user': 'test'} + 1337133713371337133713371337133713371337 5601fb93a350734d935195fee37f4054c529ff39 0 (Thu Jan 01 00:22:19 1970 +0000) {'user': 'test'} + 5601fb93a350734d935195fee37f4054c529ff39 6f96419950729f3671185b847352890f074f7557 1 (Thu Jan 01 00:22:18 1970 +0000) {'user': 'test'} $ cd .. @@ -411,20 +314,21 @@ adding file changes added 4 changesets with 4 changes to 4 files (+1 heads) $ hg -R tmpd debugobsolete - 245bde4270cd1072a27757984f9cda8ba26f08ca cdbce2fbb16313928851e97e0d85413f3f7eb77f C {'date': '56 12', 'user': 'test'} - cdbce2fbb16313928851e97e0d85413f3f7eb77f ca819180edb99ed25ceafb3e9584ac287e240b00 0 {'date': '1337 0', 'user': 'test'} - ca819180edb99ed25ceafb3e9584ac287e240b00 1337133713371337133713371337133713371337 0 {'date': '1338 0', 'user': 'test'} - 1337133713371337133713371337133713371337 5601fb93a350734d935195fee37f4054c529ff39 0 {'date': '1339 0', 'user': 'test'} - 5601fb93a350734d935195fee37f4054c529ff39 6f96419950729f3671185b847352890f074f7557 1 {'date': '1338 0', 'user': 'test'} + 245bde4270cd1072a27757984f9cda8ba26f08ca cdbce2fbb16313928851e97e0d85413f3f7eb77f C (Thu Jan 01 00:00:44 1970 -0000) {'user': 'test'} + cdbce2fbb16313928851e97e0d85413f3f7eb77f ca819180edb99ed25ceafb3e9584ac287e240b00 0 (Thu Jan 01 00:22:17 1970 +0000) {'user': 'test'} + ca819180edb99ed25ceafb3e9584ac287e240b00 1337133713371337133713371337133713371337 0 (Thu Jan 01 00:22:18 1970 +0000) {'user': 'test'} + 1337133713371337133713371337133713371337 5601fb93a350734d935195fee37f4054c529ff39 0 (Thu Jan 01 00:22:19 1970 +0000) {'user': 'test'} + 5601fb93a350734d935195fee37f4054c529ff39 6f96419950729f3671185b847352890f074f7557 1 (Thu Jan 01 00:22:18 1970 +0000) {'user': 'test'} Check obsolete keys are exchanged only if source has an obsolete store $ hg init empty $ hg --config extensions.debugkeys=debugkeys.py -R empty push tmpd pushing to tmpd + listkeys phases + listkeys bookmarks no changes found listkeys phases - listkeys bookmarks [1] clone support @@ -434,52 +338,26 @@ 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'} - cdbce2fbb16313928851e97e0d85413f3f7eb77f ca819180edb99ed25ceafb3e9584ac287e240b00 0 {'date': '1337 0', 'user': 'test'} - ca819180edb99ed25ceafb3e9584ac287e240b00 1337133713371337133713371337133713371337 0 {'date': '1338 0', 'user': 'test'} - 1337133713371337133713371337133713371337 5601fb93a350734d935195fee37f4054c529ff39 0 {'date': '1339 0', 'user': 'test'} - 5601fb93a350734d935195fee37f4054c529ff39 6f96419950729f3671185b847352890f074f7557 1 {'date': '1338 0', 'user': 'test'} + 245bde4270cd1072a27757984f9cda8ba26f08ca cdbce2fbb16313928851e97e0d85413f3f7eb77f C (Thu Jan 01 00:00:44 1970 -0000) {'user': 'test'} + cdbce2fbb16313928851e97e0d85413f3f7eb77f ca819180edb99ed25ceafb3e9584ac287e240b00 0 (Thu Jan 01 00:22:17 1970 +0000) {'user': 'test'} + ca819180edb99ed25ceafb3e9584ac287e240b00 1337133713371337133713371337133713371337 0 (Thu Jan 01 00:22:18 1970 +0000) {'user': 'test'} + 1337133713371337133713371337133713371337 5601fb93a350734d935195fee37f4054c529ff39 0 (Thu Jan 01 00:22:19 1970 +0000) {'user': 'test'} + 5601fb93a350734d935195fee37f4054c529ff39 6f96419950729f3671185b847352890f074f7557 1 (Thu Jan 01 00:22:18 1970 +0000) {'user': 'test'} Destination repo have existing data @@ -499,12 +377,12 @@ added 4 changesets with 4 changes to 4 files (+1 heads) (run 'hg heads' to see heads, 'hg merge' to merge) $ hg debugobsolete - 2448244824482448244824482448244824482448 1339133913391339133913391339133913391339 0 {'date': '1339 0', 'user': 'test'} - 245bde4270cd1072a27757984f9cda8ba26f08ca cdbce2fbb16313928851e97e0d85413f3f7eb77f C {'date': '56 12', 'user': 'test'} - cdbce2fbb16313928851e97e0d85413f3f7eb77f ca819180edb99ed25ceafb3e9584ac287e240b00 0 {'date': '1337 0', 'user': 'test'} - ca819180edb99ed25ceafb3e9584ac287e240b00 1337133713371337133713371337133713371337 0 {'date': '1338 0', 'user': 'test'} - 1337133713371337133713371337133713371337 5601fb93a350734d935195fee37f4054c529ff39 0 {'date': '1339 0', 'user': 'test'} - 5601fb93a350734d935195fee37f4054c529ff39 6f96419950729f3671185b847352890f074f7557 1 {'date': '1338 0', 'user': 'test'} + 2448244824482448244824482448244824482448 1339133913391339133913391339133913391339 0 (Thu Jan 01 00:22:19 1970 +0000) {'user': 'test'} + 245bde4270cd1072a27757984f9cda8ba26f08ca cdbce2fbb16313928851e97e0d85413f3f7eb77f C (Thu Jan 01 00:00:44 1970 -0000) {'user': 'test'} + cdbce2fbb16313928851e97e0d85413f3f7eb77f ca819180edb99ed25ceafb3e9584ac287e240b00 0 (Thu Jan 01 00:22:17 1970 +0000) {'user': 'test'} + ca819180edb99ed25ceafb3e9584ac287e240b00 1337133713371337133713371337133713371337 0 (Thu Jan 01 00:22:18 1970 +0000) {'user': 'test'} + 1337133713371337133713371337133713371337 5601fb93a350734d935195fee37f4054c529ff39 0 (Thu Jan 01 00:22:19 1970 +0000) {'user': 'test'} + 5601fb93a350734d935195fee37f4054c529ff39 6f96419950729f3671185b847352890f074f7557 1 (Thu Jan 01 00:22:18 1970 +0000) {'user': 'test'} On push @@ -515,78 +393,45 @@ no changes found [1] $ hg -R ../tmpc debugobsolete - 245bde4270cd1072a27757984f9cda8ba26f08ca cdbce2fbb16313928851e97e0d85413f3f7eb77f C {'date': '56 12', 'user': 'test'} - cdbce2fbb16313928851e97e0d85413f3f7eb77f ca819180edb99ed25ceafb3e9584ac287e240b00 0 {'date': '1337 0', 'user': 'test'} - ca819180edb99ed25ceafb3e9584ac287e240b00 1337133713371337133713371337133713371337 0 {'date': '1338 0', 'user': 'test'} - 1337133713371337133713371337133713371337 5601fb93a350734d935195fee37f4054c529ff39 0 {'date': '1339 0', 'user': 'test'} - 5601fb93a350734d935195fee37f4054c529ff39 6f96419950729f3671185b847352890f074f7557 1 {'date': '1338 0', 'user': 'test'} - 2448244824482448244824482448244824482448 1339133913391339133913391339133913391339 0 {'date': '1339 0', 'user': 'test'} + 245bde4270cd1072a27757984f9cda8ba26f08ca cdbce2fbb16313928851e97e0d85413f3f7eb77f C (Thu Jan 01 00:00:44 1970 -0000) {'user': 'test'} + cdbce2fbb16313928851e97e0d85413f3f7eb77f ca819180edb99ed25ceafb3e9584ac287e240b00 0 (Thu Jan 01 00:22:17 1970 +0000) {'user': 'test'} + ca819180edb99ed25ceafb3e9584ac287e240b00 1337133713371337133713371337133713371337 0 (Thu Jan 01 00:22:18 1970 +0000) {'user': 'test'} + 1337133713371337133713371337133713371337 5601fb93a350734d935195fee37f4054c529ff39 0 (Thu Jan 01 00:22:19 1970 +0000) {'user': 'test'} + 5601fb93a350734d935195fee37f4054c529ff39 6f96419950729f3671185b847352890f074f7557 1 (Thu Jan 01 00:22:18 1970 +0000) {'user': 'test'} + 2448244824482448244824482448244824482448 1339133913391339133913391339133913391339 0 (Thu Jan 01 00:22:19 1970 +0000) {'user': 'test'} detect outgoing obsolete and unstable --------------------------------------- $ 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 $ mkcommit original_d $ mkcommit original_e - $ hg debugobsolete `getid original_d` -d '0 0' + $ hg debugobsolete --record-parents `getid original_d` -d '0 0' + $ hg debugobsolete | grep `getid original_d` + 94b33453f93bdb8d457ef9b770851a618bf413e1 0 {6f96419950729f3671185b847352890f074f7557} (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'} $ 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 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 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 @@ -615,38 +460,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 @@ -666,37 +485,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 @@ -705,13 +504,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 @@ -720,6 +513,72 @@ adding file changes added 1 changesets with 1 changes to 1 files (+1 heads) +test relevance computation +--------------------------------------- + +Checking simple case of "marker relevance". + + +Reminder of the repo situation + + $ hg log --hidden --graph + @ 6:3de5eca88c00 (draft) [tip ] add obsolete_e + | + | x 5:cda648ca50f5 (draft) [ ] add original_e + | | + | x 4:94b33453f93b (draft) [ ] add original_d + |/ + o 3:6f9641995072 (draft) [ ] add n3w_3_c + | + | o 2:245bde4270cd (public) [ ] add original_c + |/ + o 1:7c3bad9141dc (public) [ ] add b + | + o 0:1f0dee641bb7 (public) [ ] add a + + +List of all markers + + $ hg debugobsolete + 2448244824482448244824482448244824482448 1339133913391339133913391339133913391339 0 (Thu Jan 01 00:22:19 1970 +0000) {'user': 'test'} + 245bde4270cd1072a27757984f9cda8ba26f08ca cdbce2fbb16313928851e97e0d85413f3f7eb77f C (Thu Jan 01 00:00:44 1970 -0000) {'user': 'test'} + cdbce2fbb16313928851e97e0d85413f3f7eb77f ca819180edb99ed25ceafb3e9584ac287e240b00 0 (Thu Jan 01 00:22:17 1970 +0000) {'user': 'test'} + ca819180edb99ed25ceafb3e9584ac287e240b00 1337133713371337133713371337133713371337 0 (Thu Jan 01 00:22:18 1970 +0000) {'user': 'test'} + 1337133713371337133713371337133713371337 5601fb93a350734d935195fee37f4054c529ff39 0 (Thu Jan 01 00:22:19 1970 +0000) {'user': 'test'} + 5601fb93a350734d935195fee37f4054c529ff39 6f96419950729f3671185b847352890f074f7557 1 (Thu Jan 01 00:22:18 1970 +0000) {'user': 'test'} + 94b33453f93bdb8d457ef9b770851a618bf413e1 0 {6f96419950729f3671185b847352890f074f7557} (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'} + cda648ca50f50482b7055c0b0c4c117bba6733d9 3de5eca88c00aa039da7399a220f4a5221faa585 0 (*) {'user': 'test'} (glob) + +List of changesets with no chain + + $ hg debugobsolete --hidden --rev ::2 + +List of changesets that are included on marker chain + + $ hg debugobsolete --hidden --rev 6 + cda648ca50f50482b7055c0b0c4c117bba6733d9 3de5eca88c00aa039da7399a220f4a5221faa585 0 (*) {'user': 'test'} (glob) + +List of changesets with a longer chain, (including a pruned children) + + $ hg debugobsolete --hidden --rev 3 + 1337133713371337133713371337133713371337 5601fb93a350734d935195fee37f4054c529ff39 0 (Thu Jan 01 00:22:19 1970 +0000) {'user': 'test'} + 245bde4270cd1072a27757984f9cda8ba26f08ca cdbce2fbb16313928851e97e0d85413f3f7eb77f C (Thu Jan 01 00:00:44 1970 -0000) {'user': 'test'} + 5601fb93a350734d935195fee37f4054c529ff39 6f96419950729f3671185b847352890f074f7557 1 (Thu Jan 01 00:22:18 1970 +0000) {'user': 'test'} + 94b33453f93bdb8d457ef9b770851a618bf413e1 0 {6f96419950729f3671185b847352890f074f7557} (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'} + ca819180edb99ed25ceafb3e9584ac287e240b00 1337133713371337133713371337133713371337 0 (Thu Jan 01 00:22:18 1970 +0000) {'user': 'test'} + cdbce2fbb16313928851e97e0d85413f3f7eb77f ca819180edb99ed25ceafb3e9584ac287e240b00 0 (Thu Jan 01 00:22:17 1970 +0000) {'user': 'test'} + +List of both + + $ hg debugobsolete --hidden --rev 3::6 + 1337133713371337133713371337133713371337 5601fb93a350734d935195fee37f4054c529ff39 0 (Thu Jan 01 00:22:19 1970 +0000) {'user': 'test'} + 245bde4270cd1072a27757984f9cda8ba26f08ca cdbce2fbb16313928851e97e0d85413f3f7eb77f C (Thu Jan 01 00:00:44 1970 -0000) {'user': 'test'} + 5601fb93a350734d935195fee37f4054c529ff39 6f96419950729f3671185b847352890f074f7557 1 (Thu Jan 01 00:22:18 1970 +0000) {'user': 'test'} + 94b33453f93bdb8d457ef9b770851a618bf413e1 0 {6f96419950729f3671185b847352890f074f7557} (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'} + ca819180edb99ed25ceafb3e9584ac287e240b00 1337133713371337133713371337133713371337 0 (Thu Jan 01 00:22:18 1970 +0000) {'user': 'test'} + cda648ca50f50482b7055c0b0c4c117bba6733d9 3de5eca88c00aa039da7399a220f4a5221faa585 0 (*) {'user': 'test'} (glob) + cdbce2fbb16313928851e97e0d85413f3f7eb77f ca819180edb99ed25ceafb3e9584ac287e240b00 0 (Thu Jan 01 00:22:17 1970 +0000) {'user': 'test'} + #if serve check hgweb does not explode @@ -781,13 +640,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 @@ -813,40 +666,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 @@ -861,13 +693,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 @@ -902,18 +728,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 Sat Aug 30 15:13:02 2014 +0200 +++ b/tests/test-oldcgi.t Sat Aug 30 18:44:59 2014 +0200 @@ -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 Sat Aug 30 15:13:02 2014 +0200 +++ b/tests/test-patchbomb.t Sat Aug 30 18:44:59 2014 +0200 @@ -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 Sat Aug 30 15:13:02 2014 +0200 +++ b/tests/test-permissions.t Sat Aug 30 18:44:59 2014 +0200 @@ -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 Sat Aug 30 15:13:02 2014 +0200 +++ b/tests/test-phases-exchange.t Sat Aug 30 18:44:59 2014 +0200 @@ -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 Sat Aug 30 15:13:02 2014 +0200 +++ b/tests/test-pull-http.t Sat Aug 30 18:44:59 2014 +0200 @@ -1,4 +1,4 @@ - $ "$TESTDIR/hghave" killdaemons || exit 80 +#require killdaemons $ hg init test $ cd test
--- a/tests/test-pull-permission.t Sat Aug 30 15:13:02 2014 +0200 +++ b/tests/test-pull-permission.t Sat Aug 30 18:44:59 2014 +0200 @@ -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 Sat Aug 30 15:13:02 2014 +0200 +++ b/tests/test-pull.t Sat Aug 30 18:44:59 2014 +0200 @@ -1,4 +1,4 @@ - $ "$TESTDIR/hghave" serve || exit 80 +#require serve $ hg init test $ cd test
--- a/tests/test-push-cgi.t Sat Aug 30 15:13:02 2014 +0200 +++ b/tests/test-push-cgi.t Sat Aug 30 18:44:59 2014 +0200 @@ -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 Sat Aug 30 15:13:02 2014 +0200 +++ b/tests/test-push-http.t Sat Aug 30 18:44:59 2014 +0200 @@ -1,4 +1,4 @@ - $ "$TESTDIR/hghave" killdaemons || exit 80 +#require killdaemons $ hg init test $ cd test
--- a/tests/test-push-warn.t Sat Aug 30 15:13:02 2014 +0200 +++ b/tests/test-push-warn.t Sat Aug 30 18:44:59 2014 +0200 @@ -35,6 +35,9 @@ searching: 2 queries query 2; still undecided: 1, sample size is: 1 2 total queries + listing keys for "phases" + checking for updated bookmarks + listing keys for "bookmarks" 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-qrecord.t Sat Aug 30 15:13:02 2014 +0200 +++ b/tests/test-qrecord.t Sat Aug 30 18:44:59 2014 +0200 @@ -9,7 +9,7 @@ record extension - commands to interactively select changes for commit/qrefresh - use "hg help extensions" for information on enabling extensions + (use "hg help extensions" for information on enabling extensions) help qrecord (no record) @@ -18,7 +18,7 @@ record commands to interactively select changes for commit/qrefresh - use "hg help extensions" for information on enabling extensions + (use "hg help extensions" for information on enabling extensions) $ echo "[extensions]" >> $HGRCPATH $ echo "record=" >> $HGRCPATH @@ -54,7 +54,7 @@ This command is not available when committing a merge. - options: + options ([+] can be repeated): -A --addremove mark new/missing files as added/removed before committing @@ -74,9 +74,7 @@ -b --ignore-space-change ignore changes in the amount of white space -B --ignore-blank-lines ignore changes whose lines are all blank - [+] marked option can be specified multiple times - - use "hg -v help record" to show the global options + (some details hidden, use --verbose to show complete help) help (no mq, so no qrecord) @@ -87,7 +85,7 @@ See "hg help qnew" & "hg help record" for more information and usage. - use "hg -v help qrecord" to show the global options + (some details hidden, use --verbose to show complete help) $ hg init a @@ -99,7 +97,7 @@ interactively record a new patch - use "hg help qrecord" to show the full help text + (use "hg qrecord -h" to show more help) [255] qrecord patch (mq not present) @@ -119,7 +117,7 @@ See "hg help qnew" & "hg help record" for more information and usage. - use "hg -v help qrecord" to show the global options + (some details hidden, use --verbose to show complete help) help (mq present) @@ -133,7 +131,7 @@ See "hg help qnew" & "hg help record" for more information and usage. - options: + options ([+] can be repeated): -e --edit invoke editor on commit messages -g --git use git extended diff format @@ -150,9 +148,7 @@ -B --ignore-blank-lines ignore changes whose lines are all blank --mq operate on patch repository - [+] marked option can be specified multiple times - - use "hg -v help qrecord" to show the global options + (some details hidden, use --verbose to show complete help) $ cd a
--- a/tests/test-rebase-cache.t Sat Aug 30 15:13:02 2014 +0200 +++ b/tests/test-rebase-cache.t Sat Aug 30 18:44:59 2014 +0200 @@ -470,5 +470,11 @@ o 0 A public - $ hg rebase --dest 7 --source 5 + $ cat > $TESTTMP/checkeditform.sh <<EOF + > env | grep HGEDITFORM + > true + > EOF + $ HGEDITOR="sh $TESTTMP/checkeditform.sh" hg rebase --dest 7 --source 5 -e + HGEDITFORM=rebase.merge + HGEDITFORM=rebase.normal saved backup bundle to $TESTTMP/a3/c4/.hg/strip-backup/*-backup.hg (glob)
--- a/tests/test-rebase-collapse.t Sat Aug 30 15:13:02 2014 +0200 +++ b/tests/test-rebase-collapse.t Sat Aug 30 18:44:59 2014 +0200 @@ -148,7 +148,12 @@ abort: message can only be specified with collapse [255] - $ hg rebase --source 4 --collapse -m 'custom message' + $ cat > $TESTTMP/checkeditform.sh <<EOF + > env | grep HGEDITFORM + > true + > EOF + $ HGEDITOR="sh $TESTTMP/checkeditform.sh" hg rebase --source 4 --collapse -m 'custom message' -e + HGEDITFORM=rebase.collapse saved backup bundle to $TESTTMP/a3/.hg/strip-backup/*-backup.hg (glob) $ hg tglog
--- a/tests/test-rebase-obsolete.t Sat Aug 30 15:13:02 2014 +0200 +++ b/tests/test-rebase-obsolete.t Sat Aug 30 18:44:59 2014 +0200 @@ -101,9 +101,9 @@ o 0:cd010b8cd998 A $ hg debugobsolete - 42ccdea3bb16d28e1848c95fe2e44c000f3f21b1 e4e5be0395b2cbd471ed22a26b1b6a1a0658a794 0 {'date': '*', 'user': 'test'} (glob) - 5fddd98957c8a54a4d436dfe1da9d87f21a1b97b 2327fea05063f39961b14cb69435a9898dc9a245 0 {'date': '*', 'user': 'test'} (glob) - 32af7686d403cf45b5d95f2d70cebea587ac806a 8eeb3c33ad33d452c89e5dcf611c347f978fb42b 0 {'date': '*', 'user': 'test'} (glob) + 42ccdea3bb16d28e1848c95fe2e44c000f3f21b1 e4e5be0395b2cbd471ed22a26b1b6a1a0658a794 0 (*) {'user': 'test'} (glob) + 5fddd98957c8a54a4d436dfe1da9d87f21a1b97b 2327fea05063f39961b14cb69435a9898dc9a245 0 (*) {'user': 'test'} (glob) + 32af7686d403cf45b5d95f2d70cebea587ac806a 8eeb3c33ad33d452c89e5dcf611c347f978fb42b 0 (*) {'user': 'test'} (glob) $ cd .. @@ -166,19 +166,19 @@ o 0:cd010b8cd998 A $ hg debugobsolete - 42ccdea3bb16d28e1848c95fe2e44c000f3f21b1 0 {'date': '*', 'user': 'test'} (glob) - 5fddd98957c8a54a4d436dfe1da9d87f21a1b97b 5ae4c968c6aca831df823664e706c9d4aa34473d 0 {'date': '*', 'user': 'test'} (glob) - 32af7686d403cf45b5d95f2d70cebea587ac806a 0 {'date': '*', 'user': 'test'} (glob) + 42ccdea3bb16d28e1848c95fe2e44c000f3f21b1 0 {cd010b8cd998f3981a5a8115f94f8da4ab506089} (*) {'user': 'test'} (glob) + 5fddd98957c8a54a4d436dfe1da9d87f21a1b97b 5ae4c968c6aca831df823664e706c9d4aa34473d 0 (*) {'user': 'test'} (glob) + 32af7686d403cf45b5d95f2d70cebea587ac806a 0 {5fddd98957c8a54a4d436dfe1da9d87f21a1b97b} (*) {'user': 'test'} (glob) More complex case were part of the rebase set were already rebased $ hg rebase --rev 'desc(D)' --dest 'desc(H)' $ hg debugobsolete - 42ccdea3bb16d28e1848c95fe2e44c000f3f21b1 0 {'date': '*', 'user': 'test'} (glob) - 5fddd98957c8a54a4d436dfe1da9d87f21a1b97b 5ae4c968c6aca831df823664e706c9d4aa34473d 0 {'date': '*', 'user': 'test'} (glob) - 32af7686d403cf45b5d95f2d70cebea587ac806a 0 {'date': '*', 'user': 'test'} (glob) - 08483444fef91d6224f6655ee586a65d263ad34c 4596109a6a4328c398bde3a4a3b6737cfade3003 0 {'date': '* *', 'user': 'test'} (glob) + 42ccdea3bb16d28e1848c95fe2e44c000f3f21b1 0 {cd010b8cd998f3981a5a8115f94f8da4ab506089} (*) {'user': 'test'} (glob) + 5fddd98957c8a54a4d436dfe1da9d87f21a1b97b 5ae4c968c6aca831df823664e706c9d4aa34473d 0 (*) {'user': 'test'} (glob) + 32af7686d403cf45b5d95f2d70cebea587ac806a 0 {5fddd98957c8a54a4d436dfe1da9d87f21a1b97b} (*) {'user': 'test'} (glob) + 08483444fef91d6224f6655ee586a65d263ad34c 4596109a6a4328c398bde3a4a3b6737cfade3003 0 (*) {'user': 'test'} (glob) $ hg log -G @ 11:4596109a6a43 D | @@ -200,13 +200,13 @@ $ hg rebase --source 'desc(B)' --dest 'tip' $ hg debugobsolete - 42ccdea3bb16d28e1848c95fe2e44c000f3f21b1 0 {'date': '* *', 'user': 'test'} (glob) - 5fddd98957c8a54a4d436dfe1da9d87f21a1b97b 5ae4c968c6aca831df823664e706c9d4aa34473d 0 {'date': '* *', 'user': 'test'} (glob) - 32af7686d403cf45b5d95f2d70cebea587ac806a 0 {'date': '* *', 'user': 'test'} (glob) - 08483444fef91d6224f6655ee586a65d263ad34c 4596109a6a4328c398bde3a4a3b6737cfade3003 0 {'date': '* *', 'user': 'test'} (glob) - 8877864f1edb05d0e07dc4ba77b67a80a7b86672 462a34d07e599b87ea08676a449373fe4e2e1347 0 {'date': '* *', 'user': 'test'} (glob) - 08483444fef91d6224f6655ee586a65d263ad34c 0 {'date': '* *', 'user': 'test'} (glob) - 5ae4c968c6aca831df823664e706c9d4aa34473d 98f6af4ee9539e14da4465128f894c274900b6e5 0 {'date': '* *', 'user': 'test'} (glob) + 42ccdea3bb16d28e1848c95fe2e44c000f3f21b1 0 {cd010b8cd998f3981a5a8115f94f8da4ab506089} (*) {'user': 'test'} (glob) + 5fddd98957c8a54a4d436dfe1da9d87f21a1b97b 5ae4c968c6aca831df823664e706c9d4aa34473d 0 (*) {'user': 'test'} (glob) + 32af7686d403cf45b5d95f2d70cebea587ac806a 0 {5fddd98957c8a54a4d436dfe1da9d87f21a1b97b} (*) {'user': 'test'} (glob) + 08483444fef91d6224f6655ee586a65d263ad34c 4596109a6a4328c398bde3a4a3b6737cfade3003 0 (*) {'user': 'test'} (glob) + 8877864f1edb05d0e07dc4ba77b67a80a7b86672 462a34d07e599b87ea08676a449373fe4e2e1347 0 (*) {'user': 'test'} (glob) + 08483444fef91d6224f6655ee586a65d263ad34c 0 {8877864f1edb05d0e07dc4ba77b67a80a7b86672} (*) {'user': 'test'} (glob) + 5ae4c968c6aca831df823664e706c9d4aa34473d 98f6af4ee9539e14da4465128f894c274900b6e5 0 (*) {'user': 'test'} (glob) $ hg log --rev 'divergent()' $ hg log -G o 13:98f6af4ee953 C @@ -286,9 +286,9 @@ $ hg id --debug -r tip 4dc2197e807bae9817f09905b50ab288be2dbbcf tip $ hg debugobsolete - 42ccdea3bb16d28e1848c95fe2e44c000f3f21b1 4dc2197e807bae9817f09905b50ab288be2dbbcf 0 {'date': '*', 'user': 'test'} (glob) - 5fddd98957c8a54a4d436dfe1da9d87f21a1b97b 4dc2197e807bae9817f09905b50ab288be2dbbcf 0 {'date': '*', 'user': 'test'} (glob) - 32af7686d403cf45b5d95f2d70cebea587ac806a 4dc2197e807bae9817f09905b50ab288be2dbbcf 0 {'date': '*', 'user': 'test'} (glob) + 42ccdea3bb16d28e1848c95fe2e44c000f3f21b1 4dc2197e807bae9817f09905b50ab288be2dbbcf 0 (*) {'user': 'test'} (glob) + 5fddd98957c8a54a4d436dfe1da9d87f21a1b97b 4dc2197e807bae9817f09905b50ab288be2dbbcf 0 (*) {'user': 'test'} (glob) + 32af7686d403cf45b5d95f2d70cebea587ac806a 4dc2197e807bae9817f09905b50ab288be2dbbcf 0 (*) {'user': 'test'} (glob) $ cd .. @@ -345,9 +345,9 @@ o 0:cd010b8cd998 A $ hg debugobsolete - 5fddd98957c8a54a4d436dfe1da9d87f21a1b97b e273c5e7d2d29df783dce9f9eaa3ac4adc69c15d 0 {'date': '*', 'user': 'test'} (glob) - 32af7686d403cf45b5d95f2d70cebea587ac806a cf44d2f5a9f4297a62be94cbdd3dff7c7dc54258 0 {'date': '*', 'user': 'test'} (glob) - 42ccdea3bb16d28e1848c95fe2e44c000f3f21b1 7c6027df6a99d93f461868e5433f63bde20b6dfb 0 {'date': '*', 'user': 'test'} (glob) + 5fddd98957c8a54a4d436dfe1da9d87f21a1b97b e273c5e7d2d29df783dce9f9eaa3ac4adc69c15d 0 (*) {'user': 'test'} (glob) + 32af7686d403cf45b5d95f2d70cebea587ac806a cf44d2f5a9f4297a62be94cbdd3dff7c7dc54258 0 (*) {'user': 'test'} (glob) + 42ccdea3bb16d28e1848c95fe2e44c000f3f21b1 7c6027df6a99d93f461868e5433f63bde20b6dfb 0 (*) {'user': 'test'} (glob) Test that rewriting leaving instability behind is allowed ---------------------------------------------------------------------
--- a/tests/test-rebase-scenario-global.t Sat Aug 30 15:13:02 2014 +0200 +++ b/tests/test-rebase-scenario-global.t Sat Aug 30 18:44:59 2014 +0200 @@ -663,7 +663,7 @@ o 0: 'A' -Test that rebase is not confused by $CWD disappearing during rebase (issue 4121) +Test that rebase is not confused by $CWD disappearing during rebase (issue4121) $ cd .. $ hg init cwd-vanish
--- a/tests/test-relink.t Sat Aug 30 15:13:02 2014 +0200 +++ b/tests/test-relink.t Sat Aug 30 18:44:59 2014 +0200 @@ -1,4 +1,4 @@ - $ "$TESTDIR/hghave" hardlink || exit 80 +#require hardlink $ echo "[extensions]" >> $HGRCPATH $ echo "relink=" >> $HGRCPATH
--- a/tests/test-repair-strip.t Sat Aug 30 15:13:02 2014 +0200 +++ b/tests/test-repair-strip.t Sat Aug 30 18:44:59 2014 +0200 @@ -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 Sat Aug 30 15:13:02 2014 +0200 +++ b/tests/test-revert-flags.t Sat Aug 30 18:44:59 2014 +0200 @@ -1,4 +1,4 @@ - $ "$TESTDIR/hghave" execbit || exit 80 +#require execbit $ hg init repo $ cd repo
--- a/tests/test-revert.t Sat Aug 30 15:13:02 2014 +0200 +++ b/tests/test-revert.t Sat Aug 30 18:44:59 2014 +0200 @@ -14,101 +14,94 @@ [255] $ hg revert --all - $ echo 123 > b +Introduce some changes and revert them +-------------------------------------- -should show b unknown + $ echo 123 > b $ hg status ? b $ echo 12 > c -should show b unknown and c modified - $ hg status M c ? b $ hg add b -should show b added and c modified - $ hg status M c A b $ hg rm a -should show a removed, b added and c modified - $ hg status M c A b R a - $ hg revert a -should show b added, copy saved, and c modified +revert removal of a file + $ hg revert a $ hg status M c A b - $ hg revert b -should show b unknown, and c modified +revert addition of a file + $ hg revert b $ hg status M c ? b - $ hg revert --no-backup c -should show unknown: b +revert modification of a file (--no-backup) + $ hg revert --no-backup c $ hg status ? b - $ hg add b -should show b added +revert deletion (! status) of a added file +------------------------------------------ + + $ hg add b $ hg status b A b $ rm b - -should show b deleted - $ hg status b ! b $ hg revert -v b forgetting b - -should not find b - $ hg status b b: * (glob) -should show a c e - $ ls a 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 +115,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 @@ -145,21 +143,24 @@ $ hg st d R d -should silently keep d removed +should keep d removed $ hg revert -r0 d + no changes needed to d $ hg st d R d $ 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 reverting c -should print non-executable - $ test -x c || echo non-executable non-executable @@ -170,8 +171,6 @@ $ hg revert --all reverting c -should print executable - $ test -x c && echo executable executable #endif @@ -180,6 +179,7 @@ Issue241: update and revert produces inconsistent repositories +-------------------------------------------------------------- $ hg init a $ cd a @@ -193,20 +193,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 +227,7 @@ reverting a rename target should revert the source +-------------------------------------------------- $ hg mv a newa $ hg revert newa @@ -258,6 +262,7 @@ $ hg rm removed ignoreddir/removed should revert ignored* and undelete *removed +-------------------------------------------- $ hg revert -a --no-backup reverting ignored @@ -271,10 +276,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 +309,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 +319,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 +327,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 +341,7 @@ commit: 2 modified, 1 removed (merge) update: (current) -(clarifies who added what) +clarifies who added what $ hg status M allyour @@ -344,7 +354,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 +363,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 +374,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 +384,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 @@ -381,4 +395,807 @@ R ignored R newadd +Systematic behavior validation of most possible cases +===================================================== +This section tests most of the possible combinations of working directory +changes and inter-revision changes. The number of possible cases is significant +but they all have a slighly different handling. So this section commits to +generating and testing all of them to allow safe refactoring of the revert code. + +A python script is used to generate a file history for each combination of +changes between, on one side the working directory and its parent and on +the other side, changes between a revert target (--rev) and working directory +parent. The three states generated are: + +- a "base" revision +- a "parent" revision +- the working directory (based on "parent") + +The file generated have names of the form: + + <changeset-state>_<working-copy-state> + +Here, "changeset-state" conveys the state in "base" and "parent" (or the change +that happen between them), "working-copy-state" is self explanatory. + +All known states are not tested yet. See inline documentation for details. +Special cases from merge and rename are not tested by this section. + +There are also multiple cases where the current revert implementation is known to +slightly misbehave. + +Write the python script to disk +------------------------------- + + $ cat << EOF > gen-revert-cases.py + > # generate proper file state to test revert behavior + > import sys + > import os + > + > # content of the file in "base" and "parent" + > # None means no file at all + > ctxcontent = { + > # clean: no change from base to parent + > 'clean': ['base', 'base'], + > # modified: file content change from base to parent + > 'modified': ['base', 'parent'], + > # added: file is missing from base and added in parent + > 'added': [None, 'parent'], + > # removed: file exist in base but is removed from parent + > 'removed': ['base', None], + > # file exist neither in base not in parent + > 'missing': [None, None], + > } + > + > # content of file in working copy + > wccontent = { + > # clean: wc content is the same as parent + > 'clean': lambda cc: cc[1], + > # revert: wc content is the same as base + > 'revert': lambda cc: cc[0], + > # wc: file exist with a content different from base and parent + > 'wc': lambda cc: 'wc', + > # removed: file is missing and marked as untracked + > 'removed': lambda cc: None, + > # deleted: file is recorded as tracked but missing + > # rely on file deletion outside of this script + > 'deleted': lambda cc:'TOBEDELETED', + > } + > # untracked-X is a version of X where the file is not tracked (? unknown) + > wccontent['untracked-clean'] = wccontent['clean'] + > wccontent['untracked-revert'] = wccontent['revert'] + > wccontent['untracked-wc'] = wccontent['wc'] + > + > # build the combination of possible states + > combination = [] + > for ctxkey in ctxcontent: + > for wckey in wccontent: + > filename = "%s_%s" % (ctxkey, wckey) + > combination.append((filename, ctxkey, wckey)) + > + > # make sure we have stable output + > combination.sort() + > + > # retrieve the state we must generate + > target = sys.argv[1] + > + > # compute file content + > content = [] + > for filename, ctxkey, wckey in combination: + > cc = ctxcontent[ctxkey] + > if target == 'filelist': + > print filename + > elif target == 'base': + > content.append((filename, cc[0])) + > elif target == 'parent': + > content.append((filename, cc[1])) + > elif target == 'wc': + > content.append((filename, wccontent[wckey](cc))) + > else: + > print >> sys.stderr, "unknown target:", target + > sys.exit(1) + > + > # write actual content + > for filename, data in content: + > if data is not None: + > f = open(filename, 'w') + > f.write(data + '\n') + > f.close() + > elif os.path.exists(filename): + > os.remove(filename) + > EOF + +check list of planned files + + $ python gen-revert-cases.py filelist + added_clean + added_deleted + added_removed + added_revert + added_untracked-clean + added_untracked-revert + added_untracked-wc + added_wc + clean_clean + clean_deleted + clean_removed + clean_revert + clean_untracked-clean + clean_untracked-revert + clean_untracked-wc + clean_wc + missing_clean + missing_deleted + missing_removed + missing_revert + missing_untracked-clean + missing_untracked-revert + missing_untracked-wc + missing_wc + modified_clean + modified_deleted + modified_removed + modified_revert + modified_untracked-clean + modified_untracked-revert + modified_untracked-wc + modified_wc + removed_clean + removed_deleted + removed_removed + removed_revert + removed_untracked-clean + removed_untracked-revert + removed_untracked-wc + removed_wc + +Script to make a simple text version of the content +--------------------------------------------------- + + $ cat << EOF >> dircontent.py + > # generate a simple text view of the directory for easy comparison + > import os + > files = os.listdir('.') + > files.sort() + > for filename in files: + > if os.path.isdir(filename): + > continue + > content = open(filename).read() + > print '%-6s %s' % (content.strip(), filename) + > EOF + +Generate appropriate repo state +------------------------------- + + $ hg init revert-ref + $ cd revert-ref + +Generate base changeset + + $ python ../gen-revert-cases.py base + $ hg addremove --similarity 0 + adding clean_clean + adding clean_deleted + adding clean_removed + adding clean_revert + adding clean_untracked-clean + adding clean_untracked-revert + adding clean_untracked-wc + adding clean_wc + adding modified_clean + adding modified_deleted + adding modified_removed + adding modified_revert + adding modified_untracked-clean + adding modified_untracked-revert + adding modified_untracked-wc + adding modified_wc + adding removed_clean + adding removed_deleted + adding removed_removed + adding removed_revert + adding removed_untracked-clean + adding removed_untracked-revert + adding removed_untracked-wc + adding removed_wc + $ hg status + A clean_clean + A clean_deleted + A clean_removed + A clean_revert + A clean_untracked-clean + A clean_untracked-revert + A clean_untracked-wc + A clean_wc + A modified_clean + A modified_deleted + A modified_removed + A modified_revert + A modified_untracked-clean + A modified_untracked-revert + A modified_untracked-wc + A modified_wc + A removed_clean + A removed_deleted + A removed_removed + A removed_revert + A removed_untracked-clean + A removed_untracked-revert + A removed_untracked-wc + A removed_wc + $ hg commit -m 'base' + +(create a simple text version of the content) + + $ python ../dircontent.py > ../content-base.txt + $ cat ../content-base.txt + base clean_clean + base clean_deleted + base clean_removed + base clean_revert + base clean_untracked-clean + base clean_untracked-revert + base clean_untracked-wc + base clean_wc + base modified_clean + base modified_deleted + base modified_removed + base modified_revert + base modified_untracked-clean + base modified_untracked-revert + base modified_untracked-wc + base modified_wc + base removed_clean + base removed_deleted + base removed_removed + base removed_revert + base removed_untracked-clean + base removed_untracked-revert + base removed_untracked-wc + base removed_wc + +Create parent changeset + + $ python ../gen-revert-cases.py parent + $ hg addremove --similarity 0 + adding added_clean + adding added_deleted + adding added_removed + adding added_revert + adding added_untracked-clean + adding added_untracked-revert + adding added_untracked-wc + adding added_wc + removing removed_clean + removing removed_deleted + removing removed_removed + removing removed_revert + removing removed_untracked-clean + removing removed_untracked-revert + removing removed_untracked-wc + removing removed_wc + $ hg status + M modified_clean + M modified_deleted + M modified_removed + M modified_revert + M modified_untracked-clean + M modified_untracked-revert + M modified_untracked-wc + M modified_wc + A added_clean + A added_deleted + A added_removed + A added_revert + A added_untracked-clean + A added_untracked-revert + A added_untracked-wc + A added_wc + R removed_clean + R removed_deleted + R removed_removed + R removed_revert + R removed_untracked-clean + R removed_untracked-revert + R removed_untracked-wc + R removed_wc + $ hg commit -m 'parent' + +(create a simple text version of the content) + + $ python ../dircontent.py > ../content-parent.txt + $ cat ../content-parent.txt + parent added_clean + parent added_deleted + parent added_removed + parent added_revert + parent added_untracked-clean + parent added_untracked-revert + parent added_untracked-wc + parent added_wc + base clean_clean + base clean_deleted + base clean_removed + base clean_revert + base clean_untracked-clean + base clean_untracked-revert + base clean_untracked-wc + base clean_wc + parent modified_clean + parent modified_deleted + parent modified_removed + parent modified_revert + parent modified_untracked-clean + parent modified_untracked-revert + parent modified_untracked-wc + parent modified_wc + +Setup working directory + + $ python ../gen-revert-cases.py wc | cat + $ hg addremove --similarity 0 + removing added_removed + removing added_revert + removing added_untracked-revert + removing clean_removed + adding missing_deleted + adding missing_untracked-wc + adding missing_wc + removing modified_removed + adding removed_deleted + adding removed_revert + adding removed_untracked-revert + adding removed_untracked-wc + adding removed_wc + $ hg forget *untracked* + $ rm *deleted* + $ hg status + M added_wc + M clean_wc + M modified_revert + M modified_wc + A missing_wc + A removed_revert + A removed_wc + R added_removed + R added_revert + R added_untracked-clean + R added_untracked-revert + R added_untracked-wc + R clean_removed + R clean_untracked-clean + R clean_untracked-revert + R clean_untracked-wc + R modified_removed + R modified_untracked-clean + R modified_untracked-revert + R modified_untracked-wc + ! added_deleted + ! clean_deleted + ! missing_deleted + ! modified_deleted + ! removed_deleted + ? missing_untracked-wc + ? removed_untracked-revert + ? removed_untracked-wc + + $ hg status --rev 'desc("base")' + M clean_wc + M modified_clean + M modified_wc + M removed_wc + A added_clean + A added_wc + A missing_wc + R clean_removed + R clean_untracked-clean + R clean_untracked-revert + R clean_untracked-wc + R modified_removed + R modified_untracked-clean + R modified_untracked-revert + R modified_untracked-wc + R removed_clean + R removed_deleted + R removed_removed + R removed_untracked-clean + R removed_untracked-revert + R removed_untracked-wc + ! added_deleted + ! clean_deleted + ! missing_deleted + ! modified_deleted + ! removed_deleted + ? missing_untracked-wc + +(create a simple text version of the content) + + $ python ../dircontent.py > ../content-wc.txt + $ cat ../content-wc.txt + parent added_clean + parent added_untracked-clean + wc added_untracked-wc + wc added_wc + base clean_clean + base clean_revert + base clean_untracked-clean + base clean_untracked-revert + wc clean_untracked-wc + wc clean_wc + wc missing_untracked-wc + wc missing_wc + parent modified_clean + base modified_revert + parent modified_untracked-clean + base modified_untracked-revert + wc modified_untracked-wc + wc modified_wc + base removed_revert + base removed_untracked-revert + wc removed_untracked-wc + wc removed_wc + + $ cd .. + +Test revert --all to parent content +----------------------------------- + +(setup from reference repo) + + $ cp -r revert-ref revert-parent-all + $ cd revert-parent-all + +check revert output + + $ hg revert --all + reverting added_deleted + undeleting added_removed + undeleting added_revert + undeleting added_untracked-clean + undeleting added_untracked-revert + undeleting added_untracked-wc + reverting added_wc + reverting clean_deleted + undeleting clean_removed + undeleting clean_untracked-clean + undeleting clean_untracked-revert + undeleting clean_untracked-wc + reverting clean_wc + forgetting missing_deleted + forgetting missing_wc + reverting modified_deleted + undeleting modified_removed + reverting modified_revert + undeleting modified_untracked-clean + undeleting modified_untracked-revert + undeleting modified_untracked-wc + reverting modified_wc + forgetting removed_deleted + forgetting removed_revert + forgetting removed_wc + +Compare resulting directory with revert target. + +The diff is filtered to include change only. The only difference should be +additional `.orig` backup file when applicable. + + $ python ../dircontent.py > ../content-parent-all.txt + $ cd .. + $ diff -U 0 -- content-parent.txt content-parent-all.txt | grep _ + +wc added_untracked-wc.orig + +wc added_wc.orig + +wc clean_untracked-wc.orig + +wc clean_wc.orig + +wc missing_untracked-wc + +wc missing_wc + +base modified_revert.orig + +base modified_untracked-revert.orig + +wc modified_untracked-wc.orig + +wc modified_wc.orig + +base removed_revert + +base removed_untracked-revert + +wc removed_untracked-wc + +wc removed_wc + +Test revert --all to "base" content +----------------------------------- + +(setup from reference repo) + + $ cp -r revert-ref revert-base-all + $ cd revert-base-all + +check revert output + + $ hg revert --all --rev 'desc(base)' + removing added_clean + removing added_deleted + removing added_wc + reverting clean_deleted + undeleting clean_removed + undeleting clean_untracked-clean + undeleting clean_untracked-revert + undeleting clean_untracked-wc + reverting clean_wc + forgetting missing_deleted + forgetting missing_wc + reverting modified_clean + reverting modified_deleted + undeleting modified_removed + undeleting modified_untracked-clean + undeleting modified_untracked-revert + undeleting modified_untracked-wc + reverting modified_wc + adding removed_clean + reverting removed_deleted + adding removed_removed + adding removed_untracked-clean + adding removed_untracked-revert + adding removed_untracked-wc + reverting removed_wc + +Compare resulting directory with revert target. + +The diff is filtered to include change only. The only difference should be +additional `.orig` backup file when applicable. + +Misbehavior: + +- no backup for +| - added_wc (DATA LOSS) + + $ python ../dircontent.py > ../content-base-all.txt + $ cd .. + $ diff -U 0 -- content-base.txt content-base-all.txt | grep _ + +parent added_untracked-clean + +wc added_untracked-wc + +wc clean_untracked-wc.orig + +wc clean_wc.orig + +wc missing_untracked-wc + +wc missing_wc + +parent modified_untracked-clean.orig + +wc modified_untracked-wc.orig + +wc modified_wc.orig + +wc removed_untracked-wc.orig + +wc removed_wc.orig + +Test revert to parent content with explicit file name +----------------------------------------------------- + +(setup from reference repo) + + $ cp -r revert-ref revert-parent-explicit + $ cd revert-parent-explicit + +revert all files individually and check the output +(output is expected to be different than in the --all case) + + $ for file in `python ../gen-revert-cases.py filelist`; do + > echo '### revert for:' $file; + > hg revert $file; + > echo + > done + ### revert for: added_clean + no changes needed to added_clean + + ### revert for: added_deleted + + ### revert for: added_removed + + ### revert for: added_revert + + ### revert for: added_untracked-clean + + ### revert for: added_untracked-revert + + ### revert for: added_untracked-wc + + ### revert for: added_wc + + ### revert for: clean_clean + no changes needed to clean_clean + + ### revert for: clean_deleted + + ### revert for: clean_removed + + ### revert for: clean_revert + no changes needed to clean_revert + + ### revert for: clean_untracked-clean + + ### revert for: clean_untracked-revert + + ### revert for: clean_untracked-wc + + ### revert for: clean_wc + + ### revert for: missing_clean + missing_clean: no such file in rev * (glob) + + ### revert for: missing_deleted + + ### revert for: missing_removed + missing_removed: no such file in rev * (glob) + + ### revert for: missing_revert + missing_revert: no such file in rev * (glob) + + ### revert for: missing_untracked-clean + missing_untracked-clean: no such file in rev * (glob) + + ### revert for: missing_untracked-revert + missing_untracked-revert: no such file in rev * (glob) + + ### revert for: missing_untracked-wc + file not managed: missing_untracked-wc + + ### revert for: missing_wc + + ### revert for: modified_clean + no changes needed to modified_clean + + ### revert for: modified_deleted + + ### revert for: modified_removed + + ### revert for: modified_revert + + ### revert for: modified_untracked-clean + + ### revert for: modified_untracked-revert + + ### revert for: modified_untracked-wc + + ### revert for: modified_wc + + ### revert for: removed_clean + removed_clean: no such file in rev * (glob) + + ### revert for: removed_deleted + + ### revert for: removed_removed + removed_removed: no such file in rev * (glob) + + ### revert for: removed_revert + + ### revert for: removed_untracked-clean + removed_untracked-clean: no such file in rev * (glob) + + ### revert for: removed_untracked-revert + file not managed: removed_untracked-revert + + ### revert for: removed_untracked-wc + file not managed: removed_untracked-wc + + ### revert for: removed_wc + + +check resulting directory againt the --all run +(There should be no difference) + + $ python ../dircontent.py > ../content-parent-explicit.txt + $ cd .. + $ diff -U 0 -- content-parent-all.txt content-parent-explicit.txt | grep _ + [1] + +Test revert to "base" content with explicit file name +----------------------------------------------------- + +(setup from reference repo) + + $ cp -r revert-ref revert-base-explicit + $ cd revert-base-explicit + +revert all files individually and check the output +(output is expected to be different than in the --all case) + + $ for file in `python ../gen-revert-cases.py filelist`; do + > echo '### revert for:' $file; + > hg revert $file --rev 'desc(base)'; + > echo + > done + ### revert for: added_clean + + ### revert for: added_deleted + + ### revert for: added_removed + no changes needed to added_removed + + ### revert for: added_revert + no changes needed to added_revert + + ### revert for: added_untracked-clean + no changes needed to added_untracked-clean + + ### revert for: added_untracked-revert + no changes needed to added_untracked-revert + + ### revert for: added_untracked-wc + no changes needed to added_untracked-wc + + ### revert for: added_wc + + ### revert for: clean_clean + no changes needed to clean_clean + + ### revert for: clean_deleted + + ### revert for: clean_removed + + ### revert for: clean_revert + no changes needed to clean_revert + + ### revert for: clean_untracked-clean + + ### revert for: clean_untracked-revert + + ### revert for: clean_untracked-wc + + ### revert for: clean_wc + + ### revert for: missing_clean + missing_clean: no such file in rev * (glob) + + ### revert for: missing_deleted + + ### revert for: missing_removed + missing_removed: no such file in rev * (glob) + + ### revert for: missing_revert + missing_revert: no such file in rev * (glob) + + ### revert for: missing_untracked-clean + missing_untracked-clean: no such file in rev * (glob) + + ### revert for: missing_untracked-revert + missing_untracked-revert: no such file in rev * (glob) + + ### revert for: missing_untracked-wc + file not managed: missing_untracked-wc + + ### revert for: missing_wc + + ### revert for: modified_clean + + ### revert for: modified_deleted + + ### revert for: modified_removed + + ### revert for: modified_revert + no changes needed to modified_revert + + ### revert for: modified_untracked-clean + + ### revert for: modified_untracked-revert + + ### revert for: modified_untracked-wc + + ### revert for: modified_wc + + ### revert for: removed_clean + + ### revert for: removed_deleted + + ### revert for: removed_removed + + ### revert for: removed_revert + no changes needed to removed_revert + + ### revert for: removed_untracked-clean + + ### revert for: removed_untracked-revert + + ### revert for: removed_untracked-wc + + ### revert for: removed_wc + + +check resulting directory againt the --all run +(There should be no difference) + + $ python ../dircontent.py > ../content-base-explicit.txt + $ cd .. + $ diff -U 0 -- content-base-all.txt content-base-explicit.txt | grep _ + [1]
--- a/tests/test-rollback.t Sat Aug 30 15:13:02 2014 +0200 +++ b/tests/test-rollback.t Sat Aug 30 18:44:59 2014 +0200 @@ -96,7 +96,7 @@ bar $ hg bookmark --delete foo -rollback by pretxncommit saves commit message (issue 1635) +rollback by pretxncommit saves commit message (issue1635) $ echo a >> a $ hg --config hooks.pretxncommit=false commit -m"precious commit message"
--- a/tests/test-run-tests.t Sat Aug 30 15:13:02 2014 +0200 +++ b/tests/test-run-tests.t Sat Aug 30 18:44:59 2014 +0200 @@ -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 (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 !. @@ -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 (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 ! 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 + . + # Ran 2 tests, 1 skipped, 0 warned, 0 failed. + failed $ $TESTDIR/run-tests.py --with-hg=`which hg` test-failure.t --- $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 ! @@ -89,6 +137,25 @@ python hash seed: * (glob) [1] +failure w/ keyword + $ $TESTDIR/run-tests.py --with-hg=`which hg` -k rataxes + + --- $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, 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,20 @@ $ cat test-failure.t $ echo babar rataxes + This is a noop statement so that + this test is still more bytes than success. + +View the fix + + $ echo 'y' | $TESTDIR/run-tests.py --with-hg=`which hg` --view echo + $TESTTMP/test-failure.t $TESTTMP/test-failure.t.err + + 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] Accept the fix @@ -178,16 +269,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 +296,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: skipped + 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 + .s + Skipped test-skip.t: skipped + # Ran 2 tests, 2 skipped, 0 warned, 0 failed. + +Skips with xml + $ $TESTDIR/run-tests.py --with-hg=`which hg` --keyword xyzzy \ + > --xunit=xunit.xml + .s + Skipped test-skip.t: skipped + # Ran 2 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="2"> + <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 Sat Aug 30 15:13:02 2014 +0200 +++ b/tests/test-schemes.t Sat Aug 30 18:44:59 2014 +0200 @@ -1,4 +1,4 @@ - $ "$TESTDIR/hghave" serve || exit 80 +#require serve $ cat <<EOF >> $HGRCPATH > [extensions]
--- a/tests/test-serve.t Sat Aug 30 15:13:02 2014 +0200 +++ b/tests/test-serve.t Sat Aug 30 18:44:59 2014 +0200 @@ -1,4 +1,4 @@ - $ "$TESTDIR/hghave" serve || exit 80 +#require serve $ hgserve() > {
--- a/tests/test-share.t Sat Aug 30 15:13:02 2014 +0200 +++ b/tests/test-share.t Sat Aug 30 18:44:59 2014 +0200 @@ -1,4 +1,4 @@ - $ "$TESTDIR/hghave" killdaemons || exit 80 +#require killdaemons $ echo "[extensions]" >> $HGRCPATH $ echo "share = " >> $HGRCPATH
--- a/tests/test-shelve.t Sat Aug 30 15:13:02 2014 +0200 +++ b/tests/test-shelve.t Sat Aug 30 18:44:59 2014 +0200 @@ -446,7 +446,7 @@ $ hg --config extensions.mq=! unshelve unshelving change 'test' -shelve should leave dirstate clean (issue 4055) +shelve should leave dirstate clean (issue4055) $ cd .. $ hg init shelverebase @@ -475,7 +475,7 @@ $ cd .. -shelve should only unshelve pending changes (issue 4068) +shelve should only unshelve pending changes (issue4068) $ hg init onlypendingchanges $ cd onlypendingchanges @@ -680,9 +680,6 @@ g $ hg unshelve --abort rebase aborted - no changes needed to a - no changes needed to d - no changes needed to e unshelve of 'default' aborted $ hg st ? f.orig
--- a/tests/test-simplemerge.py Sat Aug 30 15:13:02 2014 +0200 +++ b/tests/test-simplemerge.py Sat Aug 30 18:44:59 2014 +0200 @@ -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 Sat Aug 30 15:13:02 2014 +0200 +++ b/tests/test-simplemerge.py.out Sat Aug 30 18:44:59 2014 +0200 @@ -1,5 +1,5 @@ -.................... +................ ---------------------------------------------------------------------- -Ran 20 tests in 0.000s +Ran 16 tests in 0.000s OK
--- a/tests/test-ssh.t Sat Aug 30 15:13:02 2014 +0200 +++ b/tests/test-ssh.t Sat Aug 30 18:44:59 2014 +0200 @@ -360,6 +360,47 @@ $ cd .. +stderr from remote commands should be printed before stdout from local code (issue4336) + + $ hg clone remote stderr-ordering + updating to branch default + 3 files updated, 0 files merged, 0 files removed, 0 files unresolved + $ cd stderr-ordering + $ cat >> localwrite.py << EOF + > from mercurial import exchange, extensions + > + > def wrappedpush(orig, repo, *args, **kwargs): + > res = orig(repo, *args, **kwargs) + > repo.ui.write('local stdout\n') + > return res + > + > def extsetup(ui): + > extensions.wrapfunction(exchange, 'push', wrappedpush) + > EOF + + $ cat >> .hg/hgrc << EOF + > [paths] + > default-push = ssh://user@dummy/remote + > [ui] + > ssh = python "$TESTDIR/dummyssh" + > [extensions] + > localwrite = localwrite.py + > EOF + + $ echo localwrite > foo + $ hg commit -m 'testing localwrite' + $ hg push + pushing to ssh://user@dummy/remote + searching for changes + remote: adding changesets + remote: adding manifests + remote: adding file changes + remote: added 1 changesets with 1 changes to 1 files + remote: KABOOM + local stdout + + $ cd .. + $ cat dummylog Got arguments 1:user@dummy 2:hg -R nonexistent serve --stdio Got arguments 1:user@dummy 2:hg -R /$TESTTMP/nonexistent serve --stdio @@ -387,3 +428,5 @@ Got arguments 1:user@dummy 2:hg -R 'a repo' serve --stdio Got arguments 1:user@dummy 2:hg -R 'a repo' serve --stdio Got arguments 1:user@dummy 2:hg -R 'a repo' serve --stdio + Got arguments 1:user@dummy 2:hg -R remote serve --stdio + changegroup-in-remote hook: HG_NODE=65c38f4125f9602c8db4af56530cc221d93b8ef8 HG_SOURCE=serve HG_URL=remote:ssh:127.0.0.1
--- a/tests/test-static-http.t Sat Aug 30 15:13:02 2014 +0200 +++ b/tests/test-static-http.t Sat Aug 30 18:44:59 2014 +0200 @@ -1,4 +1,4 @@ - $ "$TESTDIR/hghave" killdaemons || exit 80 +#require killdaemons #if windows $ hg clone http://localhost:$HGPORT/ copy @@ -125,7 +125,7 @@ updating to branch default 2 files updated, 0 files merged, 0 files removed, 0 files unresolved -test with "/" URI (issue 747) and subrepo +test with "/" URI (issue747) and subrepo $ hg init $ hg init sub
--- a/tests/test-strict.t Sat Aug 30 15:13:02 2014 +0200 +++ b/tests/test-strict.t Sat Aug 30 18:44:59 2014 +0200 @@ -37,7 +37,7 @@ summary summarize working directory state update update working directory (or switch revisions) - use "hg help" for the full list of commands or "hg -v" for details + (use "hg help" for the full list of commands or "hg -v" for details) [255] $ hg annotate a 0: a
--- a/tests/test-strip.t Sat Aug 30 15:13:02 2014 +0200 +++ b/tests/test-strip.t Sat Aug 30 18:44:59 2014 +0200 @@ -532,9 +532,9 @@ strip changesets and all their descendants from the repository - use "hg help -e strip" to show help for the strip extension + (use "hg help -e strip" to show help for the strip extension) - options: + options ([+] can be repeated): -r --rev REV [+] strip specified revision (optional, can specify revisions without this option) @@ -545,7 +545,5 @@ -B --bookmark VALUE remove revs only reachable from given bookmark --mq operate on patch repository - [+] marked option can be specified multiple times - - use "hg help strip" to show the full help text + (use "hg strip -h" to show more help) [255]
--- a/tests/test-subrepo-git.t Sat Aug 30 15:13:02 2014 +0200 +++ b/tests/test-subrepo-git.t Sat Aug 30 18:44:59 2014 +0200 @@ -1,4 +1,4 @@ - $ "$TESTDIR/hghave" git || exit 80 +#require git make git commits repeatable
--- a/tests/test-subrepo-relative-path.t Sat Aug 30 15:13:02 2014 +0200 +++ b/tests/test-subrepo-relative-path.t Sat Aug 30 18:44:59 2014 +0200 @@ -1,4 +1,4 @@ - $ "$TESTDIR/hghave" killdaemons || exit 80 +#require killdaemons Preparing the subrepository 'sub'
--- a/tests/test-subrepo-svn.t Sat Aug 30 15:13:02 2014 +0200 +++ b/tests/test-subrepo-svn.t Sat Aug 30 18:44:59 2014 +0200 @@ -1,4 +1,4 @@ - $ "$TESTDIR/hghave" svn15 || exit 80 +#require svn15 $ SVNREPOPATH=`pwd`/svn-repo #if windows
--- a/tests/test-symlink-placeholder.t Sat Aug 30 15:13:02 2014 +0200 +++ b/tests/test-symlink-placeholder.t Sat Aug 30 18:44:59 2014 +0200 @@ -1,4 +1,4 @@ - $ "$TESTDIR/hghave" symlink || exit 80 +#require symlink Create extension that can disable symlink support:
--- a/tests/test-symlinks.t Sat Aug 30 15:13:02 2014 +0200 +++ b/tests/test-symlinks.t Sat Aug 30 18:44:59 2014 +0200 @@ -1,4 +1,4 @@ - $ "$TESTDIR/hghave" symlink || exit 80 +#require symlink == tests added in 0.7 ==
--- a/tests/test-transplant.t Sat Aug 30 15:13:02 2014 +0200 +++ b/tests/test-transplant.t Sat Aug 30 18:44:59 2014 +0200 @@ -1,4 +1,4 @@ - $ "$TESTDIR/hghave" killdaemons || exit 80 +#require killdaemons $ cat <<EOF >> $HGRCPATH > [extensions] @@ -95,8 +95,13 @@ $ hg ci -qm "b4" $ hg status --rev "7^1" --rev 7 A b3 - $ HGEDITOR=cat hg transplant --edit 7 + $ cat > $TESTTMP/checkeditform.sh <<EOF + > env | grep HGEDITFORM + > true + > EOF + $ HGEDITOR="sh $TESTTMP/checkeditform.sh; cat" hg transplant --edit 7 applying ffd6818a3975 + HGEDITFORM=transplant.normal b3 @@ -373,7 +378,8 @@ patch failed to apply abort: fix up the merge and run hg transplant --continue [255] - $ hg transplant --continue + $ HGEDITOR="sh $TESTTMP/checkeditform.sh" hg transplant --continue -e + HGEDITFORM=transplant.normal 46ae92138f3c transplanted as 9159dada197d $ hg transplant 1:3 skipping already applied revision 1:46ae92138f3c @@ -430,9 +436,30 @@ transplant - $ hg transplant -m 1 + $ HGEDITOR="sh $TESTTMP/checkeditform.sh" hg transplant -m 1 -e applying 42dc4432fd35 + HGEDITFORM=transplant.merge 1:42dc4432fd35 merged at a9f4acbac129 + $ hg update -q -C 2 + $ cat > a <<EOF + > x + > y + > z + > EOF + $ hg commit -m replace + $ hg update -q -C 4 + $ hg transplant -m 5 + applying 600a3cdcb41d + patching file a + Hunk #1 FAILED at 0 + 1 out of 1 hunks FAILED -- saving rejects to file a.rej + patch failed to apply + abort: fix up the merge and run hg transplant --continue + [255] + $ HGEDITOR="sh $TESTTMP/checkeditform.sh" hg transplant --continue -e + HGEDITFORM=transplant.merge + 600a3cdcb41d transplanted as a3f88be652e0 + $ cd .. test transplant into empty repository
--- a/tests/test-treediscovery-legacy.t Sat Aug 30 15:13:02 2014 +0200 +++ b/tests/test-treediscovery-legacy.t Sat Aug 30 18:44:59 2014 +0200 @@ -1,4 +1,4 @@ - $ "$TESTDIR/hghave" killdaemons || exit 80 +#require killdaemons Tests discovery against servers without getbundle support:
--- a/tests/test-treediscovery.t Sat Aug 30 15:13:02 2014 +0200 +++ b/tests/test-treediscovery.t Sat Aug 30 18:44:59 2014 +0200 @@ -1,4 +1,4 @@ - $ "$TESTDIR/hghave" killdaemons || exit 80 +#require killdaemons Tests discovery against servers without getbundle support: @@ -522,12 +522,13 @@ "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=phases "GET /?cmd=capabilities HTTP/1.1" 200 - "GET /?cmd=heads HTTP/1.1" 200 - + "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=phases + "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=bookmarks "GET /?cmd=branchmap HTTP/1.1" 200 - "GET /?cmd=branchmap HTTP/1.1" 200 - "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=bookmarks "POST /?cmd=unbundle HTTP/1.1" 200 - x-hgarg-1:heads=686173686564+1827a5bb63e602382eb89dd58f2ac9f3b007ad91 "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=phases - "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=bookmarks "GET /?cmd=capabilities HTTP/1.1" 200 - "GET /?cmd=heads HTTP/1.1" 200 - "GET /?cmd=capabilities HTTP/1.1" 200 -
--- a/tests/test-unbundlehash.t Sat Aug 30 15:13:02 2014 +0200 +++ b/tests/test-unbundlehash.t Sat Aug 30 18:44:59 2014 +0200 @@ -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 Sat Aug 30 15:13:02 2014 +0200 +++ b/tests/test-update-issue1456.t Sat Aug 30 18:44:59 2014 +0200 @@ -1,4 +1,4 @@ - $ "$TESTDIR/hghave" execbit || exit 80 +#require execbit $ rm -rf a $ hg init a