--- a/contrib/check-code.py Mon Oct 07 17:47:19 2013 -0400
+++ b/contrib/check-code.py Mon Oct 07 17:47:55 2013 -0400
@@ -61,11 +61,13 @@
(r'pushd|popd', "don't use 'pushd' or 'popd', use 'cd'"),
(r'\W\$?\(\([^\)\n]*\)\)', "don't use (()) or $(()), use 'expr'"),
(r'grep.*-q', "don't use 'grep -q', redirect to /dev/null"),
+ (r'(?<!hg )grep.*-a', "don't use 'grep -a', use in-line python"),
(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'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"),
(r'ls.*-\w*R', "don't use 'ls -R', use 'find'"),
(r'printf.*[^\\]\\([1-9]|0\d)', "don't use 'printf \NNN', use Python"),
@@ -118,7 +120,7 @@
(uprefix + r'.*\|\| echo.*(fail|error)',
"explicit exit code checks unnecessary"),
(uprefix + r'set -e', "don't use set -e"),
- (uprefix + r'\s', "don't indent commands, use > for continued lines"),
+ (uprefix + r'(\s|fi\b|done\b)', "use > for continued lines"),
(r'^ saved backup bundle to \$TESTTMP.*\.hg$', winglobmsg),
(r'^ changeset .* references (corrupted|missing) \$TESTTMP/.*[^)]$',
winglobmsg),
@@ -160,6 +162,9 @@
"tuple parameter unpacking not available in Python 3+"),
(r'lambda\s*\(.*,.*\)',
"tuple parameter unpacking not available in Python 3+"),
+ (r'import (.+,[^.]+\.[^.]+|[^.]+\.[^.]+,)',
+ '2to3 can\'t always rewrite "import qux, foo.bar", '
+ 'use "import foo.bar" on its own line instead.'),
(r'(?<!def)\s+(cmp)\(', "cmp is not available in Python 3+"),
(r'\breduce\s*\(.*', "reduce is not available in Python 3+"),
(r'\.has_key\b', "dict.has_key is not available in Python 3+"),
@@ -221,6 +226,8 @@
"missing whitespace around operator"),
(r'[^^+=*/!<>&| %-](\s=|=\s)[^= ]',
"wrong whitespace around ="),
+ (r'\([^()]*( =[^=]|[^<>!=]= )',
+ "no whitespace around = for named parameters"),
(r'raise Exception', "don't raise generic exceptions"),
(r'raise [^,(]+, (\([^\)]+\)|[^,\(\)]+)$',
"don't use old-style two-argument raise, use Exception(message)"),
@@ -285,8 +292,9 @@
(r'(while|if|do|for)\(', "use space after while/if/do/for"),
(r'return\(', "return is not a function"),
(r' ;', "no space before ;"),
+ (r'[)][{]', "space between ) and {"),
(r'\w+\* \w+', "use int *foo, not int* foo"),
- (r'\([^\)]+\) \w+', "use (int)foo, not (int) foo"),
+ (r'\W\([^\)]+\) \w+', "use (int)foo, not (int) foo"),
(r'\w+ (\+\+|--)', "use foo++, not foo ++"),
(r'\w,\w', "missing whitespace after ,"),
(r'^[^#]\w[+/*]\w', "missing whitespace in expression"),
@@ -324,7 +332,7 @@
checks = [
('python', r'.*\.(py|cgi)$', pyfilters, pypats),
('test script', r'(.*/)?test-[^.~]*$', testfilters, testpats),
- ('c', r'.*\.c$', cfilters, cpats),
+ ('c', r'.*\.[ch]$', cfilters, cpats),
('unified test', r'.*\.t$', utestfilters, utestpats),
('layering violation repo in revlog', r'mercurial/revlog\.py', pyfilters,
inrevlogpats),
--- a/contrib/debugshell.py Mon Oct 07 17:47:19 2013 -0400
+++ b/contrib/debugshell.py Mon Oct 07 17:47:55 2013 -0400
@@ -1,20 +1,52 @@
# debugshell extension
"""a python shell with repo, changelog & manifest objects"""
+import sys
import mercurial
import code
-def debugshell(ui, repo, **opts):
+def pdb(ui, repo, msg, **opts):
objects = {
'mercurial': mercurial,
'repo': repo,
'cl': repo.changelog,
'mf': repo.manifest,
}
+
+ code.interact(msg, local=objects)
+
+def ipdb(ui, repo, msg, **opts):
+ import IPython
+
+ cl = repo.changelog
+ mf = repo.manifest
+ cl, mf # use variables to appease pyflakes
+
+ IPython.embed()
+
+def debugshell(ui, repo, **opts):
bannermsg = "loaded repo : %s\n" \
"using source: %s" % (repo.root,
mercurial.__path__[0])
- code.interact(bannermsg, local=objects)
+
+ pdbmap = {
+ 'pdb' : 'code',
+ 'ipdb' : 'IPython'
+ }
+
+ debugger = ui.config("ui", "debugger")
+ if not debugger:
+ debugger = 'pdb'
+
+ # if IPython doesn't exist, fallback to code.interact
+ try:
+ __import__(pdbmap[debugger])
+ except ImportError:
+ ui.warn("%s debugger specified but %s module was not found\n"
+ % (debugger, pdbmap[debugger]))
+ debugger = 'pdb'
+
+ getattr(sys.modules[__name__], debugger)(ui, repo, bannermsg, **opts)
cmdtable = {
"debugshell|dbsh": (debugshell, [])
--- a/contrib/hgfixes/fix_bytesmod.py Mon Oct 07 17:47:19 2013 -0400
+++ b/contrib/hgfixes/fix_bytesmod.py Mon Oct 07 17:47:55 2013 -0400
@@ -58,6 +58,6 @@
else:
args = [formatstr, Comma().clone(), data]
- call = Call(Name('bytesformatter', prefix = ' '), args)
+ call = Call(Name('bytesformatter', prefix=' '), args)
return call
--- a/contrib/perf.py Mon Oct 07 17:47:19 2013 -0400
+++ b/contrib/perf.py Mon Oct 07 17:47:55 2013 -0400
@@ -87,7 +87,8 @@
@command('perftags')
def perftags(ui, repo):
- import mercurial.changelog, mercurial.manifest
+ import mercurial.changelog
+ import mercurial.manifest
def t():
repo.changelog = mercurial.changelog.changelog(repo.sopener)
repo.manifest = mercurial.manifest.manifest(repo.sopener)
@@ -171,13 +172,14 @@
copies.pathcopies(ctx1, ctx2)
timer(d)
-@command('perfmanifest')
-def perfmanifest(ui, repo):
+@command('perfmanifest', [], 'REV')
+def perfmanifest(ui, repo, rev):
+ ctx = scmutil.revsingle(repo, rev, rev)
+ t = ctx.manifestnode()
def d():
- t = repo.manifest.tip()
+ repo.manifest._mancache.clear()
+ repo.manifest._cache = None
repo.manifest.read(t)
- repo.manifest.mapcache = None
- repo.manifest._cache = None
timer(d)
@command('perfchangeset')
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/plan9/9mail Mon Oct 07 17:47:55 2013 -0400
@@ -0,0 +1,26 @@
+#!/bin/rc
+# 9mail - Mercurial email wrapper for upas/marshal
+
+fn usage {
+ echo >[1=2] usage: mercurial/9mail -f from to [cc]
+ exit usage
+}
+
+from=()
+cc=()
+to=()
+
+switch($1){
+case -f
+ from=$2
+case *
+ usage
+}
+
+to=($3)
+if(~ $#* 4)
+ cc=(-C $4)
+
+upasname=$from
+upas/marshal $cc $to
+
--- a/contrib/plan9/hgrc.d/9diff.rc Mon Oct 07 17:47:19 2013 -0400
+++ b/contrib/plan9/hgrc.d/9diff.rc Mon Oct 07 17:47:55 2013 -0400
@@ -4,4 +4,4 @@
extdiff =
[extdiff]
-9diff = 9diff -cm $parent $child $root
+9diff = /bin/mercurial/9diff -cm $parent $child $root
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/plan9/hgrc.d/9mail.rc Mon Oct 07 17:47:55 2013 -0400
@@ -0,0 +1,4 @@
+# The 9mail to support patchbomb and other email wrappers
+[email]
+method = /bin/mercurial/9mail
+
--- a/hgext/acl.py Mon Oct 07 17:47:19 2013 -0400
+++ b/hgext/acl.py Mon Oct 07 17:47:55 2013 -0400
@@ -284,8 +284,8 @@
cfg = ui.config('acl', 'config')
if cfg:
- ui.readconfig(cfg, sections = ['acl.groups', 'acl.allow.branches',
- 'acl.deny.branches', 'acl.allow', 'acl.deny'])
+ ui.readconfig(cfg, sections=['acl.groups', 'acl.allow.branches',
+ 'acl.deny.branches', 'acl.allow', 'acl.deny'])
allowbranches = buildmatch(ui, None, user, 'acl.allow.branches')
denybranches = buildmatch(ui, None, user, 'acl.deny.branches')
--- a/hgext/color.py Mon Oct 07 17:47:19 2013 -0400
+++ b/hgext/color.py Mon Oct 07 17:47:55 2013 -0400
@@ -63,6 +63,10 @@
rebase.rebased = blue
rebase.remaining = red bold
+ shelve.age = cyan
+ shelve.newest = green bold
+ shelve.name = blue bold
+
histedit.remaining = red bold
The available effects in terminfo mode are 'blink', 'bold', 'dim',
@@ -259,6 +263,9 @@
'rebase.remaining': 'red bold',
'resolve.resolved': 'green bold',
'resolve.unresolved': 'red bold',
+ 'shelve.age': 'cyan',
+ 'shelve.newest': 'green bold',
+ 'shelve.name': 'blue bold',
'status.added': 'green bold',
'status.clean': 'none',
'status.copied': 'none',
--- a/hgext/convert/__init__.py Mon Oct 07 17:47:19 2013 -0400
+++ b/hgext/convert/__init__.py Mon Oct 07 17:47:55 2013 -0400
@@ -311,7 +311,7 @@
('d', 'dest-type', '',
_('destination repository type'), _('TYPE')),
('r', 'rev', '',
- _('import up to target revision REV'), _('REV')),
+ _('import up to source revision REV'), _('REV')),
('A', 'authormap', '',
_('remap usernames using this file'), _('FILE')),
('', 'filemap', '',
--- a/hgext/convert/filemap.py Mon Oct 07 17:47:19 2013 -0400
+++ b/hgext/convert/filemap.py Mon Oct 07 17:47:55 2013 -0400
@@ -7,7 +7,7 @@
import posixpath
import shlex
from mercurial.i18n import _
-from mercurial import util
+from mercurial import util, error
from common import SKIPREV, converter_source
def rpairs(name):
@@ -195,12 +195,19 @@
self.seenchildren.clear()
for rev, wanted, arg in self.convertedorder:
if rev not in self.origparents:
- self.origparents[rev] = self.getcommit(rev).parents
+ try:
+ self.origparents[rev] = self.getcommit(rev).parents
+ except error.RepoLookupError:
+ self.ui.debug("unknown revmap source: %s\n" % rev)
+ continue
if arg is not None:
self.children[arg] = self.children.get(arg, 0) + 1
for rev, wanted, arg in self.convertedorder:
- parents = self.origparents[rev]
+ try:
+ parents = self.origparents[rev]
+ except KeyError:
+ continue # unknown revmap source
if wanted:
self.mark_wanted(rev, parents)
else:
@@ -231,8 +238,8 @@
continue
self.seenchildren[r] = self.seenchildren.get(r, 0) + 1
if self.seenchildren[r] == self.children[r]:
- del self.wantedancestors[r]
- del self.parentmap[r]
+ self.wantedancestors.pop(r, None)
+ self.parentmap.pop(r, None)
del self.seenchildren[r]
if self._rebuilt:
del self.children[r]
@@ -281,7 +288,11 @@
# of wanted ancestors of its parents. Plus rev itself.
wrev = set()
for p in parents:
- wrev.update(self.wantedancestors[p])
+ if p in self.wantedancestors:
+ wrev.update(self.wantedancestors[p])
+ else:
+ self.ui.warn(_('warning: %s parent %s is missing\n') %
+ (rev, p))
wrev.add(rev)
self.wantedancestors[rev] = wrev
--- a/hgext/convert/subversion.py Mon Oct 07 17:47:19 2013 -0400
+++ b/hgext/convert/subversion.py Mon Oct 07 17:47:55 2013 -0400
@@ -2,7 +2,8 @@
#
# Copyright(C) 2007 Daniel Holth et al
-import os, re, sys, tempfile, urllib, urllib2, xml.dom.minidom
+import os, re, sys, tempfile, urllib, urllib2
+import xml.dom.minidom
import cPickle as pickle
from mercurial import strutil, scmutil, util, encoding
--- a/hgext/factotum.py Mon Oct 07 17:47:19 2013 -0400
+++ b/hgext/factotum.py Mon Oct 07 17:47:55 2013 -0400
@@ -101,7 +101,7 @@
user, passwd = auth.get('username'), auth.get('password')
if not user or not passwd:
if not prefix:
- prefix = '*'
+ prefix = realm.split(' ')[0].lower()
params = 'service=%s prefix=%s' % (_service, prefix)
if user:
params = '%s user=%s' % (params, user)
--- a/hgext/highlight/__init__.py Mon Oct 07 17:47:19 2013 -0400
+++ b/hgext/highlight/__init__.py Mon Oct 07 17:47:55 2013 -0400
@@ -50,7 +50,7 @@
def generate_css(web, req, tmpl):
pg_style = web.config('web', 'pygments_style', 'colorful')
- fmter = highlight.HtmlFormatter(style = pg_style)
+ fmter = highlight.HtmlFormatter(style=pg_style)
req.respond(common.HTTP_OK, 'text/css')
return ['/* pygments_style = %s */\n\n' % pg_style,
fmter.get_style_defs('')]
--- a/hgext/histedit.py Mon Oct 07 17:47:19 2013 -0400
+++ b/hgext/histedit.py Mon Oct 07 17:47:55 2013 -0400
@@ -419,10 +419,6 @@
if revs:
revs = [repo.lookup(rev) for rev in revs]
- # hexlify nodes from outgoing, because we're going to parse
- # parent[0] using revsingle below, and if the binary hash
- # contains special revset characters like ":" the revset
- # parser can choke.
outgoing = discovery.findcommonoutgoing(repo, other, revs, force=force)
if not outgoing.missing:
raise util.Abort(_('no outgoing ancestors'))
@@ -519,7 +515,6 @@
if goal == 'continue':
(parentctxnode, rules, keep, topmost, replacements) = readstate(repo)
- currentparent, wantnull = repo.dirstate.parents()
parentctx = repo[parentctxnode]
parentctx, repl = bootstrapcontinue(ui, repo, parentctx, rules, opts)
replacements.extend(repl)
--- a/hgext/inotify/server.py Mon Oct 07 17:47:19 2013 -0400
+++ b/hgext/inotify/server.py Mon Oct 07 17:47:55 2013 -0400
@@ -451,8 +451,9 @@
runargs = util.hgcmd() + sys.argv[1:]
pidfile = ui.config('inotify', 'pidfile')
- if opts['daemon'] and pidfile is not None and 'pid-file' not in runargs:
- runargs.append("--pid-file=%s" % pidfile)
+ opts.setdefault('pid_file', '')
+ if opts['daemon'] and pidfile is not None and not opts['pid_file']:
+ opts['pid_file'] = pidfile
service = service()
logfile = ui.config('inotify', 'log')
--- a/hgext/largefiles/__init__.py Mon Oct 07 17:47:19 2013 -0400
+++ b/hgext/largefiles/__init__.py Mon Oct 07 17:47:55 2013 -0400
@@ -105,16 +105,26 @@
command.
'''
-from mercurial import commands
+from mercurial import commands, localrepo, extensions
import lfcommands
import reposetup
-import uisetup
+import uisetup as uisetupmod
testedwith = 'internal'
reposetup = reposetup.reposetup
-uisetup = uisetup.uisetup
+
+def featuresetup(ui, supported):
+ for name, module in extensions.extensions(ui):
+ if __name__ == module.__name__:
+ # don't die on seeing a repo with the largefiles requirement
+ supported |= set(['largefiles'])
+ return
+
+def uisetup(ui):
+ localrepo.localrepository.featuresetupfuncs.add(featuresetup)
+ uisetupmod.uisetup(ui)
commands.norepo += " lfconvert"
--- a/hgext/largefiles/overrides.py Mon Oct 07 17:47:19 2013 -0400
+++ b/hgext/largefiles/overrides.py Mon Oct 07 17:47:55 2013 -0400
@@ -315,7 +315,7 @@
lfdirstate.normal(lfile)
lfdirstate.write()
if mod:
- raise util.Abort(_('uncommitted local changes'))
+ raise util.Abort(_('uncommitted changes'))
# XXX handle removed differently
if not opts['clean']:
for lfile in unsure + modified + added:
@@ -717,7 +717,6 @@
ui.debug('--update and --rebase are not compatible, ignoring '
'the update flag\n')
del opts['rebase']
- cmdutil.bailifchanged(repo)
origpostincoming = commands.postincoming
def _dummy(*args, **kwargs):
pass
@@ -947,7 +946,7 @@
modified, added, removed, deleted = repo.status()[:4]
repo.lfstatus = False
if modified or added or removed or deleted:
- raise util.Abort(_('outstanding uncommitted changes'))
+ raise util.Abort(_('uncommitted changes'))
# Fetch doesn't use cmdutil.bailifchanged so override it to add the check
def overridefetch(orig, ui, repo, *pats, **opts):
@@ -955,7 +954,7 @@
modified, added, removed, deleted = repo.status()[:4]
repo.lfstatus = False
if modified or added or removed or deleted:
- raise util.Abort(_('outstanding uncommitted changes'))
+ raise util.Abort(_('uncommitted changes'))
return orig(ui, repo, *pats, **opts)
def overrideforget(orig, ui, repo, *pats, **opts):
--- a/hgext/largefiles/reposetup.py Mon Oct 07 17:47:19 2013 -0400
+++ b/hgext/largefiles/reposetup.py Mon Oct 07 17:47:55 2013 -0400
@@ -10,8 +10,7 @@
import copy
import os
-from mercurial import context, error, manifest, match as match_, util, \
- discovery
+from mercurial import error, manifest, match as match_, util, discovery
from mercurial import node as node_
from mercurial.i18n import _
from mercurial import localrepo
@@ -92,14 +91,8 @@
else:
# some calls in this function rely on the old version of status
self.lfstatus = False
- if isinstance(node1, context.changectx):
- ctx1 = node1
- else:
- ctx1 = self[node1]
- if isinstance(node2, context.changectx):
- ctx2 = node2
- else:
- ctx2 = self[node2]
+ ctx1 = self[node1]
+ ctx2 = self[node2]
working = ctx2.rev() is None
parentworking = working and ctx1 == self['.']
@@ -414,6 +407,14 @@
wlock.release()
def push(self, remote, force=False, revs=None, newbranch=False):
+ if remote.local():
+ missing = set(self.requirements) - remote.local().supported
+ if missing:
+ msg = _("required features are not"
+ " supported in the destination:"
+ " %s") % (', '.join(sorted(missing)))
+ raise util.Abort(msg)
+
outgoing = discovery.findcommonoutgoing(repo, remote.peer(),
force=force)
if outgoing.missing:
--- a/hgext/largefiles/uisetup.py Mon Oct 07 17:47:19 2013 -0400
+++ b/hgext/largefiles/uisetup.py Mon Oct 07 17:47:55 2013 -0400
@@ -9,7 +9,7 @@
'''setup for largefiles extension: uisetup'''
from mercurial import archival, cmdutil, commands, extensions, filemerge, hg, \
- httppeer, localrepo, merge, scmutil, sshpeer, wireproto, revset
+ httppeer, merge, scmutil, sshpeer, wireproto, revset
from mercurial.i18n import _
from mercurial.hgweb import hgweb_mod, webcommands
from mercurial.subrepo import hgsubrepo
@@ -152,9 +152,6 @@
sshpeer.sshpeer._callstream = proto.sshrepocallstream
httppeer.httppeer._callstream = proto.httprepocallstream
- # don't die on seeing a repo with the largefiles requirement
- localrepo.localrepository.supported |= set(['largefiles'])
-
# override some extensions' stuff as well
for name, module in extensions.extensions():
if name == 'fetch':
--- a/hgext/mq.py Mon Oct 07 17:47:19 2013 -0400
+++ b/hgext/mq.py Mon Oct 07 17:47:55 2013 -0400
@@ -57,15 +57,19 @@
make them behave as if --keep-changes were passed, and non-conflicting
local changes will be tolerated and preserved. If incompatible options
such as -f/--force or --exact are passed, this setting is ignored.
+
+This extension used to provide a strip command. This command now lives
+in the strip extension.
'''
from mercurial.i18n import _
from mercurial.node import bin, hex, short, nullid, nullrev
from mercurial.lock import release
from mercurial import commands, cmdutil, hg, scmutil, util, revset
-from mercurial import repair, extensions, error, phases, bookmarks
+from mercurial import extensions, error, phases
from mercurial import patch as patchmod
from mercurial import localrepo
+from mercurial import subrepo
import os, re, errno, shutil
commands.norepo += " qclone"
@@ -76,6 +80,22 @@
command = cmdutil.command(cmdtable)
testedwith = 'internal'
+# force load strip extension formely included in mq and import some utility
+try:
+ stripext = extensions.find('strip')
+except KeyError:
+ # note: load is lazy so we could avoid the try-except,
+ # but I (marmoute) prefer this explicite code.
+ class dummyui(object):
+ def debug(self, msg):
+ pass
+ stripext = extensions.load(dummyui(), 'strip', '')
+
+strip = stripext.strip
+checksubstate = stripext.checksubstate
+checklocalchanges = stripext.checklocalchanges
+
+
# Patch names looks like unix-file names.
# They must be joinable with queue directory and result in the patch path.
normname = util.normpath
@@ -282,15 +302,11 @@
phase = phases.secret
if phase is not None:
backup = repo.ui.backupconfig('phases', 'new-commit')
- # Marking the repository as committing an mq patch can be used
- # to optimize operations like branchtags().
- repo._committingpatch = True
try:
if phase is not None:
repo.ui.setconfig('phases', 'new-commit', phase)
return repo.commit(*args, **kwargs)
finally:
- repo._committingpatch = False
if phase is not None:
repo.ui.restoreconfig(backup)
@@ -331,6 +347,7 @@
except error.ConfigError:
self.gitmode = ui.config('mq', 'git', 'auto').lower()
self.plainmode = ui.configbool('mq', 'plain', False)
+ self.checkapplied = True
@util.propertycache
def applied(self):
@@ -606,7 +623,7 @@
# apply failed, strip away that rev and merge.
hg.clean(repo, head)
- self.strip(repo, [n], update=False, backup='strip')
+ strip(self.ui, repo, [n], update=False, backup='strip')
ctx = repo[rev]
ret = hg.merge(repo, rev)
@@ -631,6 +648,14 @@
return (0, n)
def qparents(self, repo, rev=None):
+ """return the mq handled parent or p1
+
+ In some case where mq get himself in being the parent of a merge the
+ paappropriate parent may be p2.
+ (eg: an in progress merge started with mq disabled)
+
+ If no parent are managed by mq, p1 is returned.
+ """
if rev is None:
(p1, p2) = repo.dirstate.parents()
if p2 == nullid:
@@ -800,6 +825,14 @@
p1, p2 = repo.dirstate.parents()
repo.setparents(p1, merge)
+ if all_files and '.hgsubstate' in all_files:
+ wctx = repo['.']
+ mctx = actx = repo[None]
+ overwrite = False
+ mergedsubstate = subrepo.submerge(repo, wctx, mctx, actx,
+ overwrite)
+ files += mergedsubstate.keys()
+
match = scmutil.matchfiles(repo, files or [])
oldtip = repo['tip']
n = newcommit(repo, None, message, ph.user, ph.date, match=match,
@@ -940,23 +973,6 @@
return top, patch
return None, None
- def checksubstate(self, repo, baserev=None):
- '''return list of subrepos at a different revision than substate.
- Abort if any subrepos have uncommitted changes.'''
- inclsubs = []
- wctx = repo[None]
- if baserev:
- bctx = repo[baserev]
- else:
- bctx = wctx.parents()[0]
- for s in sorted(wctx.substate):
- if wctx.sub(s).dirty(True):
- raise util.Abort(
- _("uncommitted changes in subrepository %s") % s)
- elif s not in bctx.substate or bctx.sub(s).dirty():
- inclsubs.append(s)
- return inclsubs
-
def putsubstate2changes(self, substatestate, changes):
for files in changes[:3]:
if '.hgsubstate' in files:
@@ -969,18 +985,14 @@
else: # modified
changes[0].append('.hgsubstate')
- def localchangesfound(self, refresh=True):
+ def checklocalchanges(self, repo, force=False, refresh=True):
+ excsuffix = ''
if refresh:
- raise util.Abort(_("local changes found, refresh first"))
- else:
- raise util.Abort(_("local changes found"))
-
- def checklocalchanges(self, repo, force=False, refresh=True):
- cmdutil.checkunfinished(repo)
- m, a, r, d = repo.status()[:4]
- if (m or a or r or d) and not force:
- self.localchangesfound(refresh)
- return m, a, r, d
+ excsuffix = ', refresh first'
+ # plain versions for i18n tool to detect them
+ _("local changes found, refresh first")
+ _("local changed subrepos found, refresh first")
+ return checklocalchanges(repo, force, excsuffix)
_reserved = ('series', 'status', 'guards', '.', '..')
def checkreservedname(self, name):
@@ -1021,7 +1033,7 @@
diffopts = self.diffopts({'git': opts.get('git')})
if opts.get('checkname', True):
self.checkpatchname(patchfn)
- inclsubs = self.checksubstate(repo)
+ inclsubs = checksubstate(repo)
if inclsubs:
inclsubs.append('.hgsubstate')
substatestate = repo.dirstate['.hgsubstate']
@@ -1111,22 +1123,6 @@
finally:
release(wlock)
- def strip(self, repo, revs, update=True, backup="all", force=None):
- wlock = lock = None
- try:
- wlock = repo.wlock()
- lock = repo.lock()
-
- if update:
- self.checklocalchanges(repo, force=force, refresh=False)
- urev = self.qparents(repo, revs[0])
- hg.clean(repo, urev)
- repo.dirstate.write()
-
- repair.strip(self.ui, repo, revs, backup)
- finally:
- release(lock, wlock)
-
def isapplied(self, patch):
"""returns (index, rev, patch)"""
for i, a in enumerate(self.applied):
@@ -1435,7 +1431,7 @@
tobackup = set(a + m + r) & tobackup
if keepchanges and tobackup:
- self.localchangesfound()
+ raise util.Abort(_("local changes found, refresh first"))
self.backup(repo, tobackup)
for f in a:
@@ -1449,7 +1445,9 @@
for patch in reversed(self.applied[start:end]):
self.ui.status(_("popping %s\n") % patch.name)
del self.applied[start:end]
- self.strip(repo, [rev], update=False, backup='strip')
+ strip(self.ui, repo, [rev], update=False, backup='strip')
+ for s, state in repo['.'].substate.items():
+ repo['.'].sub(s).get(state)
if self.applied:
self.ui.write(_("now at: %s\n") % self.applied[-1].name)
else:
@@ -1493,7 +1491,7 @@
cparents = repo.changelog.parents(top)
patchparent = self.qparents(repo, top)
- inclsubs = self.checksubstate(repo, hex(patchparent))
+ inclsubs = checksubstate(repo, hex(patchparent))
if inclsubs:
inclsubs.append('.hgsubstate')
substatestate = repo.dirstate['.hgsubstate']
@@ -1650,8 +1648,7 @@
repo.setparents(*cparents)
self.applied.pop()
self.applieddirty = True
- self.strip(repo, [top], update=False,
- backup='strip')
+ strip(self.ui, repo, [top], update=False, backup='strip')
except: # re-raises
repo.dirstate.invalidate()
raise
@@ -1823,7 +1820,7 @@
update = True
else:
update = False
- self.strip(repo, [rev], update=update, backup='strip')
+ strip(self.ui, repo, [rev], update=update, backup='strip')
if qpp:
self.ui.warn(_("saved queue repository parents: %s %s\n") %
(short(qpp[0]), short(qpp[1])))
@@ -2304,7 +2301,7 @@
if qbase:
ui.note(_('stripping applied patches from destination '
'repository\n'))
- repo.mq.strip(repo, [qbase], update=False, backup=None)
+ strip(ui, repo, [qbase], update=False, backup=None)
if not opts.get('noupdate'):
ui.note(_('updating destination repository\n'))
hg.update(repo, repo.changelog.tip())
@@ -2919,158 +2916,6 @@
q.savedirty()
return 0
-@command("strip",
- [
- ('r', 'rev', [], _('strip specified revision (optional, '
- 'can specify revisions without this '
- 'option)'), _('REV')),
- ('f', 'force', None, _('force removal of changesets, discard '
- 'uncommitted changes (no backup)')),
- ('b', 'backup', None, _('bundle only changesets with local revision'
- ' number greater than REV which are not'
- ' descendants of REV (DEPRECATED)')),
- ('', 'no-backup', None, _('no backups')),
- ('', 'nobackup', None, _('no backups (DEPRECATED)')),
- ('n', '', None, _('ignored (DEPRECATED)')),
- ('k', 'keep', None, _("do not modify working copy during strip")),
- ('B', 'bookmark', '', _("remove revs only reachable from given"
- " bookmark"))],
- _('hg strip [-k] [-f] [-n] [-B bookmark] [-r] REV...'))
-def strip(ui, repo, *revs, **opts):
- """strip changesets and all their descendants from the repository
-
- The strip command removes the specified changesets and all their
- descendants. If the working directory has uncommitted changes, the
- operation is aborted unless the --force flag is supplied, in which
- case changes will be discarded.
-
- If a parent of the working directory is stripped, then the working
- directory will automatically be updated to the most recent
- available ancestor of the stripped parent after the operation
- completes.
-
- Any stripped changesets are stored in ``.hg/strip-backup`` as a
- bundle (see :hg:`help bundle` and :hg:`help unbundle`). They can
- be restored by running :hg:`unbundle .hg/strip-backup/BUNDLE`,
- where BUNDLE is the bundle file created by the strip. Note that
- the local revision numbers will in general be different after the
- restore.
-
- Use the --no-backup option to discard the backup bundle once the
- operation completes.
-
- Strip is not a history-rewriting operation and can be used on
- changesets in the public phase. But if the stripped changesets have
- been pushed to a remote repository you will likely pull them again.
-
- Return 0 on success.
- """
- backup = 'all'
- if opts.get('backup'):
- backup = 'strip'
- elif opts.get('no_backup') or opts.get('nobackup'):
- backup = 'none'
-
- cl = repo.changelog
- revs = list(revs) + opts.get('rev')
- revs = set(scmutil.revrange(repo, revs))
-
- if opts.get('bookmark'):
- mark = opts.get('bookmark')
- marks = repo._bookmarks
- if mark not in marks:
- raise util.Abort(_("bookmark '%s' not found") % mark)
-
- # If the requested bookmark is not the only one pointing to a
- # a revision we have to only delete the bookmark and not strip
- # anything. revsets cannot detect that case.
- uniquebm = True
- for m, n in marks.iteritems():
- if m != mark and n == repo[mark].node():
- uniquebm = False
- break
- if uniquebm:
- rsrevs = repo.revs("ancestors(bookmark(%s)) - "
- "ancestors(head() and not bookmark(%s)) - "
- "ancestors(bookmark() and not bookmark(%s))",
- mark, mark, mark)
- revs.update(set(rsrevs))
- if not revs:
- del marks[mark]
- marks.write()
- ui.write(_("bookmark '%s' deleted\n") % mark)
-
- if not revs:
- raise util.Abort(_('empty revision set'))
-
- descendants = set(cl.descendants(revs))
- strippedrevs = revs.union(descendants)
- roots = revs.difference(descendants)
-
- update = False
- # if one of the wdir parent is stripped we'll need
- # to update away to an earlier revision
- for p in repo.dirstate.parents():
- if p != nullid and cl.rev(p) in strippedrevs:
- update = True
- break
-
- rootnodes = set(cl.node(r) for r in roots)
-
- q = repo.mq
- if q.applied:
- # refresh queue state if we're about to strip
- # applied patches
- if cl.rev(repo.lookup('qtip')) in strippedrevs:
- q.applieddirty = True
- start = 0
- end = len(q.applied)
- for i, statusentry in enumerate(q.applied):
- if statusentry.node in rootnodes:
- # if one of the stripped roots is an applied
- # patch, only part of the queue is stripped
- start = i
- break
- del q.applied[start:end]
- q.savedirty()
-
- revs = sorted(rootnodes)
- if update and opts.get('keep'):
- wlock = repo.wlock()
- try:
- urev = repo.mq.qparents(repo, revs[0])
- uctx = repo[urev]
-
- # only reset the dirstate for files that would actually change
- # between the working context and uctx
- descendantrevs = repo.revs("%s::." % uctx.rev())
- changedfiles = []
- for rev in descendantrevs:
- # blindly reset the files, regardless of what actually changed
- changedfiles.extend(repo[rev].files())
-
- # reset files that only changed in the dirstate too
- dirstate = repo.dirstate
- dirchanges = [f for f in dirstate if dirstate[f] != 'n']
- changedfiles.extend(dirchanges)
-
- repo.dirstate.rebuild(urev, uctx.manifest(), changedfiles)
- repo.dirstate.write()
- update = False
- finally:
- wlock.release()
-
- if opts.get('bookmark'):
- if mark == repo._bookmarkcurrent:
- bookmarks.setcurrent(repo, None)
- del marks[mark]
- marks.write()
- ui.write(_("bookmark '%s' deleted\n") % mark)
-
- repo.mq.strip(repo, revs, backup=backup, update=update,
- force=opts.get('force'))
-
- return 0
@command("qselect",
[('n', 'none', None, _('disable all guards')),
@@ -3420,7 +3265,7 @@
return queue(self.ui, self.baseui, self.path)
def abortifwdirpatched(self, errmsg, force=False):
- if self.mq.applied and not force:
+ if self.mq.applied and self.mq.checkapplied and not force:
parents = self.dirstate.parents()
patches = [s.node for s in self.mq.applied]
if parents[0] in patches or parents[1] in patches:
@@ -3436,7 +3281,7 @@
editor, extra)
def checkpush(self, force, revs):
- if self.mq.applied and not force:
+ if self.mq.applied and self.mq.checkapplied and not force:
outapplied = [e.node for e in self.mq.applied]
if revs:
# Assume applied patches have no non-patch descendants and
--- a/hgext/notify.py Mon Oct 07 17:47:19 2013 -0400
+++ b/hgext/notify.py Mon Oct 07 17:47:55 2013 -0400
@@ -133,9 +133,13 @@
'''
+import email, socket, time
+# On python2.4 you have to import this by name or they fail to
+# load. This was not a problem on Python 2.7.
+import email.Parser
from mercurial.i18n import _
from mercurial import patch, cmdutil, templater, util, mail
-import email.Parser, email.Errors, fnmatch, socket, time
+import fnmatch
testedwith = 'internal'
--- a/hgext/patchbomb.py Mon Oct 07 17:47:19 2013 -0400
+++ b/hgext/patchbomb.py Mon Oct 07 17:47:55 2013 -0400
@@ -46,8 +46,12 @@
'''
import os, errno, socket, tempfile, cStringIO
-import email.MIMEMultipart, email.MIMEBase
-import email.Utils, email.Encoders, email.Generator
+import email
+# On python2.4 you have to import these by name or they fail to
+# load. This was not a problem on Python 2.7.
+import email.Generator
+import email.MIMEMultipart
+
from mercurial import cmdutil, commands, hg, mail, patch, util
from mercurial import scmutil
from mercurial.i18n import _
--- a/hgext/progress.py Mon Oct 07 17:47:19 2013 -0400
+++ b/hgext/progress.py Mon Oct 07 17:47:55 2013 -0400
@@ -239,6 +239,13 @@
# this one are also closed
if topic in self.topics:
self.topics = self.topics[:self.topics.index(topic)]
+ # reset the last topic to the one we just unwound to,
+ # so that higher-level topics will be stickier than
+ # lower-level topics
+ if self.topics:
+ self.lasttopic = self.topics[-1]
+ else:
+ self.lasttopic = None
else:
if topic not in self.topics:
self.starttimes[topic] = now
--- a/hgext/rebase.py Mon Oct 07 17:47:19 2013 -0400
+++ b/hgext/rebase.py Mon Oct 07 17:47:55 2013 -0400
@@ -29,6 +29,25 @@
command = cmdutil.command(cmdtable)
testedwith = 'internal'
+def _savegraft(ctx, extra):
+ s = ctx.extra().get('source', None)
+ if s is not None:
+ extra['source'] = s
+
+def _savebranch(ctx, extra):
+ extra['branch'] = ctx.branch()
+
+def _makeextrafn(copiers):
+ """make an extrafn out of the given copy-functions.
+
+ A copy function takes a context and an extra dict, and mutates the
+ extra dict as needed based on the given context.
+ """
+ def extrafn(ctx, extra):
+ for c in copiers:
+ c(ctx, extra)
+ return extrafn
+
@command('rebase',
[('s', 'source', '',
_('rebase from the specified changeset'), _('REV')),
@@ -136,7 +155,10 @@
abortf = opts.get('abort')
collapsef = opts.get('collapse', False)
collapsemsg = cmdutil.logmessage(ui, opts)
- extrafn = opts.get('extrafn') # internal, used by e.g. hgsubversion
+ e = opts.get('extrafn') # internal, used by e.g. hgsubversion
+ extrafns = [_savegraft]
+ if e:
+ extrafns = [e]
keepf = opts.get('keep', False)
keepbranchesf = opts.get('keepbranches', False)
# keepopen is not meant for use on the command line, but by
@@ -240,9 +262,10 @@
external = checkexternal(repo, state, targetancestors)
if keepbranchesf:
- assert not extrafn, 'cannot use both keepbranches and extrafn'
- def extrafn(ctx, extra):
- extra['branch'] = ctx.branch()
+ # insert _savebranch at the start of extrafns so if
+ # there's a user-provided extrafn it can clobber branch if
+ # desired
+ extrafns.insert(0, _savebranch)
if collapsef:
branches = set()
for rev in state:
@@ -262,6 +285,8 @@
if activebookmark:
bookmarks.unsetcurrent(repo)
+ extrafn = _makeextrafn(extrafns)
+
sortedstate = sorted(state)
total = len(sortedstate)
pos = 0
@@ -780,7 +805,6 @@
'the update flag\n')
movemarkfrom = repo['.'].node()
- cmdutil.bailifchanged(repo)
revsprepull = len(repo)
origpostincoming = commands.postincoming
def _dummy(*args, **kwargs):
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hgext/shelve.py Mon Oct 07 17:47:55 2013 -0400
@@ -0,0 +1,615 @@
+# shelve.py - save/restore working directory state
+#
+# Copyright 2013 Facebook, Inc.
+#
+# This software may be used and distributed according to the terms of the
+# GNU General Public License version 2 or any later version.
+
+"""save and restore changes to the working directory
+
+The "hg shelve" command saves changes made to the working directory
+and reverts those changes, resetting the working directory to a clean
+state.
+
+Later on, the "hg unshelve" command restores the changes saved by "hg
+shelve". Changes can be restored even after updating to a different
+parent, in which case Mercurial's merge machinery will resolve any
+conflicts if necessary.
+
+You can have more than one shelved change outstanding at a time; each
+shelved change has a distinct name. For details, see the help for "hg
+shelve".
+"""
+
+try:
+ import cPickle as pickle
+ pickle.dump # import now
+except ImportError:
+ import pickle
+from mercurial.i18n import _
+from mercurial.node import nullid
+from mercurial import changegroup, cmdutil, scmutil, phases
+from mercurial import error, hg, mdiff, merge, patch, repair, util
+from mercurial import templatefilters
+from mercurial import lock as lockmod
+import errno
+
+cmdtable = {}
+command = cmdutil.command(cmdtable)
+testedwith = 'internal'
+
+class shelvedfile(object):
+ """Handles common functions on shelve files (.hg/.files/.patch) using
+ the vfs layer"""
+ def __init__(self, repo, name, filetype=None):
+ self.repo = repo
+ self.name = name
+ self.vfs = scmutil.vfs(repo.join('shelved'))
+ if filetype:
+ self.fname = name + '.' + filetype
+ else:
+ self.fname = name
+
+ def exists(self):
+ return self.vfs.exists(self.fname)
+
+ def filename(self):
+ return self.vfs.join(self.fname)
+
+ def unlink(self):
+ util.unlink(self.filename())
+
+ def stat(self):
+ return self.vfs.stat(self.fname)
+
+ def opener(self, mode='rb'):
+ try:
+ return self.vfs(self.fname, mode)
+ except IOError, err:
+ if err.errno != errno.ENOENT:
+ raise
+ if mode[0] in 'wa':
+ try:
+ self.vfs.mkdir()
+ return self.vfs(self.fname, mode)
+ except IOError, err:
+ if err.errno != errno.EEXIST:
+ raise
+ elif mode[0] == 'r':
+ raise util.Abort(_("shelved change '%s' not found") %
+ self.name)
+
+class shelvedstate(object):
+ """Handles saving and restoring a shelved state. Ensures that different
+ versions of a shelved state are possible and handles them appropriate"""
+ _version = 1
+ _filename = 'shelvedstate'
+
+ @classmethod
+ def load(cls, repo):
+ fp = repo.opener(cls._filename)
+ (version, name, parents, stripnodes) = pickle.load(fp)
+
+ if version != cls._version:
+ raise util.Abort(_('this version of shelve is incompatible '
+ 'with the version used in this repo'))
+
+ obj = cls()
+ obj.name = name
+ obj.parents = parents
+ obj.stripnodes = stripnodes
+
+ return obj
+
+ @classmethod
+ def save(cls, repo, name, stripnodes):
+ fp = repo.opener(cls._filename, 'wb')
+ pickle.dump((cls._version, name,
+ repo.dirstate.parents(),
+ stripnodes), fp)
+ fp.close()
+
+ @staticmethod
+ def clear(repo):
+ util.unlinkpath(repo.join('shelvedstate'), ignoremissing=True)
+
+def createcmd(ui, repo, pats, opts):
+ def publicancestors(ctx):
+ """Compute the heads of the public ancestors of a commit.
+
+ Much faster than the revset heads(ancestors(ctx) - draft())"""
+ seen = set()
+ visit = util.deque()
+ visit.append(ctx)
+ while visit:
+ ctx = visit.popleft()
+ for parent in ctx.parents():
+ rev = parent.rev()
+ if rev not in seen:
+ seen.add(rev)
+ if parent.mutable():
+ visit.append(parent)
+ else:
+ yield parent.node()
+
+ wctx = repo[None]
+ parents = wctx.parents()
+ if len(parents) > 1:
+ raise util.Abort(_('cannot shelve while merging'))
+ parent = parents[0]
+
+ # we never need the user, so we use a generic user for all shelve operations
+ user = 'shelve@localhost'
+ label = repo._bookmarkcurrent or parent.branch() or 'default'
+
+ # slashes aren't allowed in filenames, therefore we rename it
+ origlabel, label = label, label.replace('/', '_')
+
+ def gennames():
+ yield label
+ for i in xrange(1, 100):
+ yield '%s-%02d' % (label, i)
+
+ shelvedfiles = []
+
+ def commitfunc(ui, repo, message, match, opts):
+ # check modified, added, removed, deleted only
+ for flist in repo.status(match=match)[:4]:
+ shelvedfiles.extend(flist)
+ saved, repo.mq.checkapplied = repo.mq.checkapplied, False
+ try:
+ return repo.commit(message, user, opts.get('date'), match)
+ finally:
+ repo.mq.checkapplied = saved
+
+ if parent.node() != nullid:
+ desc = parent.description().split('\n', 1)[0]
+ else:
+ desc = '(empty repository)'
+
+ if not opts['message']:
+ opts['message'] = desc
+
+ name = opts['name']
+
+ wlock = lock = tr = bms = None
+ try:
+ wlock = repo.wlock()
+ lock = repo.lock()
+
+ bms = repo._bookmarks.copy()
+ # use an uncommited transaction to generate the bundle to avoid
+ # pull races. ensure we don't print the abort message to stderr.
+ tr = repo.transaction('commit', report=lambda x: None)
+
+ if name:
+ if shelvedfile(repo, name, 'hg').exists():
+ raise util.Abort(_("a shelved change named '%s' already exists")
+ % name)
+ else:
+ for n in gennames():
+ if not shelvedfile(repo, n, 'hg').exists():
+ name = n
+ break
+ else:
+ raise util.Abort(_("too many shelved changes named '%s'") %
+ label)
+
+ # ensure we are not creating a subdirectory or a hidden file
+ if '/' in name or '\\' in name:
+ raise util.Abort(_('shelved change names may not contain slashes'))
+ if name.startswith('.'):
+ raise util.Abort(_("shelved change names may not start with '.'"))
+
+ node = cmdutil.commit(ui, repo, commitfunc, pats, opts)
+
+ if not node:
+ stat = repo.status(match=scmutil.match(repo[None], pats, opts))
+ if stat[3]:
+ ui.status(_("nothing changed (%d missing files, see "
+ "'hg status')\n") % len(stat[3]))
+ else:
+ 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))
+
+ bases = list(publicancestors(repo[node]))
+ cg = repo.changegroupsubset(bases, [node], 'shelve')
+ changegroup.writebundle(cg, shelvedfile(repo, name, 'hg').filename(),
+ 'HG10UN')
+ cmdutil.export(repo, [node],
+ fp=shelvedfile(repo, name, 'patch').opener('wb'),
+ opts=mdiff.diffopts(git=True))
+
+
+ if ui.formatted():
+ desc = util.ellipsis(desc, ui.termwidth())
+ ui.status(_('shelved as %s\n') % name)
+ hg.update(repo, parent.node())
+ finally:
+ if bms:
+ # restore old bookmarks
+ repo._bookmarks.update(bms)
+ repo._bookmarks.write()
+ if tr:
+ tr.abort()
+ lockmod.release(lock, wlock)
+
+def cleanupcmd(ui, repo):
+ wlock = None
+ try:
+ wlock = repo.wlock()
+ for (name, _) in repo.vfs.readdir('shelved'):
+ suffix = name.rsplit('.', 1)[-1]
+ if suffix in ('hg', 'files', 'patch'):
+ shelvedfile(repo, name).unlink()
+ finally:
+ lockmod.release(wlock)
+
+def deletecmd(ui, repo, pats):
+ if not pats:
+ raise util.Abort(_('no shelved changes specified!'))
+ wlock = None
+ try:
+ wlock = repo.wlock()
+ try:
+ for name in pats:
+ for suffix in 'hg files patch'.split():
+ shelvedfile(repo, name, suffix).unlink()
+ except OSError, err:
+ if err.errno != errno.ENOENT:
+ raise
+ raise util.Abort(_("shelved change '%s' not found") % name)
+ finally:
+ lockmod.release(wlock)
+
+def listshelves(repo):
+ try:
+ names = repo.vfs.readdir('shelved')
+ except OSError, err:
+ if err.errno != errno.ENOENT:
+ raise
+ return []
+ info = []
+ for (name, _) in names:
+ pfx, sfx = name.rsplit('.', 1)
+ if not pfx or sfx != 'patch':
+ continue
+ st = shelvedfile(repo, name).stat()
+ info.append((st.st_mtime, shelvedfile(repo, pfx).filename()))
+ return sorted(info, reverse=True)
+
+def listcmd(ui, repo, pats, opts):
+ pats = set(pats)
+ width = 80
+ if not ui.plain():
+ width = ui.termwidth()
+ namelabel = 'shelve.newest'
+ for mtime, name in listshelves(repo):
+ sname = util.split(name)[1]
+ if pats and sname not in pats:
+ continue
+ ui.write(sname, label=namelabel)
+ namelabel = 'shelve.name'
+ if ui.quiet:
+ ui.write('\n')
+ continue
+ ui.write(' ' * (16 - len(sname)))
+ used = 16
+ age = '(%s)' % templatefilters.age(util.makedate(mtime), abbrev=True)
+ ui.write(age, label='shelve.age')
+ ui.write(' ' * (12 - len(age)))
+ used += 12
+ fp = open(name + '.patch', 'rb')
+ try:
+ while True:
+ line = fp.readline()
+ if not line:
+ break
+ if not line.startswith('#'):
+ desc = line.rstrip()
+ if ui.formatted():
+ desc = util.ellipsis(desc, width - used)
+ ui.write(desc)
+ break
+ ui.write('\n')
+ if not (opts['patch'] or opts['stat']):
+ continue
+ difflines = fp.readlines()
+ if opts['patch']:
+ for chunk, label in patch.difflabel(iter, difflines):
+ ui.write(chunk, label=label)
+ if opts['stat']:
+ for chunk, label in patch.diffstatui(difflines, width=width,
+ git=True):
+ ui.write(chunk, label=label)
+ finally:
+ fp.close()
+
+def readshelvedfiles(repo, basename):
+ fp = shelvedfile(repo, basename, 'files').opener()
+ return fp.read().split('\0')
+
+def checkparents(repo, state):
+ if state.parents != repo.dirstate.parents():
+ raise util.Abort(_('working directory parents do not match unshelve '
+ 'state'))
+
+def unshelveabort(ui, repo, state, opts):
+ wlock = repo.wlock()
+ lock = None
+ try:
+ checkparents(repo, state)
+ lock = repo.lock()
+ merge.mergestate(repo).reset()
+ if opts['keep']:
+ repo.setparents(repo.dirstate.parents()[0])
+ else:
+ revertfiles = readshelvedfiles(repo, state.name)
+ wctx = repo.parents()[0]
+ cmdutil.revert(ui, repo, wctx, [wctx.node(), nullid],
+ *revertfiles, no_backup=True)
+ # fix up the weird dirstate states the merge left behind
+ mf = wctx.manifest()
+ dirstate = repo.dirstate
+ for f in revertfiles:
+ if f in mf:
+ dirstate.normallookup(f)
+ else:
+ dirstate.drop(f)
+ dirstate._pl = (wctx.node(), nullid)
+ dirstate._dirty = True
+ repair.strip(ui, repo, state.stripnodes, backup='none', topic='shelve')
+ shelvedstate.clear(repo)
+ ui.warn(_("unshelve of '%s' aborted\n") % state.name)
+ finally:
+ lockmod.release(lock, wlock)
+
+def unshelvecleanup(ui, repo, name, opts):
+ if not opts['keep']:
+ for filetype in 'hg files patch'.split():
+ shelvedfile(repo, name, filetype).unlink()
+
+def finishmerge(ui, repo, ms, stripnodes, name, opts):
+ # Reset the working dir so it's no longer in a merge state.
+ dirstate = repo.dirstate
+ for f in ms:
+ if dirstate[f] == 'm':
+ dirstate.normallookup(f)
+ dirstate._pl = (dirstate._pl[0], nullid)
+ dirstate._dirty = dirstate._dirtypl = True
+ shelvedstate.clear(repo)
+
+def unshelvecontinue(ui, repo, state, opts):
+ # We're finishing off a merge. First parent is our original
+ # parent, second is the temporary "fake" commit we're unshelving.
+ wlock = repo.wlock()
+ lock = None
+ try:
+ checkparents(repo, state)
+ ms = merge.mergestate(repo)
+ if [f for f in ms if ms[f] == 'u']:
+ raise util.Abort(
+ _("unresolved conflicts, can't continue"),
+ hint=_("see 'hg resolve', then 'hg unshelve --continue'"))
+ finishmerge(ui, repo, ms, state.stripnodes, state.name, opts)
+ lock = repo.lock()
+ repair.strip(ui, repo, state.stripnodes, backup='none', topic='shelve')
+ unshelvecleanup(ui, repo, state.name, opts)
+ ui.status(_("unshelve of '%s' complete\n") % state.name)
+ finally:
+ lockmod.release(lock, wlock)
+
+@command('unshelve',
+ [('a', 'abort', None,
+ _('abort an incomplete unshelve operation')),
+ ('c', 'continue', None,
+ _('continue an incomplete unshelve operation')),
+ ('', 'keep', None,
+ _('keep shelve after unshelving'))],
+ _('hg unshelve [SHELVED]'))
+def unshelve(ui, repo, *shelved, **opts):
+ """restore a shelved change to the working directory
+
+ This command accepts an optional name of a shelved change to
+ restore. If none is given, the most recent shelved change is used.
+
+ If a shelved change is applied successfully, the bundle that
+ contains the shelved changes is deleted afterwards.
+
+ Since you can restore a shelved change on top of an arbitrary
+ commit, it is possible that unshelving will result in a conflict
+ between your changes and the commits you are unshelving onto. If
+ this occurs, you must resolve the conflict, then use
+ ``--continue`` to complete the unshelve operation. (The bundle
+ will not be deleted until you successfully complete the unshelve.)
+
+ (Alternatively, you can use ``--abort`` to abandon an unshelve
+ that causes a conflict. This reverts the unshelved changes, and
+ does not delete the bundle.)
+ """
+ abortf = opts['abort']
+ continuef = opts['continue']
+ if not abortf and not continuef:
+ cmdutil.checkunfinished(repo)
+
+ if abortf or continuef:
+ if abortf and continuef:
+ raise util.Abort(_('cannot use both abort and continue'))
+ if shelved:
+ raise util.Abort(_('cannot combine abort/continue with '
+ 'naming a shelved change'))
+
+ try:
+ state = shelvedstate.load(repo)
+ except IOError, err:
+ if err.errno != errno.ENOENT:
+ raise
+ raise util.Abort(_('no unshelve operation underway'))
+
+ if abortf:
+ return unshelveabort(ui, repo, state, opts)
+ elif continuef:
+ return unshelvecontinue(ui, repo, state, opts)
+ elif len(shelved) > 1:
+ raise util.Abort(_('can only unshelve one change at a time'))
+ elif not shelved:
+ shelved = listshelves(repo)
+ if not shelved:
+ raise util.Abort(_('no shelved changes to apply!'))
+ basename = util.split(shelved[0][1])[1]
+ ui.status(_("unshelving change '%s'\n") % basename)
+ else:
+ basename = shelved[0]
+
+ shelvedfiles = readshelvedfiles(repo, basename)
+
+ m, a, r, d = repo.status()[:4]
+ unsafe = set(m + a + r + d).intersection(shelvedfiles)
+ if unsafe:
+ ui.warn(_('the following shelved files have been modified:\n'))
+ for f in sorted(unsafe):
+ ui.warn(' %s\n' % f)
+ ui.warn(_('you must commit, revert, or shelve your changes before you '
+ 'can proceed\n'))
+ raise util.Abort(_('cannot unshelve due to local changes\n'))
+
+ wlock = lock = tr = None
+ try:
+ lock = repo.lock()
+
+ tr = repo.transaction('unshelve', report=lambda x: None)
+ oldtiprev = len(repo)
+ try:
+ fp = shelvedfile(repo, basename, 'hg').opener()
+ gen = changegroup.readbundle(fp, fp.name)
+ repo.addchangegroup(gen, 'unshelve', 'bundle:' + fp.name)
+ nodes = [ctx.node() for ctx in repo.set('%d:', oldtiprev)]
+ phases.retractboundary(repo, phases.secret, nodes)
+ tr.close()
+ finally:
+ fp.close()
+
+ tip = repo['tip']
+ wctx = repo['.']
+ ancestor = tip.ancestor(wctx)
+
+ wlock = repo.wlock()
+
+ if ancestor.node() != wctx.node():
+ conflicts = hg.merge(repo, tip.node(), force=True, remind=False)
+ ms = merge.mergestate(repo)
+ stripnodes = [repo.changelog.node(rev)
+ for rev in xrange(oldtiprev, len(repo))]
+ if conflicts:
+ shelvedstate.save(repo, basename, stripnodes)
+ # Fix up the dirstate entries of files from the second
+ # parent as if we were not merging, except for those
+ # with unresolved conflicts.
+ parents = repo.parents()
+ revertfiles = set(parents[1].files()).difference(ms)
+ cmdutil.revert(ui, repo, parents[1],
+ (parents[0].node(), nullid),
+ *revertfiles, no_backup=True)
+ raise error.InterventionRequired(
+ _("unresolved conflicts (see 'hg resolve', then "
+ "'hg unshelve --continue')"))
+ finishmerge(ui, repo, ms, stripnodes, basename, opts)
+ else:
+ parent = tip.parents()[0]
+ hg.update(repo, parent.node())
+ cmdutil.revert(ui, repo, tip, repo.dirstate.parents(), *tip.files(),
+ no_backup=True)
+
+ prevquiet = ui.quiet
+ ui.quiet = True
+ try:
+ repo.rollback(force=True)
+ finally:
+ ui.quiet = prevquiet
+
+ unshelvecleanup(ui, repo, basename, opts)
+ finally:
+ if tr:
+ tr.release()
+ lockmod.release(lock, wlock)
+
+@command('shelve',
+ [('A', 'addremove', None,
+ _('mark new/missing files as added/removed before shelving')),
+ ('', 'cleanup', None,
+ _('delete all shelved changes')),
+ ('', 'date', '',
+ _('shelve with the specified commit date'), _('DATE')),
+ ('d', 'delete', None,
+ _('delete the named shelved change(s)')),
+ ('l', 'list', None,
+ _('list current shelves')),
+ ('m', 'message', '',
+ _('use text as shelve message'), _('TEXT')),
+ ('n', 'name', '',
+ _('use the given name for the shelved commit'), _('NAME')),
+ ('p', 'patch', None,
+ _('show patch')),
+ ('', 'stat', None,
+ _('output diffstat-style summary of changes'))],
+ _('hg shelve'))
+def shelvecmd(ui, repo, *pats, **opts):
+ '''save and set aside changes from the working directory
+
+ Shelving takes files that "hg status" reports as not clean, saves
+ the modifications to a bundle (a shelved change), and reverts the
+ files so that their state in the working directory becomes clean.
+
+ To restore these changes to the working directory, using "hg
+ unshelve"; this will work even if you switch to a different
+ commit.
+
+ When no files are specified, "hg shelve" saves all not-clean
+ files. If specific files or directories are named, only changes to
+ those files are shelved.
+
+ Each shelved change has a name that makes it easier to find later.
+ The name of a shelved change defaults to being based on the active
+ bookmark, or if there is no active bookmark, the current named
+ branch. To specify a different name, use ``--name``.
+
+ To see a list of existing shelved changes, use the ``--list``
+ option. For each shelved change, this will print its name, age,
+ and description; use ``--patch`` or ``--stat`` for more details.
+
+ To delete specific shelved changes, use ``--delete``. To delete
+ all shelved changes, use ``--cleanup``.
+ '''
+ cmdutil.checkunfinished(repo)
+
+ def checkopt(opt, incompatible):
+ if opts[opt]:
+ for i in incompatible.split():
+ if opts[i]:
+ raise util.Abort(_("options '--%s' and '--%s' may not be "
+ "used together") % (opt, i))
+ return True
+ if checkopt('cleanup', 'addremove delete list message name patch stat'):
+ if pats:
+ raise util.Abort(_("cannot specify names when using '--cleanup'"))
+ return cleanupcmd(ui, repo)
+ elif checkopt('delete', 'addremove cleanup list message name patch stat'):
+ return deletecmd(ui, repo, pats)
+ elif checkopt('list', 'addremove cleanup delete message name'):
+ return listcmd(ui, repo, pats, opts)
+ else:
+ for i in ('patch', 'stat'):
+ if opts[i]:
+ raise util.Abort(_("option '--%s' may not be "
+ "used when shelving a change") % (i,))
+ return createcmd(ui, repo, pats, opts)
+
+def extsetup(ui):
+ cmdutil.unfinishedstates.append(
+ [shelvedstate._filename, False, True, _('unshelve already in progress'),
+ _("use 'hg unshelve --continue' or 'hg unshelve --abort'")])
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hgext/strip.py Mon Oct 07 17:47:55 2013 -0400
@@ -0,0 +1,217 @@
+"""strip changesets and their descendents from history
+
+This extension allows to strip changesets and all their descendants from the
+repository. See the command help for details.
+"""
+from mercurial.i18n import _
+from mercurial.node import nullid
+from mercurial.lock import release
+from mercurial import cmdutil, hg, scmutil, util
+from mercurial import repair, bookmarks
+
+cmdtable = {}
+command = cmdutil.command(cmdtable)
+testedwith = 'internal'
+
+def checksubstate(repo, baserev=None):
+ '''return list of subrepos at a different revision than substate.
+ Abort if any subrepos have uncommitted changes.'''
+ inclsubs = []
+ wctx = repo[None]
+ if baserev:
+ bctx = repo[baserev]
+ else:
+ bctx = wctx.parents()[0]
+ for s in sorted(wctx.substate):
+ if wctx.sub(s).dirty(True):
+ raise util.Abort(
+ _("uncommitted changes in subrepository %s") % s)
+ elif s not in bctx.substate or bctx.sub(s).dirty():
+ inclsubs.append(s)
+ return inclsubs
+
+def checklocalchanges(repo, force=False, excsuffix=''):
+ cmdutil.checkunfinished(repo)
+ m, a, r, d = repo.status()[:4]
+ if not force:
+ if (m or a or r or d):
+ _("local changes found") # i18n tool detection
+ raise util.Abort(_("local changes found" + excsuffix))
+ if checksubstate(repo):
+ _("local changed subrepos found") # i18n tool detection
+ raise util.Abort(_("local changed subrepos found" + excsuffix))
+ return m, a, r, d
+
+def strip(ui, repo, revs, update=True, backup="all", force=None):
+ wlock = lock = None
+ try:
+ wlock = repo.wlock()
+ lock = repo.lock()
+
+ if update:
+ checklocalchanges(repo, force=force)
+ urev, p2 = repo.changelog.parents(revs[0])
+ if p2 != nullid and p2 in [x.node for x in repo.mq.applied]:
+ urev = p2
+ hg.clean(repo, urev)
+ repo.dirstate.write()
+
+ repair.strip(ui, repo, revs, backup)
+ finally:
+ release(lock, wlock)
+
+
+@command("strip",
+ [
+ ('r', 'rev', [], _('strip specified revision (optional, '
+ 'can specify revisions without this '
+ 'option)'), _('REV')),
+ ('f', 'force', None, _('force removal of changesets, discard '
+ 'uncommitted changes (no backup)')),
+ ('b', 'backup', None, _('bundle only changesets with local revision'
+ ' number greater than REV which are not'
+ ' descendants of REV (DEPRECATED)')),
+ ('', 'no-backup', None, _('no backups')),
+ ('', 'nobackup', None, _('no backups (DEPRECATED)')),
+ ('n', '', None, _('ignored (DEPRECATED)')),
+ ('k', 'keep', None, _("do not modify working copy during strip")),
+ ('B', 'bookmark', '', _("remove revs only reachable from given"
+ " bookmark"))],
+ _('hg strip [-k] [-f] [-n] [-B bookmark] [-r] REV...'))
+def stripcmd(ui, repo, *revs, **opts):
+ """strip changesets and all their descendants from the repository
+
+ The strip command removes the specified changesets and all their
+ descendants. If the working directory has uncommitted changes, the
+ operation is aborted unless the --force flag is supplied, in which
+ case changes will be discarded.
+
+ If a parent of the working directory is stripped, then the working
+ directory will automatically be updated to the most recent
+ available ancestor of the stripped parent after the operation
+ completes.
+
+ Any stripped changesets are stored in ``.hg/strip-backup`` as a
+ bundle (see :hg:`help bundle` and :hg:`help unbundle`). They can
+ be restored by running :hg:`unbundle .hg/strip-backup/BUNDLE`,
+ where BUNDLE is the bundle file created by the strip. Note that
+ the local revision numbers will in general be different after the
+ restore.
+
+ Use the --no-backup option to discard the backup bundle once the
+ operation completes.
+
+ Strip is not a history-rewriting operation and can be used on
+ changesets in the public phase. But if the stripped changesets have
+ been pushed to a remote repository you will likely pull them again.
+
+ Return 0 on success.
+ """
+ backup = 'all'
+ if opts.get('backup'):
+ backup = 'strip'
+ elif opts.get('no_backup') or opts.get('nobackup'):
+ backup = 'none'
+
+ cl = repo.changelog
+ revs = list(revs) + opts.get('rev')
+ revs = set(scmutil.revrange(repo, revs))
+
+ if opts.get('bookmark'):
+ mark = opts.get('bookmark')
+ marks = repo._bookmarks
+ if mark not in marks:
+ raise util.Abort(_("bookmark '%s' not found") % mark)
+
+ # If the requested bookmark is not the only one pointing to a
+ # a revision we have to only delete the bookmark and not strip
+ # anything. revsets cannot detect that case.
+ uniquebm = True
+ for m, n in marks.iteritems():
+ if m != mark and n == repo[mark].node():
+ uniquebm = False
+ break
+ if uniquebm:
+ rsrevs = repo.revs("ancestors(bookmark(%s)) - "
+ "ancestors(head() and not bookmark(%s)) - "
+ "ancestors(bookmark() and not bookmark(%s))",
+ mark, mark, mark)
+ revs.update(set(rsrevs))
+ if not revs:
+ del marks[mark]
+ marks.write()
+ ui.write(_("bookmark '%s' deleted\n") % mark)
+
+ if not revs:
+ raise util.Abort(_('empty revision set'))
+
+ descendants = set(cl.descendants(revs))
+ strippedrevs = revs.union(descendants)
+ roots = revs.difference(descendants)
+
+ update = False
+ # if one of the wdir parent is stripped we'll need
+ # to update away to an earlier revision
+ for p in repo.dirstate.parents():
+ if p != nullid and cl.rev(p) in strippedrevs:
+ update = True
+ break
+
+ rootnodes = set(cl.node(r) for r in roots)
+
+ q = getattr(repo, 'mq', None)
+ if q is not None and q.applied:
+ # refresh queue state if we're about to strip
+ # applied patches
+ if cl.rev(repo.lookup('qtip')) in strippedrevs:
+ q.applieddirty = True
+ start = 0
+ end = len(q.applied)
+ for i, statusentry in enumerate(q.applied):
+ if statusentry.node in rootnodes:
+ # if one of the stripped roots is an applied
+ # patch, only part of the queue is stripped
+ start = i
+ break
+ del q.applied[start:end]
+ q.savedirty()
+
+ revs = sorted(rootnodes)
+ if update and opts.get('keep'):
+ wlock = repo.wlock()
+ try:
+ urev, p2 = repo.changelog.parents(revs[0])
+ if (util.safehasattr(repo, 'mq') and p2 != nullid
+ and p2 in [x.node for x in repo.mq.applied]):
+ urev = p2
+ uctx = repo[urev]
+
+ # only reset the dirstate for files that would actually change
+ # between the working context and uctx
+ descendantrevs = repo.revs("%s::." % uctx.rev())
+ changedfiles = []
+ for rev in descendantrevs:
+ # blindly reset the files, regardless of what actually changed
+ changedfiles.extend(repo[rev].files())
+
+ # reset files that only changed in the dirstate too
+ dirstate = repo.dirstate
+ dirchanges = [f for f in dirstate if dirstate[f] != 'n']
+ changedfiles.extend(dirchanges)
+
+ repo.dirstate.rebuild(urev, uctx.manifest(), changedfiles)
+ repo.dirstate.write()
+ update = False
+ finally:
+ wlock.release()
+
+ if opts.get('bookmark'):
+ if mark == repo._bookmarkcurrent:
+ bookmarks.setcurrent(repo, None)
+ del marks[mark]
+ marks.write()
+ ui.write(_("bookmark '%s' deleted\n") % mark)
+
+ strip(ui, repo, revs, backup=backup, update=update, force=opts.get('force'))
+
+ return 0
--- a/mercurial/branchmap.py Mon Oct 07 17:47:19 2013 -0400
+++ b/mercurial/branchmap.py Mon Oct 07 17:47:55 2013 -0400
@@ -198,20 +198,7 @@
self.tipnode = cl.node(tiprev)
self.tiprev = tiprev
- # There may be branches that cease to exist when the last commit in the
- # branch was stripped. This code filters them out. Note that the
- # branch that ceased to exist may not be in newbranches because
- # newbranches is the set of candidate heads, which when you strip the
- # last commit in a branch will be the parent branch.
- droppednodes = []
- for branch in self.keys():
- nodes = [head for head in self[branch]
- if cl.hasnode(head)]
- if not nodes:
- droppednodes.extend(nodes)
- del self[branch]
- if ((not self.validfor(repo)) or (self.tipnode in droppednodes)):
-
+ if not self.validfor(repo):
# cache key are not valid anymore
self.tipnode = nullid
self.tiprev = nullrev
--- a/mercurial/bundlerepo.py Mon Oct 07 17:47:19 2013 -0400
+++ b/mercurial/bundlerepo.py Mon Oct 07 17:47:55 2013 -0400
@@ -120,7 +120,7 @@
chain.append(iterrev)
iterrev = self.index[iterrev][3]
if text is None:
- text = revlog.revlog.revision(self, iterrev)
+ text = self.baserevision(iterrev)
while chain:
delta = self._chunk(chain.pop())
@@ -130,6 +130,12 @@
self._cache = (node, rev, text)
return text
+ def baserevision(self, nodeorrev):
+ # Revlog subclasses may override 'revision' method to modify format of
+ # content retrieved from revlog. To use bundlerevlog with such class one
+ # needs to override 'baserevision' and make more specific call here.
+ return revlog.revlog.revision(self, nodeorrev)
+
def addrevision(self, text, transaction, link, p1=None, p2=None, d=None):
raise NotImplementedError
def addgroup(self, revs, linkmapper, transaction):
@@ -146,12 +152,21 @@
bundlerevlog.__init__(self, opener, self.indexfile, bundle,
linkmapper)
+ def baserevision(self, nodeorrev):
+ # Although changelog doesn't override 'revision' method, some extensions
+ # may replace this class with another that does. Same story with
+ # manifest and filelog classes.
+ return changelog.changelog.revision(self, nodeorrev)
+
class bundlemanifest(bundlerevlog, manifest.manifest):
def __init__(self, opener, bundle, linkmapper):
manifest.manifest.__init__(self, opener)
bundlerevlog.__init__(self, opener, self.indexfile, bundle,
linkmapper)
+ def baserevision(self, nodeorrev):
+ return manifest.manifest.revision(self, nodeorrev)
+
class bundlefilelog(bundlerevlog, filelog.filelog):
def __init__(self, opener, path, bundle, linkmapper, repo):
filelog.filelog.__init__(self, opener, path)
@@ -159,6 +174,9 @@
linkmapper)
self._repo = repo
+ def baserevision(self, nodeorrev):
+ return filelog.filelog.revision(self, nodeorrev)
+
def _file(self, f):
self._repo.file(f)
--- a/mercurial/cmdutil.py Mon Oct 07 17:47:19 2013 -0400
+++ b/mercurial/cmdutil.py Mon Oct 07 17:47:55 2013 -0400
@@ -84,7 +84,7 @@
raise util.Abort(_('outstanding uncommitted merge'))
modified, added, removed, deleted = repo.status()[:4]
if modified or added or removed or deleted:
- raise util.Abort(_("outstanding uncommitted changes"))
+ raise util.Abort(_('uncommitted changes'))
ctx = repo[None]
for s in sorted(ctx.substate):
if ctx.sub(s).dirty():
@@ -468,6 +468,13 @@
runargs=None, appendpid=False):
'''Run a command as a service.'''
+ def writepid(pid):
+ if opts['pid_file']:
+ mode = appendpid and 'a' or 'w'
+ fp = open(opts['pid_file'], mode)
+ fp.write(str(pid) + '\n')
+ fp.close()
+
if opts['daemon'] and not opts['daemon_pipefds']:
# Signal child process startup with file removal
lockfd, lockpath = tempfile.mkstemp(prefix='hg-service-')
@@ -490,6 +497,7 @@
pid = util.rundetached(runargs, condfn)
if pid < 0:
raise util.Abort(_('child process failed to start'))
+ writepid(pid)
finally:
try:
os.unlink(lockpath)
@@ -504,11 +512,8 @@
if initfn:
initfn()
- if opts['pid_file']:
- mode = appendpid and 'a' or 'w'
- fp = open(opts['pid_file'], mode)
- fp.write(str(os.getpid()) + '\n')
- fp.close()
+ if not opts['daemon']:
+ writepid(os.getpid())
if opts['daemon_pipefds']:
lockpath = opts['daemon_pipefds']
@@ -1172,12 +1177,34 @@
'filenames'))
# The slow path checks files modified in every changeset.
- for i in sorted(revs):
- ctx = change(i)
- matches = filter(match, ctx.files())
- if matches:
- fncache[i] = matches
- wanted.add(i)
+ # This is really slow on large repos, so compute the set lazily.
+ class lazywantedset(object):
+ def __init__(self):
+ self.set = set()
+ self.revs = set(revs)
+
+ # No need to worry about locality here because it will be accessed
+ # in the same order as the increasing window below.
+ def __contains__(self, value):
+ if value in self.set:
+ return True
+ elif not value in self.revs:
+ return False
+ else:
+ self.revs.discard(value)
+ ctx = change(value)
+ matches = filter(match, ctx.files())
+ if matches:
+ fncache[value] = matches
+ self.set.add(value)
+ return True
+ return False
+
+ def discard(self, value):
+ self.revs.discard(value)
+ self.set.discard(value)
+
+ wanted = lazywantedset()
class followfilter(object):
def __init__(self, onlyfirst=False):
--- a/mercurial/commands.py Mon Oct 07 17:47:19 2013 -0400
+++ b/mercurial/commands.py Mon Oct 07 17:47:55 2013 -0400
@@ -12,7 +12,8 @@
import hg, scmutil, util, revlog, copies, error, bookmarks
import patch, help, encoding, templatekw, discovery
import archival, changegroup, cmdutil, hbisect
-import sshserver, hgweb, hgweb.server, commandserver
+import sshserver, hgweb, commandserver
+from hgweb import server as hgweb_server
import merge as mergemod
import minirst, revset, fileset
import dagparser, context, simplemerge, graphmod
@@ -1807,7 +1808,7 @@
[('c', 'changelog', False, _('open changelog')),
('m', 'manifest', False, _('open manifest'))],
_('-c|-m|FILE REV'))
-def debugdata(ui, repo, file_, rev = None, **opts):
+def debugdata(ui, repo, file_, rev=None, **opts):
"""dump the contents of a data file revision"""
if opts.get('changelog') or opts.get('manifest'):
file_, rev = None, file_
@@ -1918,11 +1919,12 @@
ui.write("%s\n" % f)
@command('debugfsinfo', [], _('[PATH]'))
-def debugfsinfo(ui, path = "."):
+def debugfsinfo(ui, path="."):
"""show information detected about current filesystem"""
util.writefile('.debugfsinfo', '')
ui.write(('exec: %s\n') % (util.checkexec(path) and 'yes' or 'no'))
ui.write(('symlink: %s\n') % (util.checklink(path) and 'yes' or 'no'))
+ ui.write(('hardlink: %s\n') % (util.checknlink(path) and 'yes' or 'no'))
ui.write(('case-sensitive: %s\n') % (util.checkcase('.debugfsinfo')
and 'yes' or 'no'))
os.unlink('.debugfsinfo')
@@ -1972,7 +1974,7 @@
('m', 'manifest', False, _('open manifest')),
('f', 'format', 0, _('revlog format'), _('FORMAT'))],
_('[-f FORMAT] -c|-m|FILE'))
-def debugindex(ui, repo, file_ = None, **opts):
+def debugindex(ui, repo, file_=None, **opts):
"""dump the contents of an index file"""
r = cmdutil.openrevlog(repo, 'debugindex', file_, opts)
format = opts.get('format', 0)
@@ -2353,7 +2355,7 @@
('m', 'manifest', False, _('open manifest')),
('d', 'dump', False, _('dump index data'))],
_('-c|-m|FILE'))
-def debugrevlog(ui, repo, file_ = None, **opts):
+def debugrevlog(ui, repo, file_=None, **opts):
"""show data and statistics about a revlog"""
r = cmdutil.openrevlog(repo, 'debugrevlog', file_, opts)
@@ -4525,6 +4527,8 @@
ret = hg.update(repo, checkout)
except util.Abort, inst:
ui.warn(_("not updating: %s\n") % str(inst))
+ if inst.hint:
+ ui.warn(_("(%s)\n") % inst.hint)
return 0
if not ret and not checkout:
if bookmarks.update(repo, [movemarkfrom], repo['.'].node()):
@@ -5182,7 +5186,7 @@
class service(object):
def init(self):
util.setsignalhandler()
- self.httpd = hgweb.server.create_server(ui, app)
+ self.httpd = hgweb_server.create_server(ui, app)
if opts['port'] and not ui.verbose:
return
@@ -5846,7 +5850,7 @@
if check:
c = repo[None]
if c.dirty(merge=False, branch=False, missing=True):
- raise util.Abort(_("uncommitted local changes"))
+ raise util.Abort(_("uncommitted changes"))
if rev is None:
rev = repo[repo[None].branch()].rev()
mergemod._checkunknown(repo, repo[None], repo[rev])
--- a/mercurial/context.py Mon Oct 07 17:47:19 2013 -0400
+++ b/mercurial/context.py Mon Oct 07 17:47:55 2013 -0400
@@ -16,11 +16,197 @@
propertycache = util.propertycache
-class changectx(object):
+class basectx(object):
+ """A basectx object represents the common logic for its children:
+ changectx: read-only context that is already present in the repo,
+ workingctx: a context that represents the working directory and can
+ be committed,
+ memctx: a context that represents changes in-memory and can also
+ be committed."""
+ def __new__(cls, repo, changeid='', *args, **kwargs):
+ if isinstance(changeid, basectx):
+ return changeid
+
+ o = super(basectx, cls).__new__(cls)
+
+ o._repo = repo
+ o._rev = nullrev
+ o._node = nullid
+
+ return o
+
+ def __str__(self):
+ return short(self.node())
+
+ def __int__(self):
+ return self.rev()
+
+ def __repr__(self):
+ return "<%s %s>" % (type(self).__name__, str(self))
+
+ def __eq__(self, other):
+ try:
+ return type(self) == type(other) and self._rev == other._rev
+ except AttributeError:
+ return False
+
+ def __ne__(self, other):
+ return not (self == other)
+
+ def __contains__(self, key):
+ return key in self._manifest
+
+ def __getitem__(self, key):
+ return self.filectx(key)
+
+ def __iter__(self):
+ for f in sorted(self._manifest):
+ yield f
+
+ @propertycache
+ def substate(self):
+ return subrepo.state(self, self._repo.ui)
+
+ def rev(self):
+ return self._rev
+ def node(self):
+ return self._node
+ def hex(self):
+ return hex(self.node())
+ def manifest(self):
+ return self._manifest
+ def phasestr(self):
+ return phases.phasenames[self.phase()]
+ def mutable(self):
+ return self.phase() > phases.public
+
+ def obsolete(self):
+ """True if the changeset is obsolete"""
+ return self.rev() in obsmod.getrevs(self._repo, 'obsolete')
+
+ def extinct(self):
+ """True if the changeset is extinct"""
+ return self.rev() in obsmod.getrevs(self._repo, 'extinct')
+
+ def unstable(self):
+ """True if the changeset is not obsolete but it's ancestor are"""
+ return self.rev() in obsmod.getrevs(self._repo, 'unstable')
+
+ def bumped(self):
+ """True if the changeset try to be a successor of a public changeset
+
+ Only non-public and non-obsolete changesets may be bumped.
+ """
+ return self.rev() in obsmod.getrevs(self._repo, 'bumped')
+
+ def divergent(self):
+ """Is a successors of a changeset with multiple possible successors set
+
+ Only non-public and non-obsolete changesets may be divergent.
+ """
+ return self.rev() in obsmod.getrevs(self._repo, 'divergent')
+
+ def troubled(self):
+ """True if the changeset is either unstable, bumped or divergent"""
+ return self.unstable() or self.bumped() or self.divergent()
+
+ def troubles(self):
+ """return the list of troubles affecting this changesets.
+
+ Troubles are returned as strings. possible values are:
+ - unstable,
+ - bumped,
+ - divergent.
+ """
+ troubles = []
+ if self.unstable():
+ troubles.append('unstable')
+ if self.bumped():
+ troubles.append('bumped')
+ if self.divergent():
+ troubles.append('divergent')
+ return troubles
+
+ def parents(self):
+ """return contexts for each parent changeset"""
+ return self._parents
+
+ def p1(self):
+ return self._parents[0]
+
+ def p2(self):
+ if len(self._parents) == 2:
+ return self._parents[1]
+ return changectx(self._repo, -1)
+
+ def _fileinfo(self, path):
+ if '_manifest' in self.__dict__:
+ try:
+ return self._manifest[path], self._manifest.flags(path)
+ except KeyError:
+ raise error.ManifestLookupError(self._node, path,
+ _('not found in manifest'))
+ if '_manifestdelta' in self.__dict__ or path in self.files():
+ if path in self._manifestdelta:
+ return (self._manifestdelta[path],
+ self._manifestdelta.flags(path))
+ node, flag = self._repo.manifest.find(self._changeset[0], path)
+ if not node:
+ raise error.ManifestLookupError(self._node, path,
+ _('not found in manifest'))
+
+ return node, flag
+
+ def filenode(self, path):
+ return self._fileinfo(path)[0]
+
+ def flags(self, path):
+ try:
+ return self._fileinfo(path)[1]
+ except error.LookupError:
+ return ''
+
+ def sub(self, path):
+ return subrepo.subrepo(self, path)
+
+ def match(self, pats=[], include=None, exclude=None, default='glob'):
+ r = self._repo
+ return matchmod.match(r.root, r.getcwd(), pats,
+ include, exclude, default,
+ auditor=r.auditor, ctx=self)
+
+ def diff(self, ctx2=None, match=None, **opts):
+ """Returns a diff generator for the given contexts and matcher"""
+ if ctx2 is None:
+ ctx2 = self.p1()
+ if ctx2 is not None:
+ ctx2 = self._repo[ctx2]
+ diffopts = patch.diffopts(self._repo.ui, opts)
+ return patch.diff(self._repo, ctx2.node(), self.node(),
+ match=match, opts=diffopts)
+
+ @propertycache
+ def _dirs(self):
+ return scmutil.dirs(self._manifest)
+
+ def dirs(self):
+ return self._dirs
+
+ def dirty(self):
+ return False
+
+class changectx(basectx):
"""A changecontext object makes access to data related to a particular
- changeset convenient."""
+ changeset convenient. It represents a read-only context already presnt in
+ the repo."""
def __init__(self, repo, changeid=''):
"""changeid is a revision number, node, or tag"""
+
+ # since basectx.__new__ already took care of copying the object, we
+ # don't need to do anything in __init__, so we just exit here
+ if isinstance(changeid, basectx):
+ return
+
if changeid == '':
changeid = '.'
self._repo = repo
@@ -114,30 +300,12 @@
raise error.RepoLookupError(
_("unknown revision '%s'") % changeid)
- def __str__(self):
- return short(self.node())
-
- def __int__(self):
- return self.rev()
-
- def __repr__(self):
- return "<changectx %s>" % str(self)
-
def __hash__(self):
try:
return hash(self._rev)
except AttributeError:
return id(self)
- def __eq__(self, other):
- try:
- return self._rev == other._rev
- except AttributeError:
- return False
-
- def __ne__(self, other):
- return not (self == other)
-
def __nonzero__(self):
return self._rev != nullrev
@@ -160,33 +328,11 @@
p = p[:-1]
return [changectx(self._repo, x) for x in p]
- @propertycache
- def substate(self):
- return subrepo.state(self, self._repo.ui)
-
- def __contains__(self, key):
- return key in self._manifest
-
- def __getitem__(self, key):
- return self.filectx(key)
-
- def __iter__(self):
- for f in sorted(self._manifest):
- yield f
-
def changeset(self):
return self._changeset
- def manifest(self):
- return self._manifest
def manifestnode(self):
return self._changeset[0]
- def rev(self):
- return self._rev
- def node(self):
- return self._node
- def hex(self):
- return hex(self._node)
def user(self):
return self._changeset[1]
def date(self):
@@ -207,25 +353,9 @@
return self._repo.nodebookmarks(self._node)
def phase(self):
return self._repo._phasecache.phase(self._repo, self._rev)
- def phasestr(self):
- return phases.phasenames[self.phase()]
- def mutable(self):
- return self.phase() > phases.public
def hidden(self):
return self._rev in repoview.filterrevs(self._repo, 'visible')
- def parents(self):
- """return contexts for each parent changeset"""
- return self._parents
-
- def p1(self):
- return self._parents[0]
-
- def p2(self):
- if len(self._parents) == 2:
- return self._parents[1]
- return changectx(self._repo, -1)
-
def children(self):
"""return contexts for each child changeset"""
c = self._repo.changelog.children(self._node)
@@ -239,80 +369,6 @@
for d in self._repo.changelog.descendants([self._rev]):
yield changectx(self._repo, d)
- def obsolete(self):
- """True if the changeset is obsolete"""
- return self.rev() in obsmod.getrevs(self._repo, 'obsolete')
-
- def extinct(self):
- """True if the changeset is extinct"""
- return self.rev() in obsmod.getrevs(self._repo, 'extinct')
-
- def unstable(self):
- """True if the changeset is not obsolete but it's ancestor are"""
- return self.rev() in obsmod.getrevs(self._repo, 'unstable')
-
- def bumped(self):
- """True if the changeset try to be a successor of a public changeset
-
- Only non-public and non-obsolete changesets may be bumped.
- """
- return self.rev() in obsmod.getrevs(self._repo, 'bumped')
-
- def divergent(self):
- """Is a successors of a changeset with multiple possible successors set
-
- Only non-public and non-obsolete changesets may be divergent.
- """
- return self.rev() in obsmod.getrevs(self._repo, 'divergent')
-
- def troubled(self):
- """True if the changeset is either unstable, bumped or divergent"""
- return self.unstable() or self.bumped() or self.divergent()
-
- def troubles(self):
- """return the list of troubles affecting this changesets.
-
- Troubles are returned as strings. possible values are:
- - unstable,
- - bumped,
- - divergent.
- """
- troubles = []
- if self.unstable():
- troubles.append('unstable')
- if self.bumped():
- troubles.append('bumped')
- if self.divergent():
- troubles.append('divergent')
- return troubles
-
- def _fileinfo(self, path):
- if '_manifest' in self.__dict__:
- try:
- return self._manifest[path], self._manifest.flags(path)
- except KeyError:
- raise error.ManifestLookupError(self._node, path,
- _('not found in manifest'))
- if '_manifestdelta' in self.__dict__ or path in self.files():
- if path in self._manifestdelta:
- return (self._manifestdelta[path],
- self._manifestdelta.flags(path))
- node, flag = self._repo.manifest.find(self._changeset[0], path)
- if not node:
- raise error.ManifestLookupError(self._node, path,
- _('not found in manifest'))
-
- return node, flag
-
- def filenode(self, path):
- return self._fileinfo(path)[0]
-
- def flags(self, path):
- try:
- return self._fileinfo(path)[1]
- except error.LookupError:
- return ''
-
def filectx(self, path, fileid=None, filelog=None):
"""get a file context from this changeset"""
if fileid is None:
@@ -353,83 +409,15 @@
if match.bad(fn, _('no such file in rev %s') % self) and match(fn):
yield fn
- def sub(self, path):
- return subrepo.subrepo(self, path)
-
- def match(self, pats=[], include=None, exclude=None, default='glob'):
- r = self._repo
- return matchmod.match(r.root, r.getcwd(), pats,
- include, exclude, default,
- auditor=r.auditor, ctx=self)
-
- def diff(self, ctx2=None, match=None, **opts):
- """Returns a diff generator for the given contexts and matcher"""
- if ctx2 is None:
- ctx2 = self.p1()
- if ctx2 is not None and not isinstance(ctx2, changectx):
- ctx2 = self._repo[ctx2]
- diffopts = patch.diffopts(self._repo.ui, opts)
- return patch.diff(self._repo, ctx2.node(), self.node(),
- match=match, opts=diffopts)
-
- @propertycache
- def _dirs(self):
- return scmutil.dirs(self._manifest)
-
- def dirs(self):
- return self._dirs
-
- def dirty(self):
- return False
-
-class filectx(object):
- """A filecontext object makes access to data related to a particular
- filerevision convenient."""
- def __init__(self, repo, path, changeid=None, fileid=None,
- filelog=None, changectx=None):
- """changeid can be a changeset revision, node, or tag.
- fileid can be a file revision or node."""
- self._repo = repo
- self._path = path
-
- assert (changeid is not None
- or fileid is not None
- or changectx is not None), \
- ("bad args: changeid=%r, fileid=%r, changectx=%r"
- % (changeid, fileid, changectx))
-
- if filelog is not None:
- self._filelog = filelog
-
- if changeid is not None:
- self._changeid = changeid
- if changectx is not None:
- self._changectx = changectx
- if fileid is not None:
- self._fileid = fileid
-
- @propertycache
- def _changectx(self):
- try:
- return changectx(self._repo, self._changeid)
- except error.RepoLookupError:
- # Linkrev may point to any revision in the repository. When the
- # repository is filtered this may lead to `filectx` trying to build
- # `changectx` for filtered revision. In such case we fallback to
- # creating `changectx` on the unfiltered version of the reposition.
- # This fallback should not be an issue because `changectx` from
- # `filectx` are not used in complex operations that care about
- # filtering.
- #
- # This fallback is a cheap and dirty fix that prevent several
- # crashes. It does not ensure the behavior is correct. However the
- # behavior was not correct before filtering either and "incorrect
- # behavior" is seen as better as "crash"
- #
- # Linkrevs have several serious troubles with filtering that are
- # complicated to solve. Proper handling of the issue here should be
- # considered when solving linkrev issue are on the table.
- return changectx(self._repo.unfiltered(), self._changeid)
+class basefilectx(object):
+ """A filecontext object represents the common logic for its children:
+ filectx: read-only access to a filerevision that is already present
+ in the repo,
+ workingfilectx: a filecontext that represents files from the working
+ directory,
+ memfilectx: a filecontext that represents files in-memory."""
+ def __new__(cls, repo, path, *args, **kwargs):
+ return super(basefilectx, cls).__new__(cls)
@propertycache
def _filelog(self):
@@ -468,10 +456,10 @@
return False
def __str__(self):
- return "%s@%s" % (self.path(), short(self.node()))
+ return "%s@%s" % (self.path(), self._changectx)
def __repr__(self):
- return "<filectx %s>" % str(self)
+ return "<%s %s>" % (type(self).__name__, str(self))
def __hash__(self):
try:
@@ -481,7 +469,7 @@
def __eq__(self, other):
try:
- return (self._path == other._path
+ return (type(self) == type(other) and self._path == other._path
and self._filenode == other._filenode)
except AttributeError:
return False
@@ -489,12 +477,6 @@
def __ne__(self, other):
return not (self == other)
- def filectx(self, fileid):
- '''opens an arbitrary revision of the file without
- opening a new filelog'''
- return filectx(self._repo, self._path, fileid=fileid,
- filelog=self._filelog)
-
def filerev(self):
return self._filerev
def filenode(self):
@@ -510,7 +492,7 @@
def node(self):
return self._changectx.node()
def hex(self):
- return hex(self.node())
+ return self._changectx.hex()
def user(self):
return self._changectx.user()
def date(self):
@@ -532,12 +514,8 @@
def changectx(self):
return self._changectx
- def data(self):
- return self._filelog.read(self._filenode)
def path(self):
return self._path
- def size(self):
- return self._filelog.size(self._filerev)
def isbinary(self):
try:
@@ -560,31 +538,6 @@
return True
- def renamed(self):
- """check if file was actually renamed in this changeset revision
-
- If rename logged in file revision, we report copy for changeset only
- if file revisions linkrev points back to the changeset in question
- or both changeset parents contain different file revisions.
- """
-
- renamed = self._filelog.renamed(self._filenode)
- if not renamed:
- return renamed
-
- if self.rev() == self.linkrev():
- return renamed
-
- name = self.path()
- fnode = self._filenode
- for p in self._changectx.parents():
- try:
- if fnode == p.filenode(name):
- return None
- except error.LookupError:
- pass
- return renamed
-
def parents(self):
p = self._path
fl = self._filelog
@@ -606,12 +559,6 @@
return p[1]
return filectx(self._repo, self._path, fileid=-1, filelog=self._filelog)
- def children(self):
- # hard for renames
- c = self._filelog.children(self._filenode)
- return [filectx(self._repo, self._path, fileid=x,
- filelog=self._filelog) for x in c]
-
def annotate(self, follow=False, linenumber=None, diffopts=None):
'''returns a list of tuples of (ctx, line) for each line
in the file, where ctx is the filectx of the node where
@@ -783,15 +730,100 @@
self._copycache[sc2] = copies.pathcopies(c2)
return self._copycache[sc2]
-class workingctx(changectx):
- """A workingctx object makes access to data related to
- the current working directory convenient.
- date - any valid date string or (unixtime, offset), or None.
- user - username string, or None.
- extra - a dictionary of extra values, or None.
- changes - a list of file lists as returned by localrepo.status()
- or None to use the repository status.
- """
+class filectx(basefilectx):
+ """A filecontext object makes access to data related to a particular
+ filerevision convenient."""
+ def __init__(self, repo, path, changeid=None, fileid=None,
+ filelog=None, changectx=None):
+ """changeid can be a changeset revision, node, or tag.
+ fileid can be a file revision or node."""
+ self._repo = repo
+ self._path = path
+
+ assert (changeid is not None
+ or fileid is not None
+ or changectx is not None), \
+ ("bad args: changeid=%r, fileid=%r, changectx=%r"
+ % (changeid, fileid, changectx))
+
+ if filelog is not None:
+ self._filelog = filelog
+
+ if changeid is not None:
+ self._changeid = changeid
+ if changectx is not None:
+ self._changectx = changectx
+ if fileid is not None:
+ self._fileid = fileid
+
+ @propertycache
+ def _changectx(self):
+ try:
+ return changectx(self._repo, self._changeid)
+ except error.RepoLookupError:
+ # Linkrev may point to any revision in the repository. When the
+ # repository is filtered this may lead to `filectx` trying to build
+ # `changectx` for filtered revision. In such case we fallback to
+ # creating `changectx` on the unfiltered version of the reposition.
+ # This fallback should not be an issue because `changectx` from
+ # `filectx` are not used in complex operations that care about
+ # filtering.
+ #
+ # This fallback is a cheap and dirty fix that prevent several
+ # crashes. It does not ensure the behavior is correct. However the
+ # behavior was not correct before filtering either and "incorrect
+ # behavior" is seen as better as "crash"
+ #
+ # Linkrevs have several serious troubles with filtering that are
+ # complicated to solve. Proper handling of the issue here should be
+ # considered when solving linkrev issue are on the table.
+ return changectx(self._repo.unfiltered(), self._changeid)
+
+ def filectx(self, fileid):
+ '''opens an arbitrary revision of the file without
+ opening a new filelog'''
+ return filectx(self._repo, self._path, fileid=fileid,
+ filelog=self._filelog)
+
+ def data(self):
+ return self._filelog.read(self._filenode)
+ def size(self):
+ return self._filelog.size(self._filerev)
+
+ def renamed(self):
+ """check if file was actually renamed in this changeset revision
+
+ If rename logged in file revision, we report copy for changeset only
+ if file revisions linkrev points back to the changeset in question
+ or both changeset parents contain different file revisions.
+ """
+
+ renamed = self._filelog.renamed(self._filenode)
+ if not renamed:
+ return renamed
+
+ if self.rev() == self.linkrev():
+ return renamed
+
+ name = self.path()
+ fnode = self._filenode
+ for p in self._changectx.parents():
+ try:
+ if fnode == p.filenode(name):
+ return None
+ except error.LookupError:
+ pass
+ return renamed
+
+ def children(self):
+ # hard for renames
+ c = self._filelog.children(self._filenode)
+ return [filectx(self._repo, self._path, fileid=x,
+ filelog=self._filelog) for x in c]
+
+class committablectx(basectx):
+ """A committablectx object provides common functionality for a context that
+ wants the ability to commit, e.g. workingctx or memctx."""
def __init__(self, repo, text="", user=None, date=None, extra=None,
changes=None):
self._repo = repo
@@ -827,9 +859,6 @@
def __str__(self):
return str(self._parents[0]) + "+"
- def __repr__(self):
- return "<workingctx %s>" % str(self)
-
def __nonzero__(self):
return True
@@ -904,12 +933,6 @@
return man
- def __iter__(self):
- d = self._repo.dirstate
- for f in d:
- if d[f] != 'r':
- yield f
-
@propertycache
def _status(self):
return self._repo.status()[:4]
@@ -922,13 +945,6 @@
def _date(self):
return util.makedate()
- @propertycache
- def _parents(self):
- p = self._repo.dirstate.parents()
- if p[1] == nullid:
- p = p[:-1]
- return [changectx(self._repo, x) for x in p]
-
def status(self, ignored=False, clean=False, unknown=False):
"""Explicit status query
Unless this method is used to query the working copy status, the
@@ -945,8 +961,6 @@
self._status = stat[:4]
return stat
- def manifest(self):
- return self._manifest
def user(self):
return self._user or self._repo.ui.username()
def date(self):
@@ -1016,11 +1030,6 @@
except OSError:
return ''
- def filectx(self, path, filelog=None):
- """get a file context from the working directory"""
- return workingfilectx(self._repo, path, workingctx=self,
- filelog=filelog)
-
def ancestor(self, c2):
"""return the ancestor context of self and c2"""
return self._parents[0].ancestor(c2) # punt on two parents for now
@@ -1029,6 +1038,61 @@
return sorted(self._repo.dirstate.walk(match, sorted(self.substate),
True, False))
+ def ancestors(self):
+ for a in self._repo.changelog.ancestors(
+ [p.rev() for p in self._parents]):
+ yield changectx(self._repo, a)
+
+ def markcommitted(self, node):
+ """Perform post-commit cleanup necessary after committing this ctx
+
+ Specifically, this updates backing stores this working context
+ wraps to reflect the fact that the changes reflected by this
+ workingctx have been committed. For example, it marks
+ modified and added files as normal in the dirstate.
+
+ """
+
+ for f in self.modified() + self.added():
+ self._repo.dirstate.normal(f)
+ for f in self.removed():
+ self._repo.dirstate.drop(f)
+ self._repo.dirstate.setparents(node)
+
+ def dirs(self):
+ return self._repo.dirstate.dirs()
+
+class workingctx(committablectx):
+ """A workingctx object makes access to data related to
+ the current working directory convenient.
+ date - any valid date string or (unixtime, offset), or None.
+ user - username string, or None.
+ extra - a dictionary of extra values, or None.
+ changes - a list of file lists as returned by localrepo.status()
+ or None to use the repository status.
+ """
+ def __init__(self, repo, text="", user=None, date=None, extra=None,
+ changes=None):
+ super(workingctx, self).__init__(repo, text, user, date, extra, changes)
+
+ def __iter__(self):
+ d = self._repo.dirstate
+ for f in d:
+ if d[f] != 'r':
+ yield f
+
+ @propertycache
+ def _parents(self):
+ p = self._repo.dirstate.parents()
+ if p[1] == nullid:
+ p = p[:-1]
+ return [changectx(self._repo, x) for x in p]
+
+ def filectx(self, path, filelog=None):
+ """get a file context from the working directory"""
+ return workingfilectx(self._repo, path, workingctx=self,
+ filelog=filelog)
+
def dirty(self, missing=False, merge=True, branch=True):
"check whether a working directory is modified"
# check subrepos first
@@ -1093,11 +1157,6 @@
finally:
wlock.release()
- def ancestors(self):
- for a in self._repo.changelog.ancestors(
- [p.rev() for p in self._parents]):
- yield changectx(self._repo, a)
-
def undelete(self, list):
pctxs = self.parents()
wlock = self._repo.wlock()
@@ -1129,31 +1188,10 @@
finally:
wlock.release()
- def markcommitted(self, node):
- """Perform post-commit cleanup necessary after committing this ctx
-
- Specifically, this updates backing stores this working context
- wraps to reflect the fact that the changes reflected by this
- workingctx have been committed. For example, it marks
- modified and added files as normal in the dirstate.
-
- """
-
- for f in self.modified() + self.added():
- self._repo.dirstate.normal(f)
- for f in self.removed():
- self._repo.dirstate.drop(f)
- self._repo.dirstate.setparents(node)
-
- def dirs(self):
- return self._repo.dirstate.dirs()
-
-class workingfilectx(filectx):
- """A workingfilectx object makes access to data related to a particular
- file in the working directory convenient."""
- def __init__(self, repo, path, filelog=None, workingctx=None):
- """changeid can be a changeset revision, node, or tag.
- fileid can be a file revision or node."""
+class committablefilectx(basefilectx):
+ """A committablefilectx provides common functionality for a file context
+ that wants the ability to commit, e.g. workingfilectx or memfilectx."""
+ def __init__(self, repo, path, filelog=None, ctx=None):
self._repo = repo
self._path = path
self._changeid = None
@@ -1161,30 +1199,12 @@
if filelog is not None:
self._filelog = filelog
- if workingctx:
- self._changectx = workingctx
-
- @propertycache
- def _changectx(self):
- return workingctx(self._repo)
+ if ctx:
+ self._changectx = ctx
def __nonzero__(self):
return True
- def __str__(self):
- return "%s@%s" % (self.path(), self._changectx)
-
- def __repr__(self):
- return "<workingfilectx %s>" % str(self)
-
- def data(self):
- return self._repo.wread(self._path)
- def renamed(self):
- rp = self._repo.dirstate.copied(self._path)
- if not rp:
- return None
- return rp, self._changectx._parents[0]._manifest.get(rp, nullid)
-
def parents(self):
'''return parent filectxs, following copies if necessary'''
def filenode(ctx, path):
@@ -1209,6 +1229,24 @@
def children(self):
return []
+class workingfilectx(committablefilectx):
+ """A workingfilectx object makes access to data related to a particular
+ file in the working directory convenient."""
+ def __init__(self, repo, path, filelog=None, workingctx=None):
+ super(workingfilectx, self).__init__(repo, path, filelog, workingctx)
+
+ @propertycache
+ def _changectx(self):
+ return workingctx(self._repo)
+
+ def data(self):
+ return self._repo.wread(self._path)
+ def renamed(self):
+ rp = self._repo.dirstate.copied(self._path)
+ if not rp:
+ return None
+ return rp, self._changectx._parents[0]._manifest.get(rp, nullid)
+
def size(self):
return os.lstat(self._repo.wjoin(self._path)).st_size
def date(self):
--- a/mercurial/dirstate.py Mon Oct 07 17:47:19 2013 -0400
+++ b/mercurial/dirstate.py Mon Oct 07 17:47:55 2013 -0400
@@ -801,12 +801,9 @@
mexact = match.exact
dirignore = self._dirignore
checkexec = self._checkexec
- checklink = self._checklink
copymap = self._copymap
lastnormaltime = self._lastnormaltime
- lnkkind = stat.S_IFLNK
-
# We need to do full walks when either
# - we're listing all clean files, or
# - match.traversedir does something, because match.traversedir should
@@ -827,20 +824,14 @@
if not st and state in "nma":
dadd(fn)
elif state == 'n':
- # The "mode & lnkkind != lnkkind or self._checklink"
- # lines are an expansion of "islink => checklink"
- # where islink means "is this a link?" and checklink
- # means "can we check links?".
mtime = int(st.st_mtime)
if (size >= 0 and
((size != st.st_size and size != st.st_size & _rangemask)
or ((mode ^ st.st_mode) & 0100 and checkexec))
- and (mode & lnkkind != lnkkind or checklink)
or size == -2 # other parent
or fn in copymap):
madd(fn)
- elif ((time != mtime and time != mtime & _rangemask)
- and (mode & lnkkind != lnkkind or checklink)):
+ elif time != mtime and time != mtime & _rangemask:
ladd(fn)
elif mtime == lastnormaltime:
# fn may have been changed in the same timeslot without
--- a/mercurial/discovery.py Mon Oct 07 17:47:19 2013 -0400
+++ b/mercurial/discovery.py Mon Oct 07 17:47:55 2013 -0400
@@ -269,13 +269,12 @@
allfuturecommon = set(c.node() for c in repo.set('%ld', outgoing.common))
allfuturecommon.update(allmissing)
for branch, heads in sorted(headssum.iteritems()):
- if heads[0] is None:
- # Maybe we should abort if we push more that one head
- # for new branches ?
- continue
candidate_newhs = set(heads[1])
# add unsynced data
- oldhs = set(heads[0])
+ if heads[0] is None:
+ oldhs = set()
+ else:
+ oldhs = set(heads[0])
oldhs.update(heads[2])
candidate_newhs.update(heads[2])
dhs = None
@@ -310,7 +309,16 @@
newhs = candidate_newhs
if [h for h in heads[2] if h not in discardedheads]:
unsynced = True
- if len(newhs) > len(oldhs):
+ if heads[0] is None:
+ if 1 < len(newhs):
+ dhs = list(newhs)
+ if error is None:
+ error = (_("push creates multiple headed new branch '%s'")
+ % (branch))
+ hint = _("merge or"
+ " see \"hg help push\" for detail about"
+ " pushing new heads")
+ elif len(newhs) > len(oldhs):
# strip updates to existing remote heads from the new heads list
dhs = sorted(newhs - bookmarkedheads - oldhs)
if dhs:
--- a/mercurial/dispatch.py Mon Oct 07 17:47:19 2013 -0400
+++ b/mercurial/dispatch.py Mon Oct 07 17:47:55 2013 -0400
@@ -88,11 +88,47 @@
try:
try:
+ debugger = 'pdb'
+ debugtrace = {
+ 'pdb' : pdb.set_trace
+ }
+ debugmortem = {
+ 'pdb' : pdb.post_mortem
+ }
+
+ # read --config before doing anything else
+ # (e.g. to change trust settings for reading .hg/hgrc)
+ cfgs = _parseconfig(req.ui, _earlygetopt(['--config'], req.args))
+
+ if req.repo:
+ # copy configs that were passed on the cmdline (--config) to
+ # the repo ui
+ for cfg in cfgs:
+ req.repo.ui.setconfig(*cfg)
+
+ debugger = ui.config("ui", "debugger")
+ if not debugger:
+ debugger = 'pdb'
+
+ try:
+ debugmod = __import__(debugger)
+ except ImportError:
+ debugmod = pdb
+
+ debugtrace[debugger] = debugmod.set_trace
+ debugmortem[debugger] = debugmod.post_mortem
+
# enter the debugger before command execution
if '--debugger' in req.args:
ui.warn(_("entering debugger - "
"type c to continue starting hg or h for help\n"))
- pdb.set_trace()
+
+ if (debugger != 'pdb' and
+ debugtrace[debugger] == debugtrace['pdb']):
+ ui.warn(_("%s debugger specified "
+ "but its module was not found\n") % debugger)
+
+ debugtrace[debugger]()
try:
return _dispatch(req)
finally:
@@ -101,7 +137,7 @@
# enter the debugger when we hit an exception
if '--debugger' in req.args:
traceback.print_exc()
- pdb.post_mortem(sys.exc_info()[2])
+ debugmortem[debugger](sys.exc_info()[2])
ui.traceback()
raise
@@ -619,10 +655,6 @@
args = req.args
ui = req.ui
- # read --config before doing anything else
- # (e.g. to change trust settings for reading .hg/hgrc)
- cfgs = _parseconfig(ui, _earlygetopt(['--config'], args))
-
# check for cwd
cwd = _earlygetopt(['--cwd'], args)
if cwd:
@@ -699,10 +731,6 @@
if req.repo:
uis.add(req.repo.ui)
- # copy configs that were passed on the cmdline (--config) to the repo ui
- for cfg in cfgs:
- req.repo.ui.setconfig(*cfg)
-
if options['verbose'] or options['debug'] or options['quiet']:
for opt in ('verbose', 'debug', 'quiet'):
val = str(bool(options[opt]))
--- a/mercurial/extensions.py Mon Oct 07 17:47:19 2013 -0400
+++ b/mercurial/extensions.py Mon Oct 07 17:47:55 2013 -0400
@@ -13,10 +13,18 @@
_order = []
_ignore = ['hbisect', 'bookmarks', 'parentrevspec', 'interhg']
-def extensions():
+def extensions(ui=None):
+ if ui:
+ def enabled(name):
+ for format in ['%s', 'hgext.%s']:
+ conf = ui.config('extensions', format % name)
+ if conf is not None and not conf.startswith('!'):
+ return True
+ else:
+ enabled = lambda name: True
for name in _order:
module = _extensions[name]
- if module:
+ if module and enabled(name):
yield name, module
def find(name):
--- a/mercurial/hg.py Mon Oct 07 17:47:19 2013 -0400
+++ b/mercurial/hg.py Mon Oct 07 17:47:55 2013 -0400
@@ -101,7 +101,7 @@
"""return a repository object for the specified path"""
obj = _peerlookup(path).instance(ui, path, create)
ui = getattr(obj, "ui", ui)
- for name, module in extensions.extensions():
+ for name, module in extensions.extensions(ui):
hook = getattr(module, 'reposetup', None)
if hook:
hook(ui, obj)
--- a/mercurial/hgweb/webcommands.py Mon Oct 07 17:47:19 2013 -0400
+++ b/mercurial/hgweb/webcommands.py Mon Oct 07 17:47:55 2013 -0400
@@ -9,13 +9,15 @@
import webutil
from mercurial import error, encoding, archival, templater, templatefilters
from mercurial.node import short, hex, nullid
-from mercurial.util import binary
+from mercurial import util
from common import paritygen, staticfile, get_contact, ErrorResponse
from common import HTTP_OK, HTTP_FORBIDDEN, HTTP_NOT_FOUND
from mercurial import graphmod, patch
from mercurial import help as helpmod
from mercurial import scmutil
from mercurial.i18n import _
+from mercurial.error import ParseError, RepoLookupError, Abort
+from mercurial import revset
# __all__ is populated with the allowed commands. Be sure to add to it if
# you're adding a new command, or the new command won't work.
@@ -57,7 +59,7 @@
if guessmime:
mt = mimetypes.guess_type(path)[0]
if mt is None:
- mt = binary(text) and 'application/binary' or 'text/plain'
+ mt = util.binary(text) and 'application/binary' or 'text/plain'
if mt.startswith('text/'):
mt += '; charset="%s"' % encoding.encoding
@@ -69,7 +71,7 @@
text = fctx.data()
parity = paritygen(web.stripecount)
- if binary(text):
+ if util.binary(text):
mt = mimetypes.guess_type(f)[0] or 'application/octet-stream'
text = '(binary:%s)' % mt
@@ -109,9 +111,14 @@
raise inst
def _search(web, req, tmpl):
+ MODE_REVISION = 'rev'
+ MODE_KEYWORD = 'keyword'
+ MODE_REVSET = 'revset'
- def changelist(**map):
- count = 0
+ def revsearch(ctx):
+ yield ctx
+
+ def keywordsearch(query):
lower = encoding.lower
qw = lower(query).split()
@@ -137,6 +144,62 @@
if miss:
continue
+ yield ctx
+
+ def revsetsearch(revs):
+ for r in revs:
+ yield web.repo[r]
+
+ searchfuncs = {
+ MODE_REVISION: (revsearch, _('exact revision search')),
+ MODE_KEYWORD: (keywordsearch, _('literal keyword search')),
+ MODE_REVSET: (revsetsearch, _('revset expression search')),
+ }
+
+ def getsearchmode(query):
+ try:
+ ctx = web.repo[query]
+ except (error.RepoError, error.LookupError):
+ # query is not an exact revision pointer, need to
+ # decide if it's a revset expession or keywords
+ pass
+ else:
+ return MODE_REVISION, ctx
+
+ revdef = 'reverse(%s)' % query
+ try:
+ tree, pos = revset.parse(revdef)
+ except ParseError:
+ # can't parse to a revset tree
+ return MODE_KEYWORD, query
+
+ if revset.depth(tree) <= 2:
+ # no revset syntax used
+ return MODE_KEYWORD, query
+
+ if util.any((token, (value or '')[:3]) == ('string', 're:')
+ for token, value, pos in revset.tokenize(revdef)):
+ return MODE_KEYWORD, query
+
+ funcsused = revset.funcsused(tree)
+ if not funcsused.issubset(revset.safesymbols):
+ return MODE_KEYWORD, query
+
+ mfunc = revset.match(web.repo.ui, revdef)
+ try:
+ revs = mfunc(web.repo, list(web.repo))
+ return MODE_REVSET, revs
+ # ParseError: wrongly placed tokens, wrongs arguments, etc
+ # RepoLookupError: no such revision, e.g. in 'revision:'
+ # Abort: bookmark/tag not exists
+ # LookupError: ambiguous identifier, e.g. in '(bc)' on a large repo
+ except (ParseError, RepoLookupError, Abort, LookupError):
+ return MODE_KEYWORD, query
+
+ def changelist(**map):
+ count = 0
+
+ for ctx in searchfunc[0](funcarg):
count += 1
n = ctx.node()
showtags = webutil.showtag(web.repo, tmpl, 'changelogtag', n)
@@ -176,35 +239,45 @@
morevars['revcount'] = revcount * 2
morevars['rev'] = query
+ mode, funcarg = getsearchmode(query)
+
+ if 'forcekw' in req.form:
+ showforcekw = ''
+ showunforcekw = searchfuncs[mode][1]
+ mode = MODE_KEYWORD
+ funcarg = query
+ else:
+ if mode != MODE_KEYWORD:
+ showforcekw = searchfuncs[MODE_KEYWORD][1]
+ else:
+ showforcekw = ''
+ showunforcekw = ''
+
+ searchfunc = searchfuncs[mode]
+
tip = web.repo['tip']
parity = paritygen(web.stripecount)
return tmpl('search', query=query, node=tip.hex(),
entries=changelist, archives=web.archivelist("tip"),
- morevars=morevars, lessvars=lessvars)
+ morevars=morevars, lessvars=lessvars,
+ modedesc=searchfunc[1],
+ showforcekw=showforcekw, showunforcekw=showunforcekw)
def changelog(web, req, tmpl, shortlog=False):
query = ''
if 'node' in req.form:
ctx = webutil.changectx(web.repo, req)
+ elif 'rev' in req.form:
+ return _search(web, req, tmpl)
else:
- if 'rev' in req.form:
- query = req.form['rev'][0]
- hi = query
- else:
- hi = 'tip'
- try:
- ctx = web.repo[hi]
- except (error.RepoError, error.LookupError):
- return _search(web, req, tmpl) # XXX redirect to 404 page?
+ ctx = web.repo['tip']
- def changelist(latestonly, **map):
+ def changelist():
revs = []
if pos != -1:
revs = web.repo.changelog.revs(pos, 0)
- if latestonly:
- revs = (revs.next(),)
curcount = 0
for i in revs:
ctx = web.repo[i]
@@ -213,7 +286,7 @@
files = webutil.listfilediffs(tmpl, ctx.files(), n, web.maxfiles)
curcount += 1
- if curcount > revcount:
+ if curcount > revcount + 1:
break
yield {"parity": parity.next(),
"author": ctx.user(),
@@ -249,15 +322,23 @@
changenav = webutil.revnav(web.repo).gen(pos, revcount, count)
+ entries = list(changelist())
+ latestentry = entries[:1]
+ if len(entries) > revcount:
+ nextentry = entries[-1:]
+ entries = entries[:-1]
+ else:
+ nextentry = []
+
return tmpl(shortlog and 'shortlog' or 'changelog', changenav=changenav,
node=ctx.hex(), rev=pos, changesets=count,
- entries=lambda **x: changelist(latestonly=False, **x),
- latestentry=lambda **x: changelist(latestonly=True, **x),
+ entries=entries,
+ latestentry=latestentry, nextentry=nextentry,
archives=web.archivelist("tip"), revcount=revcount,
morevars=morevars, lessvars=lessvars, query=query)
def shortlog(web, req, tmpl):
- return changelog(web, req, tmpl, shortlog = True)
+ return changelog(web, req, tmpl, shortlog=True)
def changeset(web, req, tmpl):
ctx = webutil.changectx(web.repo, req)
@@ -617,7 +698,7 @@
context = parsecontext(web.config('web', 'comparisoncontext', '5'))
def filelines(f):
- if binary(f.data()):
+ if util.binary(f.data()):
mt = mimetypes.guess_type(f.path())[0]
if not mt:
mt = 'application/octet-stream'
@@ -675,7 +756,7 @@
def annotate(**map):
last = None
- if binary(fctx.data()):
+ if util.binary(fctx.data()):
mt = (mimetypes.guess_type(fctx.path())[0]
or 'application/octet-stream')
lines = enumerate([((fctx.filectx(fctx.filerev()), 1),
--- a/mercurial/httpclient/__init__.py Mon Oct 07 17:47:19 2013 -0400
+++ b/mercurial/httpclient/__init__.py Mon Oct 07 17:47:55 2013 -0400
@@ -292,7 +292,7 @@
def __init__(self, host, port=None, use_ssl=None, ssl_validator=None,
timeout=TIMEOUT_DEFAULT,
continue_timeout=TIMEOUT_ASSUME_CONTINUE,
- proxy_hostport=None, **ssl_opts):
+ proxy_hostport=None, ssl_wrap_socket=None, **ssl_opts):
"""Create a new HTTPConnection.
Args:
@@ -307,12 +307,23 @@
"100 Continue" response. Default is TIMEOUT_ASSUME_CONTINUE.
proxy_hostport: Optional. Tuple of (host, port) to use as an http
proxy for the connection. Default is to not use a proxy.
+ ssl_wrap_socket: Optional function to use for wrapping
+ sockets. If unspecified, the one from the ssl module will
+ be used if available, or something that's compatible with
+ it if on a Python older than 2.6.
+
+ Any extra keyword arguments to this function will be provided
+ to the ssl_wrap_socket method. If no ssl
"""
if port is None and host.count(':') == 1 or ']:' in host:
host, port = host.rsplit(':', 1)
port = int(port)
if '[' in host:
host = host[1:-1]
+ if ssl_wrap_socket is not None:
+ self._ssl_wrap_socket = ssl_wrap_socket
+ else:
+ self._ssl_wrap_socket = socketutil.wrap_socket
if use_ssl is None and port is None:
use_ssl = False
port = 80
@@ -387,7 +398,7 @@
sock.setblocking(1)
logger.debug('wrapping socket for ssl with options %r',
self.ssl_opts)
- sock = socketutil.wrap_socket(sock, **self.ssl_opts)
+ sock = self._ssl_wrap_socket(sock, **self.ssl_opts)
if self._ssl_validator:
self._ssl_validator(sock)
sock.setblocking(0)
@@ -495,6 +506,10 @@
else:
raise BadRequestData('body has no __len__() nor read()')
+ # If we're reusing the underlying socket, there are some
+ # conditions where we'll want to retry, so make a note of the
+ # state of self.sock
+ fresh_socket = self.sock is None
self._connect()
outgoing_headers = self._buildheaders(
method, path, hdrs, self.http_version)
@@ -640,6 +655,26 @@
# the whole request
if response is None:
response = self.response_class(self.sock, self.timeout, method)
+ if not fresh_socket:
+ if not response._select():
+ # This means the response failed to get any response
+ # data at all, and in all probability the socket was
+ # closed before the server even saw our request. Try
+ # the request again on a fresh socket.
+ logging.debug('response._select() failed during request().'
+ ' Assuming request needs to be retried.')
+ self.sock = None
+ # Call this method explicitly to re-try the
+ # request. We don't use self.request() because
+ # some tools (notably Mercurial) expect to be able
+ # to subclass and redefine request(), and they
+ # don't have the same argspec as we do.
+ #
+ # TODO restructure sending of requests to avoid
+ # this recursion
+ return HTTPConnection.request(
+ self, method, path, body=body, headers=headers,
+ expect_continue=expect_continue)
data_left = bool(outgoing_headers or body)
if data_left:
logger.info('stopped sending request early, '
--- a/mercurial/httpconnection.py Mon Oct 07 17:47:19 2013 -0400
+++ b/mercurial/httpconnection.py Mon Oct 07 17:47:55 2013 -0400
@@ -275,14 +275,13 @@
if '[' in host:
host = host[1:-1]
- if keyfile:
- kwargs['keyfile'] = keyfile
- if certfile:
- kwargs['certfile'] = certfile
+ kwargs['keyfile'] = keyfile
+ kwargs['certfile'] = certfile
kwargs.update(sslutil.sslkwargs(self.ui, host))
con = HTTPConnection(host, port, use_ssl=True,
+ ssl_wrap_socket=sslutil.ssl_wrap_socket,
ssl_validator=sslutil.validator(self.ui, host),
**kwargs)
return con
--- a/mercurial/keepalive.py Mon Oct 07 17:47:19 2013 -0400
+++ b/mercurial/keepalive.py Mon Oct 07 17:47:55 2013 -0400
@@ -499,7 +499,7 @@
data, self._rbuf = self._rbuf[:i], self._rbuf[i:]
return data
- def readlines(self, sizehint = 0):
+ def readlines(self, sizehint=0):
total = 0
list = []
while True:
--- a/mercurial/localrepo.py Mon Oct 07 17:47:19 2013 -0400
+++ b/mercurial/localrepo.py Mon Oct 07 17:47:55 2013 -0400
@@ -147,12 +147,14 @@
class localrepository(object):
supportedformats = set(('revlogv1', 'generaldelta'))
- supported = supportedformats | set(('store', 'fncache', 'shared',
- 'dotencode'))
+ _basesupported = supportedformats | set(('store', 'fncache', 'shared',
+ 'dotencode'))
openerreqs = set(('revlogv1', 'generaldelta'))
requirements = ['revlogv1']
filtername = None
+ featuresetupfuncs = set()
+
def _baserequirements(self, create):
return self.requirements[:]
@@ -177,6 +179,13 @@
except IOError:
pass
+ if self.featuresetupfuncs:
+ self.supported = set(self._basesupported) # use private copy
+ for setupfunc in self.featuresetupfuncs:
+ setupfunc(self.ui, self.supported)
+ else:
+ self.supported = self._basesupported
+
if not self.vfs.isdir():
if create:
if not self.wvfs.exists():
@@ -804,7 +813,7 @@
def wwritedata(self, filename, data):
return self._filter(self._decodefilterpats, filename, data)
- def transaction(self, desc):
+ def transaction(self, desc, report=None):
tr = self._transref and self._transref() or None
if tr and tr.running():
return tr.nest()
@@ -816,8 +825,8 @@
self._writejournal(desc)
renames = [(vfs, x, undoname(x)) for vfs, x in self._journalfiles()]
-
- tr = transaction.transaction(self.ui.warn, self.sopener,
+ rp = report and report or self.ui.warn
+ tr = transaction.transaction(rp, self.sopener,
self.sjoin("journal"),
aftertrans(renames),
self.store.createmode)
@@ -1460,14 +1469,8 @@
del mf[fn]
return mf
- if isinstance(node1, context.changectx):
- ctx1 = node1
- else:
- ctx1 = self[node1]
- if isinstance(node2, context.changectx):
- ctx2 = node2
- else:
- ctx2 = self[node2]
+ ctx1 = self[node1]
+ ctx2 = self[node2]
working = ctx2.rev() is None
parentworking = working and ctx1 == self['.']
@@ -1564,7 +1567,7 @@
for f in modified:
if ctx2.flags(f) == 'l':
d = ctx2[f].data()
- if len(d) >= 1024 or '\n' in d or util.binary(d):
+ if d == '' or len(d) >= 1024 or '\n' in d or util.binary(d):
self.ui.debug('ignoring suspect symlink placeholder'
' "%s"\n' % f)
continue
@@ -1656,6 +1659,14 @@
return r
def pull(self, remote, heads=None, force=False):
+ if remote.local():
+ missing = set(remote.requirements) - self.supported
+ if missing:
+ msg = _("required features are not"
+ " supported in the destination:"
+ " %s") % (', '.join(sorted(missing)))
+ raise util.Abort(msg)
+
# don't open transaction for nothing or you break future useful
# rollback call
tr = None
@@ -1756,6 +1767,14 @@
we have outgoing changesets but refused to push
- other values as described by addchangegroup()
'''
+ if remote.local():
+ missing = set(self.requirements) - remote.local().supported
+ if missing:
+ msg = _("required features are not"
+ " supported in the destination:"
+ " %s") % (', '.join(sorted(missing)))
+ raise util.Abort(msg)
+
# there are two ways to push to remote repo:
#
# addchangegroup assumes local user can lock remote
--- a/mercurial/mail.py Mon Oct 07 17:47:19 2013 -0400
+++ b/mercurial/mail.py Mon Oct 07 17:47:55 2013 -0400
@@ -8,7 +8,11 @@
from i18n import _
import util, encoding, sslutil
import os, smtplib, socket, quopri, time, sys
-import email.Header, email.MIMEText, email.Utils
+import email
+# On python2.4 you have to import these by name or they fail to
+# load. This was not a problem on Python 2.7.
+import email.Header
+import email.MIMEText
_oldheaderinit = email.Header.Header.__init__
def _unifiedheaderinit(self, *args, **kw):
--- a/mercurial/match.py Mon Oct 07 17:47:19 2013 -0400
+++ b/mercurial/match.py Mon Oct 07 17:47:55 2013 -0400
@@ -140,7 +140,7 @@
class exact(match):
def __init__(self, root, cwd, files):
- match.__init__(self, root, cwd, files, exact = True)
+ match.__init__(self, root, cwd, files, exact=True)
class always(match):
def __init__(self, root, cwd):
--- a/mercurial/merge.py Mon Oct 07 17:47:19 2013 -0400
+++ b/mercurial/merge.py Mon Oct 07 17:47:55 2013 -0400
@@ -656,19 +656,21 @@
-c -C dirty rev | linear same cross
n n n n | ok (1) x
n n n y | ok ok ok
- n n y * | merge (2) (2)
+ n n y n | merge (2) (2)
+ n n y y | merge (3) (3)
n y * * | --- discard ---
- y n y * | --- (3) ---
+ y n y * | --- (4) ---
y n n * | --- ok ---
- y y * * | --- (4) ---
+ y y * * | --- (5) ---
x = can't happen
* = don't-care
- 1 = abort: crosses branches (use 'hg merge' or 'hg update -c')
- 2 = abort: crosses branches (use 'hg merge' to merge or
- use 'hg update -C' to discard changes)
- 3 = abort: uncommitted local changes
- 4 = incompatible options (checked in commands.py)
+ 1 = abort: not a linear update (merge or update --check to force update)
+ 2 = abort: uncommitted changes (commit and merge, or update --clean to
+ discard changes)
+ 3 = abort: uncommitted changes (commit or update --clean to discard changes)
+ 4 = abort: uncommitted changes (checked in commands.py)
+ 5 = incompatible options (checked in commands.py)
Return the same tuple as applyupdates().
"""
@@ -709,11 +711,11 @@
hint=_("use 'hg update' "
"or check 'hg heads'"))
if not force and (wc.files() or wc.deleted()):
- raise util.Abort(_("outstanding uncommitted changes"),
+ raise util.Abort(_("uncommitted changes"),
hint=_("use 'hg status' to list changes"))
for s in sorted(wc.substate):
if wc.sub(s).dirty():
- raise util.Abort(_("outstanding uncommitted changes in "
+ raise util.Abort(_("uncommitted changes in "
"subrepository '%s'") % s)
elif not overwrite:
@@ -727,13 +729,18 @@
if repo[node].node() in foreground:
pa = p1 # allow updating to successors
elif dirty:
- msg = _("crosses branches (merge branches or use"
- " --clean to discard changes)")
- raise util.Abort(msg)
+ msg = _("uncommitted changes")
+ if onode is None:
+ hint = _("commit and merge, or update --clean to"
+ " discard changes")
+ else:
+ hint = _("commit or update --clean to discard"
+ " changes")
+ raise util.Abort(msg, hint=hint)
else: # node is none
- msg = _("crosses branches (merge branches or update"
- " --check to force update)")
- raise util.Abort(msg)
+ msg = _("not a linear update")
+ hint = _("merge or update --check to force update")
+ raise util.Abort(msg, hint=hint)
else:
# Allow jumping branches if clean and specific rev given
pa = p1
--- a/mercurial/obsolete.py Mon Oct 07 17:47:19 2013 -0400
+++ b/mercurial/obsolete.py Mon Oct 07 17:47:55 2013 -0400
@@ -371,7 +371,7 @@
lock.release()
def syncpush(repo, remote):
- """utility function to push bookmark to a remote
+ """utility function to push obsolete markers to a remote
Exist mostly to allow overridding for experimentation purpose"""
if (_enabled and repo.obsstore and
@@ -387,7 +387,7 @@
repo.ui.warn(msg)
def syncpull(repo, remote, gettransaction):
- """utility function to pull bookmark to a remote
+ """utility function to pull obsolete markers from a remote
The `gettransaction` is function that return the pull transaction, creating
one if necessary. We return the transaction to inform the calling code that
--- a/mercurial/parsers.c Mon Oct 07 17:47:19 2013 -0400
+++ b/mercurial/parsers.c Mon Oct 07 17:47:55 2013 -0400
@@ -14,16 +14,32 @@
#include "util.h"
+static int8_t hextable[256] = {
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -1, -1, -1, -1, -1, -1, /* 0-9 */
+ -1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* A-F */
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* a-f */
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
+};
+
static inline int hexdigit(const char *p, Py_ssize_t off)
{
- char c = p[off];
+ int8_t val = hextable[(unsigned char)p[off]];
- if (c >= '0' && c <= '9')
- return c - '0';
- if (c >= 'a' && c <= 'f')
- return c - 'a' + 10;
- if (c >= 'A' && c <= 'F')
- return c - 'A' + 10;
+ if (val >= 0) {
+ return val;
+ }
PyErr_SetString(PyExc_ValueError, "input contains non-hex character");
return 0;
@@ -61,7 +77,7 @@
static PyObject *parse_manifest(PyObject *self, PyObject *args)
{
PyObject *mfdict, *fdict;
- char *str, *cur, *start, *zero;
+ char *str, *start, *end;
int len;
if (!PyArg_ParseTuple(args, "O!O!s#:parse_manifest",
@@ -70,30 +86,34 @@
&str, &len))
goto quit;
- for (start = cur = str, zero = NULL; cur < str + len; cur++) {
+ start = str;
+ end = str + len;
+ while (start < end) {
PyObject *file = NULL, *node = NULL;
PyObject *flags = NULL;
+ char *zero = NULL, *newline = NULL;
ptrdiff_t nlen;
- if (!*cur) {
- zero = cur;
- continue;
- }
- else if (*cur != '\n')
- continue;
-
+ zero = memchr(start, '\0', end - start);
if (!zero) {
PyErr_SetString(PyExc_ValueError,
"manifest entry has no separator");
goto quit;
}
+ newline = memchr(zero + 1, '\n', end - (zero + 1));
+ if (!newline) {
+ PyErr_SetString(PyExc_ValueError,
+ "manifest contains trailing garbage");
+ goto quit;
+ }
+
file = PyBytes_FromStringAndSize(start, zero - start);
if (!file)
goto bail;
- nlen = cur - zero - 1;
+ nlen = newline - zero - 1;
node = unhexlify(zero + 1, nlen > 40 ? 40 : (int)nlen);
if (!node)
@@ -112,8 +132,7 @@
if (PyDict_SetItem(mfdict, file, node) == -1)
goto bail;
- start = cur + 1;
- zero = NULL;
+ start = newline + 1;
Py_XDECREF(flags);
Py_XDECREF(node);
@@ -126,12 +145,6 @@
goto quit;
}
- if (len > 0 && *(cur - 1) != '\n') {
- PyErr_SetString(PyExc_ValueError,
- "manifest contains trailing garbage");
- goto quit;
- }
-
Py_INCREF(Py_None);
return Py_None;
quit:
@@ -142,8 +155,8 @@
{
PyObject *dmap, *cmap, *parents = NULL, *ret = NULL;
PyObject *fname = NULL, *cname = NULL, *entry = NULL;
- char *str, *cur, *end, *cpos;
- int state, mode, size, mtime;
+ char state, *str, *cur, *end, *cpos;
+ int mode, size, mtime;
unsigned int flen;
int len;
@@ -330,7 +343,7 @@
* this. */
if (PyDict_SetItem(map, k, dirstate_unset) == -1)
goto bail;
- mode = 0, size = -1, mtime = -1;
+ mtime = -1;
}
putbe32(mode, p);
putbe32(size, p + 4);
@@ -524,11 +537,12 @@
uncomp_len, base_rev, link_rev,
parent_1, parent_2, c_node_id, 20);
- if (entry)
+ if (entry) {
PyObject_GC_UnTrack(entry);
+ Py_INCREF(entry);
+ }
self->cache[pos] = entry;
- Py_INCREF(entry);
return entry;
}
@@ -1195,14 +1209,19 @@
long sp;
bitmask *seen;
+ if (gca == NULL)
+ return PyErr_NoMemory();
+
for (i = 0; i < revcount; i++) {
if (revs[i] > maxrev)
maxrev = revs[i];
}
seen = calloc(sizeof(*seen), maxrev + 1);
- if (seen == NULL)
+ if (seen == NULL) {
+ Py_DECREF(gca);
return PyErr_NoMemory();
+ }
for (i = 0; i < revcount; i++)
seen[revs[i]] = 1ull << i;
--- a/mercurial/patch.py Mon Oct 07 17:47:19 2013 -0400
+++ b/mercurial/patch.py Mon Oct 07 17:47:55 2013 -0400
@@ -6,8 +6,12 @@
# This software may be used and distributed according to the terms of the
# GNU General Public License version 2 or any later version.
-import cStringIO, email.Parser, os, errno, re, posixpath
+import cStringIO, email, os, errno, re, posixpath
import tempfile, zlib, shutil
+# On python2.4 you have to import these by name or they fail to
+# load. This was not a problem on Python 2.7.
+import email.Generator
+import email.Parser
from i18n import _
from node import hex, short
--- a/mercurial/pure/parsers.py Mon Oct 07 17:47:19 2013 -0400
+++ b/mercurial/pure/parsers.py Mon Oct 07 17:47:55 2013 -0400
@@ -100,11 +100,11 @@
# systems with a granularity of 1 sec). This commonly happens
# for at least a couple of files on 'update'.
# The user could change the file without changing its size
- # within the same second. Invalidate the file's stat data in
+ # within the same second. Invalidate the file's mtime in
# dirstate, forcing future 'status' calls to compare the
- # contents of the file. This prevents mistakenly treating such
- # files as clean.
- e = (e[0], 0, -1, -1) # mark entry as 'unset'
+ # contents of the file if the size is the same. This prevents
+ # mistakenly treating such files as clean.
+ e = (e[0], e[1], e[2], -1)
dmap[f] = e
if f in copymap:
--- a/mercurial/revlog.py Mon Oct 07 17:47:19 2013 -0400
+++ b/mercurial/revlog.py Mon Oct 07 17:47:55 2013 -0400
@@ -14,7 +14,7 @@
# import stuff from node for others to import from revlog
from node import bin, hex, nullid, nullrev
from i18n import _
-import ancestor, mdiff, parsers, error, util
+import ancestor, mdiff, parsers, error, util, templatefilters
import struct, zlib, errno
_pack = struct.pack
@@ -845,16 +845,43 @@
def _chunkraw(self, startrev, endrev):
start = self.start(startrev)
- length = self.end(endrev) - start
+ end = self.end(endrev)
if self._inline:
start += (startrev + 1) * self._io.size
+ end += (endrev + 1) * self._io.size
+ length = end - start
return self._getchunk(start, length)
def _chunk(self, rev):
return decompress(self._chunkraw(rev, rev))
- def _chunkbase(self, rev):
- return self._chunk(rev)
+ def _chunks(self, revs):
+ '''faster version of [self._chunk(rev) for rev in revs]
+
+ Assumes that revs is in ascending order.'''
+ if not revs:
+ return []
+ start = self.start
+ length = self.length
+ inline = self._inline
+ iosize = self._io.size
+ buffer = util.buffer
+
+ l = []
+ ladd = l.append
+
+ # preload the cache
+ self._chunkraw(revs[0], revs[-1])
+ offset, data = self._chunkcache
+
+ for rev in revs:
+ chunkstart = start(rev)
+ if inline:
+ chunkstart += (rev + 1) * iosize
+ chunklength = length(rev)
+ ladd(decompress(buffer(data, chunkstart - offset, chunklength)))
+
+ return l
def _chunkclear(self):
self._chunkcache = (0, '')
@@ -919,21 +946,22 @@
else:
iterrev -= 1
e = index[iterrev]
- chain.reverse()
- base = iterrev
if iterrev == cachedrev:
# cache hit
text = self._cache[2]
+ else:
+ chain.append(iterrev)
+ chain.reverse()
# drop cache to save memory
self._cache = None
- self._chunkraw(base, rev)
+ bins = self._chunks(chain)
if text is None:
- text = str(self._chunkbase(base))
+ text = str(bins[0])
+ bins = bins[1:]
- bins = [self._chunk(r) for r in chain]
text = mdiff.patches(text, bins)
text = self._checkhash(text, node, rev)
@@ -943,10 +971,16 @@
def _checkhash(self, text, node, rev):
p1, p2 = self.parents(node)
+ self.checkhash(text, p1, p2, node, rev)
+ return text
+
+ def checkhash(self, text, p1, p2, node, rev=None):
if node != hash(text, p1, p2):
- raise RevlogError(_("integrity check failed on %s:%d")
- % (self.indexfile, rev))
- return text
+ revornode = rev
+ if revornode is None:
+ revornode = templatefilters.short(hex(node))
+ raise RevlogError(_("integrity check failed on %s:%s")
+ % (self.indexfile, revornode))
def checkinlinesize(self, tr, fp=None):
if not self._inline or (self.start(-2) + self.length(-2)) < _maxinline:
@@ -987,7 +1021,8 @@
tr.replace(self.indexfile, trindex * self._io.size)
self._chunkclear()
- def addrevision(self, text, transaction, link, p1, p2, cachedelta=None):
+ def addrevision(self, text, transaction, link, p1, p2, cachedelta=None,
+ node=None):
"""add a revision to the log
text - the revision data to add
@@ -995,11 +1030,14 @@
link - the linkrev data to add
p1, p2 - the parent nodeids of the revision
cachedelta - an optional precomputed delta
+ node - nodeid of revision; typically node is not specified, and it is
+ computed by default as hash(text, p1, p2), however subclasses might
+ use different hashing method (and override checkhash() in such case)
"""
if link == nullrev:
raise RevlogError(_("attempted to add linkrev -1 to %s")
% self.indexfile)
- node = hash(text, p1, p2)
+ node = node or hash(text, p1, p2)
if node in self.nodemap:
return node
@@ -1063,9 +1101,7 @@
ifh.flush()
basetext = self.revision(self.node(cachedelta[0]))
btext[0] = mdiff.patch(basetext, cachedelta[1])
- chk = hash(btext[0], p1, p2)
- if chk != node:
- raise RevlogError(_("consistency error in delta"))
+ self.checkhash(btext[0], p1, p2, node)
return btext[0]
def builddelta(rev):
--- a/mercurial/revset.py Mon Oct 07 17:47:19 2013 -0400
+++ b/mercurial/revset.py Mon Oct 07 17:47:55 2013 -0400
@@ -1599,6 +1599,75 @@
"_list": _list,
}
+# symbols which can't be used for a DoS attack for any given input
+# (e.g. those which accept regexes as plain strings shouldn't be included)
+# functions that just return a lot of changesets (like all) don't count here
+safesymbols = set([
+ "adds",
+ "all",
+ "ancestor",
+ "ancestors",
+ "_firstancestors",
+ "author",
+ "bisect",
+ "bisected",
+ "bookmark",
+ "branch",
+ "branchpoint",
+ "bumped",
+ "bundle",
+ "children",
+ "closed",
+ "converted",
+ "date",
+ "desc",
+ "descendants",
+ "_firstdescendants",
+ "destination",
+ "divergent",
+ "draft",
+ "extinct",
+ "extra",
+ "file",
+ "filelog",
+ "first",
+ "follow",
+ "_followfirst",
+ "head",
+ "heads",
+ "hidden",
+ "id",
+ "keyword",
+ "last",
+ "limit",
+ "_matchfiles",
+ "max",
+ "merge",
+ "min",
+ "modifies",
+ "obsolete",
+ "origin",
+ "outgoing",
+ "p1",
+ "p2",
+ "parents",
+ "present",
+ "public",
+ "remote",
+ "removes",
+ "rev",
+ "reverse",
+ "roots",
+ "sort",
+ "secret",
+ "matching",
+ "tag",
+ "tagged",
+ "user",
+ "unstable",
+ "_list",
+])
+
methods = {
"range": rangeset,
"dagrange": dagrange,
@@ -1935,5 +2004,22 @@
output = '\n'.join((' '*l + s) for l, s in lines)
return output
+def depth(tree):
+ if isinstance(tree, tuple):
+ return max(map(depth, tree)) + 1
+ else:
+ return 0
+
+def funcsused(tree):
+ if not isinstance(tree, tuple) or tree[0] in ('string', 'symbol'):
+ return set()
+ else:
+ funcs = set()
+ for s in tree[1:]:
+ funcs |= funcsused(s)
+ if tree[0] == 'func':
+ funcs.add(tree[1][1])
+ return funcs
+
# tell hggettext to extract docstrings from these functions:
i18nfunctions = symbols.values()
--- a/mercurial/scmutil.py Mon Oct 07 17:47:19 2013 -0400
+++ b/mercurial/scmutil.py Mon Oct 07 17:47:55 2013 -0400
@@ -755,7 +755,8 @@
ctx = repo[None]
dirstate = repo.dirstate
- walkresults = dirstate.walk(matcher, sorted(ctx.substate), True, False)
+ walkresults = dirstate.walk(matcher, sorted(ctx.substate), True, False,
+ full=False)
for abs, st in walkresults.iteritems():
dstate = dirstate[abs]
if dstate == '?' and audit_path.check(abs):
--- a/mercurial/sslutil.py Mon Oct 07 17:47:19 2013 -0400
+++ b/mercurial/sslutil.py Mon Oct 07 17:47:55 2013 -0400
@@ -14,10 +14,13 @@
# avoid using deprecated/broken FakeSocket in python 2.6
import ssl
CERT_REQUIRED = ssl.CERT_REQUIRED
- def ssl_wrap_socket(sock, keyfile, certfile,
+ PROTOCOL_SSLv23 = ssl.PROTOCOL_SSLv23
+ PROTOCOL_TLSv1 = ssl.PROTOCOL_TLSv1
+ def ssl_wrap_socket(sock, keyfile, certfile, ssl_version=PROTOCOL_TLSv1,
cert_reqs=ssl.CERT_NONE, ca_certs=None):
sslsocket = ssl.wrap_socket(sock, keyfile, certfile,
- cert_reqs=cert_reqs, ca_certs=ca_certs)
+ cert_reqs=cert_reqs, ca_certs=ca_certs,
+ ssl_version=ssl_version)
# check if wrap_socket failed silently because socket had been closed
# - see http://bugs.python.org/issue13721
if not sslsocket.cipher():
@@ -26,9 +29,12 @@
except ImportError:
CERT_REQUIRED = 2
+ PROTOCOL_SSLv23 = 2
+ PROTOCOL_TLSv1 = 3
+
import socket, httplib
- def ssl_wrap_socket(sock, key_file, cert_file,
+ def ssl_wrap_socket(sock, keyfile, certfile, ssl_version=PROTOCOL_TLSv1,
cert_reqs=CERT_REQUIRED, ca_certs=None):
if not util.safehasattr(socket, 'ssl'):
raise util.Abort(_('Python SSL support not found'))
@@ -36,7 +42,7 @@
raise util.Abort(_(
'certificate checking requires Python 2.6'))
- ssl = socket.ssl(sock, key_file, cert_file)
+ ssl = socket.ssl(sock, keyfile, certfile)
return httplib.FakeSocket(sock, ssl)
def _verifycert(cert, hostname):
@@ -84,15 +90,22 @@
def sslkwargs(ui, host):
cacerts = ui.config('web', 'cacerts')
+ forcetls = ui.configbool('ui', 'tls', default=True)
+ if forcetls:
+ ssl_version = PROTOCOL_TLSv1
+ else:
+ ssl_version = PROTOCOL_SSLv23
hostfingerprint = ui.config('hostfingerprints', host)
+ kws = {'ssl_version': ssl_version,
+ }
if cacerts and not hostfingerprint:
cacerts = util.expandpath(cacerts)
if not os.path.exists(cacerts):
raise util.Abort(_('could not find web.cacerts: %s') % cacerts)
- return {'ca_certs': cacerts,
- 'cert_reqs': CERT_REQUIRED,
- }
- return {}
+ kws.update({'ca_certs': cacerts,
+ 'cert_reqs': CERT_REQUIRED,
+ })
+ return kws
class validator(object):
def __init__(self, ui, host):
--- a/mercurial/statichttprepo.py Mon Oct 07 17:47:19 2013 -0400
+++ b/mercurial/statichttprepo.py Mon Oct 07 17:47:55 2013 -0400
@@ -89,6 +89,8 @@
return False
class statichttprepository(localrepo.localrepository):
+ supported = localrepo.localrepository._basesupported
+
def __init__(self, ui, path):
self._url = path
self.ui = ui
--- a/mercurial/subrepo.py Mon Oct 07 17:47:19 2013 -0400
+++ b/mercurial/subrepo.py Mon Oct 07 17:47:55 2013 -0400
@@ -5,7 +5,8 @@
# This software may be used and distributed according to the terms of the
# GNU General Public License version 2 or any later version.
-import errno, os, re, xml.dom.minidom, shutil, posixpath, sys
+import errno, os, re, shutil, posixpath, sys
+import xml.dom.minidom
import stat, subprocess, tarfile
from i18n import _
import config, scmutil, util, node, error, cmdutil, bookmarks, match as matchmod
@@ -201,9 +202,24 @@
wctx.sub(s).get(r, overwrite)
sm[s] = r
else:
- debug(s, "both sides changed, merge with", r)
- wctx.sub(s).merge(r)
- sm[s] = l
+ debug(s, "both sides changed")
+ option = repo.ui.promptchoice(
+ _(' subrepository %s diverged (local revision: %s, '
+ 'remote revision: %s)\n'
+ '(M)erge, keep (l)ocal or keep (r)emote?'
+ '$$ &Merge $$ &Local $$ &Remote')
+ % (s, l[1][:12], r[1][:12]), 0)
+ if option == 0:
+ wctx.sub(s).merge(r)
+ sm[s] = l
+ debug(s, "merge with", r)
+ elif option == 1:
+ sm[s] = l
+ debug(s, "keep local subrepo revision", l)
+ else:
+ wctx.sub(s).get(r, overwrite)
+ sm[s] = r
+ debug(s, "get remote subrepo revision", r)
elif ld == a: # remote removed, local unchanged
debug(s, "remote removed, remove")
wctx.sub(s).remove()
@@ -237,6 +253,7 @@
# record merged .hgsubstate
writestate(repo, sm)
+ return sm
def _updateprompt(ui, sub, dirty, local, remote):
if dirty:
--- a/mercurial/templatefilters.py Mon Oct 07 17:47:19 2013 -0400
+++ b/mercurial/templatefilters.py Mon Oct 07 17:47:55 2013 -0400
@@ -15,15 +15,15 @@
"""
return text.replace('\n', '<br/>\n')
-agescales = [("year", 3600 * 24 * 365),
- ("month", 3600 * 24 * 30),
- ("week", 3600 * 24 * 7),
- ("day", 3600 * 24),
- ("hour", 3600),
- ("minute", 60),
- ("second", 1)]
+agescales = [("year", 3600 * 24 * 365, 'Y'),
+ ("month", 3600 * 24 * 30, 'M'),
+ ("week", 3600 * 24 * 7, 'W'),
+ ("day", 3600 * 24, 'd'),
+ ("hour", 3600, 'h'),
+ ("minute", 60, 'm'),
+ ("second", 1, 's')]
-def age(date):
+def age(date, abbrev=False):
""":age: Date. Returns a human-readable date/time difference between the
given date/time and the current date/time.
"""
@@ -32,7 +32,9 @@
if c == 1:
return t
return t + "s"
- def fmt(t, c):
+ def fmt(t, c, a):
+ if abbrev:
+ return "%d%s" % (c, a)
return "%d %s" % (c, plural(t, c))
now = time.time()
@@ -48,12 +50,12 @@
if delta > agescales[0][1] * 2:
return util.shortdate(date)
- for t, s in agescales:
+ for t, s, a in agescales:
n = delta // s
if n >= 2 or s == 1:
if future:
- return '%s from now' % fmt(t, n)
- return '%s ago' % fmt(t, n)
+ return '%s from now' % fmt(t, n, a)
+ return '%s ago' % fmt(t, n, a)
def basename(path):
""":basename: Any text. Treats the text as a path, and returns the last
@@ -99,7 +101,7 @@
para_re = None
space_re = None
-def fill(text, width, initindent = '', hangindent = ''):
+def fill(text, width, initindent='', hangindent=''):
'''fill many paragraphs with optional indentation.'''
global para_re, space_re
if para_re is None:
--- a/mercurial/templater.py Mon Oct 07 17:47:19 2013 -0400
+++ b/mercurial/templater.py Mon Oct 07 17:47:55 2013 -0400
@@ -139,7 +139,12 @@
def runsymbol(context, mapping, key):
v = mapping.get(key)
if v is None:
- v = context._defaults.get(key, '')
+ v = context._defaults.get(key)
+ if v is None:
+ try:
+ v = context.process(key, mapping)
+ except TemplateNotFound:
+ v = ''
if util.safehasattr(v, '__call__'):
return v(**mapping)
if isinstance(v, types.GeneratorType):
@@ -449,6 +454,9 @@
stylelist.append(split[1])
return ", ".join(sorted(stylelist))
+class TemplateNotFound(util.Abort):
+ pass
+
class templater(object):
def __init__(self, mapfile, filters={}, defaults={}, cache={},
@@ -500,7 +508,8 @@
try:
self.cache[t] = util.readfile(self.map[t][1])
except KeyError, inst:
- raise util.Abort(_('"%s" not in template map') % inst.args[0])
+ raise TemplateNotFound(_('"%s" not in template map') %
+ inst.args[0])
except IOError, inst:
raise IOError(inst.args[0], _('template file %s: %s') %
(self.map[t][1], inst.args[1]))
--- a/mercurial/templates/paper/bookmarks.tmpl Mon Oct 07 17:47:19 2013 -0400
+++ b/mercurial/templates/paper/bookmarks.tmpl Mon Oct 07 17:47:55 2013 -0400
@@ -38,8 +38,7 @@
<form class="search" action="{url|urlescape}log">
{sessionvars%hiddenformentry}
<p><input name="rev" id="search1" type="text" size="30" /></p>
-<div id="hint">find changesets by author, revision,
-files, or words in the commit message</div>
+<div id="hint">{searchhint}</div>
</form>
<table class="bigtable">
--- a/mercurial/templates/paper/branches.tmpl Mon Oct 07 17:47:19 2013 -0400
+++ b/mercurial/templates/paper/branches.tmpl Mon Oct 07 17:47:55 2013 -0400
@@ -38,8 +38,7 @@
<form class="search" action="{url|urlescape}log">
{sessionvars%hiddenformentry}
<p><input name="rev" id="search1" type="text" size="30" /></p>
-<div id="hint">find changesets by author, revision,
-files, or words in the commit message</div>
+<div id="hint">{searchhint}</div>
</form>
<table class="bigtable">
--- a/mercurial/templates/paper/changeset.tmpl Mon Oct 07 17:47:19 2013 -0400
+++ b/mercurial/templates/paper/changeset.tmpl Mon Oct 07 17:47:55 2013 -0400
@@ -36,8 +36,7 @@
<form class="search" action="{url|urlescape}log">
{sessionvars%hiddenformentry}
<p><input name="rev" id="search1" type="text" size="30" /></p>
-<div id="hint">find changesets by author, revision,
-files, or words in the commit message</div>
+<div id="hint">{searchhint}</div>
</form>
<div class="description">{desc|strip|escape|websub|nonempty}</div>
--- a/mercurial/templates/paper/error.tmpl Mon Oct 07 17:47:19 2013 -0400
+++ b/mercurial/templates/paper/error.tmpl Mon Oct 07 17:47:55 2013 -0400
@@ -29,8 +29,7 @@
<form class="search" action="{url|urlescape}log">
{sessionvars%hiddenformentry}
<p><input name="rev" id="search1" type="text" size="30"></p>
-<div id="hint">find changesets by author, revision,
-files, or words in the commit message</div>
+<div id="hint">{searchhint}</div>
</form>
<div class="description">
--- a/mercurial/templates/paper/fileannotate.tmpl Mon Oct 07 17:47:19 2013 -0400
+++ b/mercurial/templates/paper/fileannotate.tmpl Mon Oct 07 17:47:55 2013 -0400
@@ -42,8 +42,7 @@
<form class="search" action="{url|urlescape}log">
{sessionvars%hiddenformentry}
<p><input name="rev" id="search1" type="text" size="30" /></p>
-<div id="hint">find changesets by author, revision,
-files, or words in the commit message</div>
+<div id="hint">{searchhint}</div>
</form>
<div class="description">{desc|strip|escape|websub|nonempty}</div>
@@ -65,7 +64,6 @@
<th class="author">children</th>
<td class="author">{child%filerevchild}</td>
</tr>
-{changesettag}
</table>
<div class="overflow">
--- a/mercurial/templates/paper/filecomparison.tmpl Mon Oct 07 17:47:19 2013 -0400
+++ b/mercurial/templates/paper/filecomparison.tmpl Mon Oct 07 17:47:55 2013 -0400
@@ -41,8 +41,7 @@
<form class="search" action="{url|urlescape}log">
<p>{sessionvars%hiddenformentry}</p>
<p><input name="rev" id="search1" type="text" size="30" /></p>
-<div id="hint">find changesets by author, revision,
-files, or words in the commit message</div>
+<div id="hint">{searchhint}</div>
</form>
<div class="description">{desc|strip|escape|websub|nonempty}</div>
@@ -64,7 +63,6 @@
<th>children</th>
<td>{child%filerevchild}</td>
</tr>
-{changesettag}
</table>
<div class="overflow">
--- a/mercurial/templates/paper/filediff.tmpl Mon Oct 07 17:47:19 2013 -0400
+++ b/mercurial/templates/paper/filediff.tmpl Mon Oct 07 17:47:55 2013 -0400
@@ -41,8 +41,7 @@
<form class="search" action="{url|urlescape}log">
<p>{sessionvars%hiddenformentry}</p>
<p><input name="rev" id="search1" type="text" size="30" /></p>
-<div id="hint">find changesets by author, revision,
-files, or words in the commit message</div>
+<div id="hint">{searchhint}</div>
</form>
<div class="description">{desc|strip|escape|websub|nonempty}</div>
@@ -64,7 +63,6 @@
<th>children</th>
<td>{child%filerevchild}</td>
</tr>
-{changesettag}
</table>
<div class="overflow">
--- a/mercurial/templates/paper/filelog.tmpl Mon Oct 07 17:47:19 2013 -0400
+++ b/mercurial/templates/paper/filelog.tmpl Mon Oct 07 17:47:55 2013 -0400
@@ -49,8 +49,7 @@
<form class="search" action="{url|urlescape}log">
{sessionvars%hiddenformentry}
<p><input name="rev" id="search1" type="text" size="30" /></p>
-<div id="hint">find changesets by author, revision,
-files, or words in the commit message</div>
+<div id="hint">{searchhint}</div>
</form>
<div class="navigate">
--- a/mercurial/templates/paper/filerevision.tmpl Mon Oct 07 17:47:19 2013 -0400
+++ b/mercurial/templates/paper/filerevision.tmpl Mon Oct 07 17:47:55 2013 -0400
@@ -40,8 +40,7 @@
<form class="search" action="{url|urlescape}log">
{sessionvars%hiddenformentry}
<p><input name="rev" id="search1" type="text" size="30" /></p>
-<div id="hint">find changesets by author, revision,
-files, or words in the commit message</div>
+<div id="hint">{searchhint}</div>
</form>
<div class="description">{desc|strip|escape|websub|nonempty}</div>
@@ -63,7 +62,6 @@
<th class="author">children</th>
<td class="author">{child%filerevchild}</td>
</tr>
-{changesettag}
</table>
<div class="overflow">
--- a/mercurial/templates/paper/graph.tmpl Mon Oct 07 17:47:19 2013 -0400
+++ b/mercurial/templates/paper/graph.tmpl Mon Oct 07 17:47:55 2013 -0400
@@ -43,8 +43,7 @@
<form class="search" action="{url|urlescape}log">
{sessionvars%hiddenformentry}
<p><input name="rev" id="search1" type="text" size="30" /></p>
-<div id="hint">find changesets by author, revision,
-files, or words in the commit message</div>
+<div id="hint">{searchhint}</div>
</form>
<div class="navigate">
@@ -123,6 +122,17 @@
| rev {rev}: {changenav%navgraph}
</div>
+<script type="text/javascript">
+ ajaxScrollInit(
+ '{url|urlescape}graph/{rev}?revcount=%next%',
+ {revcount}+60,
+ function (htmlText, previousVal) \{ return previousVal + 60; },
+ '#wrapper',
+ '<div class="%class%" style="text-align: center;">%text%</div>',
+ 'graph'
+ );
+</script>
+
</div>
</div>
--- a/mercurial/templates/paper/help.tmpl Mon Oct 07 17:47:19 2013 -0400
+++ b/mercurial/templates/paper/help.tmpl Mon Oct 07 17:47:55 2013 -0400
@@ -28,8 +28,7 @@
<form class="search" action="{url|urlescape}log">
{sessionvars%hiddenformentry}
<p><input name="rev" id="search1" type="text" size="30" /></p>
-<div id="hint">find changesets by author, revision,
-files, or words in the commit message</div>
+<div id="hint">{searchhint}</div>
</form>
<div id="doc">
{rstdoc(doc, "html")}
--- a/mercurial/templates/paper/helptopics.tmpl Mon Oct 07 17:47:19 2013 -0400
+++ b/mercurial/templates/paper/helptopics.tmpl Mon Oct 07 17:47:55 2013 -0400
@@ -26,8 +26,7 @@
<form class="search" action="{url|urlescape}log">
{sessionvars%hiddenformentry}
<p><input name="rev" id="search1" type="text" size="30" /></p>
-<div id="hint">find changesets by author, revision,
-files, or words in the commit message</div>
+<div id="hint">{searchhint}</div>
</form>
<table class="bigtable">
<tr><td colspan="2"><h2><a name="main" href="#topics">Topics</a></h2></td></tr>
--- a/mercurial/templates/paper/manifest.tmpl Mon Oct 07 17:47:19 2013 -0400
+++ b/mercurial/templates/paper/manifest.tmpl Mon Oct 07 17:47:55 2013 -0400
@@ -35,8 +35,7 @@
<form class="search" action="{url|urlescape}log">
{sessionvars%hiddenformentry}
<p><input name="rev" id="search1" type="text" size="30" /></p>
-<div id="hint">find changesets by author, revision,
-files, or words in the commit message</div>
+<div id="hint">{searchhint}</div>
</form>
<table class="bigtable">
--- a/mercurial/templates/paper/map Mon Oct 07 17:47:19 2013 -0400
+++ b/mercurial/templates/paper/map Mon Oct 07 17:47:55 2013 -0400
@@ -243,3 +243,6 @@
urlparameter = '{separator}{name}={value|urlescape}'
hiddenformentry = '<input type="hidden" name="{name}" value="{value|escape}" />'
breadcrumb = '> <a href="{url|urlescape}">{name|escape}</a> '
+
+searchhint = 'Find changesets by keywords (author, files, the commit message), revision
+ number or hash, or <a href="{url|urlescape}help/revsets">revset expression</a>.'
--- a/mercurial/templates/paper/search.tmpl Mon Oct 07 17:47:19 2013 -0400
+++ b/mercurial/templates/paper/search.tmpl Mon Oct 07 17:47:55 2013 -0400
@@ -23,11 +23,18 @@
<h2 class="breadcrumb"><a href="/">Mercurial</a> {pathdef%breadcrumb}</h2>
<h3>searching for '{query|escape}'</h3>
+<p>
+Assuming {modedesc}.
+{if(showforcekw, '<a href="{url|urlescape}log?rev={query|urlescape}&forcekw=1">
+Use {showforcekw}</a> instead.')}
+{if(showunforcekw, '<a href="{url|urlescape}log?rev={query|urlescape}">
+Use {showunforcekw}</a> instead.')}
+</p>
+
<form class="search" action="{url|urlescape}log">
{sessionvars%hiddenformentry}
<p><input name="rev" id="search1" type="text" size="30" value="{query|escape}"></p>
-<div id="hint">find changesets by author, revision,
-files, or words in the commit message</div>
+<div id="hint">{searchhint}</div>
</form>
<div class="navigate">
--- a/mercurial/templates/paper/shortlog.tmpl Mon Oct 07 17:47:19 2013 -0400
+++ b/mercurial/templates/paper/shortlog.tmpl Mon Oct 07 17:47:55 2013 -0400
@@ -45,8 +45,7 @@
<form class="search" action="{url|urlescape}log">
{sessionvars%hiddenformentry}
<p><input name="rev" id="search1" type="text" size="30" value="{query|escape}" /></p>
-<div id="hint">find changesets by author, revision,
-files, or words in the commit message</div>
+<div id="hint">{searchhint}</div>
</form>
<div class="navigate">
@@ -72,6 +71,21 @@
| rev {rev}: {changenav%navshort}
</div>
+<script type="text/javascript">
+ ajaxScrollInit(
+ '{url|urlescape}shortlog/%next%',
+ '{nextentry%"{node}"}', <!-- NEXTHASH
+ function (htmlText, previousVal) \{
+ var m = htmlText.match(/'(\w+)', <!-- NEXTHASH/);
+ return m ? m[1] : null;
+ },
+ '.bigtable > tbody:nth-of-type(2)',
+ '<tr class="%class%">\
+ <td colspan="3" style="text-align: center;">%text%</td>\
+ </tr>'
+ );
+</script>
+
</div>
</div>
--- a/mercurial/templates/paper/shortlogentry.tmpl Mon Oct 07 17:47:19 2013 -0400
+++ b/mercurial/templates/paper/shortlogentry.tmpl Mon Oct 07 17:47:55 2013 -0400
@@ -1,5 +1,5 @@
<tr>
<td class="age">{date|rfc822date}</td>
<td class="author">{author|person}</td>
- <td class="description"><a href="{url|urlescape}rev/{node|short}{sessionvars%urlparameter}">{desc|strip|firstline|escape|nonempty}</a>{inbranch%changelogbranchname}{branches%changelogbranchhead}{tags % '<span class="tag">{name|escape}</span> '}{bookmarks % '<span class="tag">{name|escape}</span> '}</td>
+ <td class="description"><a href="{url|urlescape}rev/{node|short}{sessionvars%urlparameter}">{desc|strip|firstline|escape|nonempty}</a>{inbranch%changelogbranchname}{branches%changelogbranchhead}{tags%changelogtag}{bookmarks%changelogtag}</td>
</tr>
--- a/mercurial/templates/paper/tags.tmpl Mon Oct 07 17:47:19 2013 -0400
+++ b/mercurial/templates/paper/tags.tmpl Mon Oct 07 17:47:55 2013 -0400
@@ -37,8 +37,7 @@
<form class="search" action="{url|urlescape}log">
{sessionvars%hiddenformentry}
<p><input name="rev" id="search1" type="text" size="30" /></p>
-<div id="hint">find changesets by author, revision,
-files, or words in the commit message</div>
+<div id="hint">{searchhint}</div>
</form>
<table class="bigtable">
--- a/mercurial/templates/raw/search.tmpl Mon Oct 07 17:47:19 2013 -0400
+++ b/mercurial/templates/raw/search.tmpl Mon Oct 07 17:47:55 2013 -0400
@@ -2,5 +2,6 @@
# HG changesets search
# Node ID {node}
# Query "{query}"
+# Mode {modedesc}
{entries%changelogentry}
--- a/mercurial/templates/static/mercurial.js Mon Oct 07 17:47:19 2013 -0400
+++ b/mercurial/templates/static/mercurial.js Mon Oct 07 17:47:55 2013 -0400
@@ -23,7 +23,7 @@
];
function Graph() {
-
+
this.canvas = document.getElementById('graph');
if (window.G_vmlCanvasManager) this.canvas = window.G_vmlCanvasManager.initElement(this.canvas);
this.ctx = this.canvas.getContext('2d');
@@ -35,13 +35,21 @@
this.cell = [2, 0];
this.columns = 0;
this.revlink = '';
-
+
+ this.reset = function() {
+ this.bg = [0, 4];
+ this.cell = [2, 0];
+ this.columns = 0;
+ document.getElementById('nodebgs').innerHTML = '';
+ document.getElementById('graphnodes').innerHTML = '';
+ }
+
this.scale = function(height) {
this.bg_height = height;
this.box_size = Math.floor(this.bg_height / 1.2);
this.cell_height = this.box_size;
}
-
+
function colorPart(num) {
num *= 255
num = num < 0 ? 0 : num;
@@ -55,7 +63,7 @@
}
this.setColor = function(color, bg, fg) {
-
+
// Set the colour.
//
// If color is a string, expect an hexadecimal RGB
@@ -81,11 +89,11 @@
this.ctx.strokeStyle = s;
this.ctx.fillStyle = s;
return s;
-
+
}
this.edge = function(x0, y0, x1, y1, color, width) {
-
+
this.setColor(color, 0.0, 0.65);
if(width >= 0)
this.ctx.lineWidth = width;
@@ -93,28 +101,28 @@
this.ctx.moveTo(x0, y0);
this.ctx.lineTo(x1, y1);
this.ctx.stroke();
-
+
}
this.render = function(data) {
-
+
var backgrounds = '';
var nodedata = '';
-
+
for (var i in data) {
-
+
var parity = i % 2;
this.cell[1] += this.bg_height;
this.bg[1] += this.bg_height;
-
+
var cur = data[i];
var node = cur[1];
var edges = cur[2];
var fold = false;
-
+
var prevWidth = this.ctx.lineWidth;
for (var j in edges) {
-
+
line = edges[j];
start = line[0];
end = line[1];
@@ -125,50 +133,50 @@
var branchcolor = line[4];
if(branchcolor)
color = branchcolor;
-
+
if (end > this.columns || start > this.columns) {
this.columns += 1;
}
-
+
if (start == this.columns && start > end) {
var fold = true;
}
-
+
x0 = this.cell[0] + this.box_size * start + this.box_size / 2;
y0 = this.bg[1] - this.bg_height / 2;
x1 = this.cell[0] + this.box_size * end + this.box_size / 2;
y1 = this.bg[1] + this.bg_height / 2;
-
+
this.edge(x0, y0, x1, y1, color, width);
-
+
}
this.ctx.lineWidth = prevWidth;
-
+
// Draw the revision node in the right column
-
+
column = node[0]
color = node[1]
-
+
radius = this.box_size / 8;
x = this.cell[0] + this.box_size * column + this.box_size / 2;
y = this.bg[1] - this.bg_height / 2;
var add = this.vertex(x, y, color, parity, cur);
backgrounds += add[0];
nodedata += add[1];
-
+
if (fold) this.columns -= 1;
-
+
}
-
+
document.getElementById('nodebgs').innerHTML += backgrounds;
document.getElementById('graphnodes').innerHTML += nodedata;
-
+
}
}
-process_dates = (function(document, RegExp, Math, isNaN, Date, _false, _true){
+function process_dates(parentSelector){
// derived from code from mercurial/templatefilter.py
@@ -219,9 +227,9 @@
var delta = Math.floor((now.getTime() - once.getTime()) / 1000);
- var future = _false;
+ var future = false;
if (delta < 0){
- future = _true;
+ future = true;
delta = -delta;
if (delta > (30 * scales.year)){
return "in the distant future";
@@ -245,25 +253,21 @@
}
}
- return function(){
- var nodes = document.getElementsByTagName('*');
- var ageclass = new RegExp('\\bage\\b');
- var dateclass = new RegExp('\\bdate\\b');
- for (var i=0; i<nodes.length; ++i){
- var node = nodes[i];
- var classes = node.className;
- if (ageclass.test(classes)){
- var agevalue = age(node.textContent);
- if (dateclass.test(classes)){
- // We want both: date + (age)
- node.textContent += ' ('+agevalue+')';
- } else {
- node.textContent = agevalue;
- }
- }
+ var nodes = document.querySelectorAll((parentSelector || '') + ' .age');
+ var dateclass = new RegExp('\\bdate\\b');
+ for (var i=0; i<nodes.length; ++i){
+ var node = nodes[i];
+ var classes = node.className;
+ var agevalue = age(node.textContent);
+ if (dateclass.test(classes)){
+ // We want both: date + (age)
+ node.textContent += ' ('+agevalue+')';
+ } else {
+ node.title = node.textContent;
+ node.textContent = agevalue;
}
}
-})(document, RegExp, Math, isNaN, Date, false, true)
+}
function toggleDiffstat() {
var curdetails = document.getElementById('diffstatdetails').style.display;
@@ -297,3 +301,139 @@
setLinewrap(!getLinewrap());
}
+
+function format(str, replacements) {
+ return str.replace(/%(\w+)%/g, function(match, p1) {
+ return String(replacements[p1]);
+ });
+}
+
+function makeRequest(url, method, onstart, onsuccess, onerror, oncomplete) {
+ xfr = new XMLHttpRequest();
+ xfr.onreadystatechange = function() {
+ if (xfr.readyState === 4) {
+ try {
+ if (xfr.status === 200) {
+ onsuccess(xfr.responseText);
+ } else {
+ throw 'server error';
+ }
+ } catch (e) {
+ onerror(e);
+ } finally {
+ oncomplete();
+ }
+ }
+ };
+
+ xfr.open(method, url);
+ xfr.send();
+ onstart();
+ return xfr;
+}
+
+function removeByClassName(className) {
+ var nodes = document.getElementsByClassName(className);
+ while (nodes.length) {
+ nodes[0].parentNode.removeChild(nodes[0]);
+ }
+}
+
+function docFromHTML(html) {
+ var doc = document.implementation.createHTMLDocument('');
+ doc.documentElement.innerHTML = html;
+ return doc;
+}
+
+function appendFormatHTML(element, formatStr, replacements) {
+ element.insertAdjacentHTML('beforeend', format(formatStr, replacements));
+}
+
+function ajaxScrollInit(urlFormat,
+ nextPageVar,
+ nextPageVarGet,
+ containerSelector,
+ messageFormat,
+ mode) {
+ updateInitiated = false;
+ container = document.querySelector(containerSelector);
+
+ function scrollHandler() {
+ if (updateInitiated) {
+ return;
+ }
+
+ var scrollHeight = document.documentElement.scrollHeight;
+ var clientHeight = document.documentElement.clientHeight;
+ var scrollTop = document.body.scrollTop
+ || document.documentElement.scrollTop;
+
+ if (scrollHeight - (scrollTop + clientHeight) < 50) {
+ updateInitiated = true;
+ removeByClassName('scroll-loading-error');
+ container.lastElementChild.classList.add('scroll-separator');
+
+ if (!nextPageVar) {
+ var message = {
+ class: 'scroll-loading-info',
+ text: 'No more entries'
+ };
+ appendFormatHTML(container, messageFormat, message);
+ return;
+ }
+
+ makeRequest(
+ format(urlFormat, {next: nextPageVar}),
+ 'GET',
+ function onstart() {
+ var message = {
+ class: 'scroll-loading',
+ text: 'Loading...'
+ };
+ appendFormatHTML(container, messageFormat, message);
+ },
+ function onsuccess(htmlText) {
+ nextPageVar = nextPageVarGet(htmlText, nextPageVar);
+
+ if (mode == 'graph') {
+ var addHeight = htmlText.match(/^<canvas id="graph".*height="(\d+)"><\/canvas>$/m)[1];
+ addHeight = parseInt(addHeight);
+ graph.canvas.height = addHeight;
+
+ var dataStr = htmlText.match(/^\s*var data = (.*);$/m)[1];
+ var data = JSON.parse(dataStr)
+ graph.reset();
+ graph.render(data);
+ } else {
+ var doc = docFromHTML(htmlText);
+ var nodes = doc.querySelector(containerSelector).children;
+ var curClass = 'c' + Date.now();
+ while (nodes.length) {
+ var node = nodes[0];
+ node = document.adoptNode(node);
+ node.classList.add(curClass);
+ container.appendChild(node);
+ }
+ process_dates('.' + curClass);
+ }
+ },
+ function onerror(errorText) {
+ var message = {
+ class: 'scroll-loading-error',
+ text: 'Error: ' + errorText
+ };
+ appendFormatHTML(container, messageFormat, message);
+ },
+ function oncomplete() {
+ removeByClassName('scroll-loading');
+ updateInitiated = false;
+ scrollHandler();
+ }
+ );
+ }
+ }
+
+ window.addEventListener('scroll', scrollHandler);
+ window.addEventListener('resize', scrollHandler);
+ scrollHandler();
+}
--- a/mercurial/templates/static/style-paper.css Mon Oct 07 17:47:19 2013 -0400
+++ b/mercurial/templates/static/style-paper.css Mon Oct 07 17:47:55 2013 -0400
@@ -382,3 +382,27 @@
.breadcrumb a {
color: blue;
}
+
+.scroll-loading {
+ -webkit-animation: change_color 1s linear 0s infinite alternate;
+ -moz-animation: change_color 1s linear 0s infinite alternate;
+ -o-animation: change_color 1s linear 0s infinite alternate;
+ animation: change_color 1s linear 0s infinite alternate;
+}
+
+@-webkit-keyframes change_color {
+ from { background-color: #A0CEFF; } to { }
+}
+@-moz-keyframes change_color {
+ from { background-color: #A0CEFF; } to { }
+}
+@-o-keyframes change_color {
+ from { background-color: #A0CEFF; } to { }
+}
+@keyframes change_color {
+ from { background-color: #A0CEFF; } to { }
+}
+
+.scroll-loading-error {
+ background-color: #FFCCCC !important;
+}
--- a/mercurial/ui.py Mon Oct 07 17:47:19 2013 -0400
+++ b/mercurial/ui.py Mon Oct 07 17:47:55 2013 -0400
@@ -176,7 +176,7 @@
alternates = [name]
for n in alternates:
- value = self._data(untrusted).get(section, name, None)
+ value = self._data(untrusted).get(section, n, None)
if value is not None:
name = n
break
@@ -184,10 +184,11 @@
value = default
if self.debugflag and not untrusted and self._reportuntrusted:
- uvalue = self._ucfg.get(section, name)
- if uvalue is not None and uvalue != value:
- self.debug("ignoring untrusted configuration option "
- "%s.%s = %s\n" % (section, name, uvalue))
+ for n in alternates:
+ uvalue = self._ucfg.get(section, n)
+ if uvalue is not None and uvalue != value:
+ self.debug("ignoring untrusted configuration option "
+ "%s.%s = %s\n" % (section, n, uvalue))
return value
def configpath(self, section, name, default=None, untrusted=False):
--- a/mercurial/unionrepo.py Mon Oct 07 17:47:19 2013 -0400
+++ b/mercurial/unionrepo.py Mon Oct 07 17:47:55 2013 -0400
@@ -70,7 +70,7 @@
self.revlog2.rev(self.node(rev1)),
self.revlog2.rev(self.node(rev2)))
elif rev1 <= self.repotiprev and rev2 <= self.repotiprev:
- return revlog.revlog.revdiff(self, rev1, rev2)
+ return self.baserevdiff(rev1, rev2)
return mdiff.textdiff(self.revision(self.node(rev1)),
self.revision(self.node(rev2)))
@@ -93,10 +93,20 @@
text = self.revlog2.revision(node)
self._cache = (node, rev, text)
else:
- text = revlog.revlog.revision(self, rev)
+ text = self.baserevision(rev)
# already cached
return text
+ def baserevision(self, nodeorrev):
+ # Revlog subclasses may override 'revision' method to modify format of
+ # content retrieved from revlog. To use unionrevlog with such class one
+ # needs to override 'baserevision' and make more specific call here.
+ return revlog.revlog.revision(self, nodeorrev)
+
+ def baserevdiff(self, rev1, rev2):
+ # Exists for the same purpose as baserevision.
+ return revlog.revlog.revdiff(self, rev1, rev2)
+
def addrevision(self, text, transaction, link, p1=None, p2=None, d=None):
raise NotImplementedError
def addgroup(self, revs, linkmapper, transaction):
@@ -114,6 +124,15 @@
unionrevlog.__init__(self, opener, self.indexfile, changelog2,
linkmapper)
+ def baserevision(self, nodeorrev):
+ # Although changelog doesn't override 'revision' method, some extensions
+ # may replace this class with another that does. Same story with
+ # manifest and filelog classes.
+ return changelog.changelog.revision(self, nodeorrev)
+
+ def baserevdiff(self, rev1, rev2):
+ return changelog.changelog.revdiff(self, rev1, rev2)
+
class unionmanifest(unionrevlog, manifest.manifest):
def __init__(self, opener, opener2, linkmapper):
manifest.manifest.__init__(self, opener)
@@ -121,6 +140,12 @@
unionrevlog.__init__(self, opener, self.indexfile, manifest2,
linkmapper)
+ def baserevision(self, nodeorrev):
+ return manifest.manifest.revision(self, nodeorrev)
+
+ def baserevdiff(self, rev1, rev2):
+ return manifest.manifest.revdiff(self, rev1, rev2)
+
class unionfilelog(unionrevlog, filelog.filelog):
def __init__(self, opener, path, opener2, linkmapper, repo):
filelog.filelog.__init__(self, opener, path)
@@ -129,6 +154,12 @@
linkmapper)
self._repo = repo
+ def baserevision(self, nodeorrev):
+ return filelog.filelog.revision(self, nodeorrev)
+
+ def baserevdiff(self, rev1, rev2):
+ return filelog.filelog.revdiff(self, rev1, rev2)
+
def _file(self, f):
self._repo.file(f)
--- a/mercurial/url.py Mon Oct 07 17:47:19 2013 -0400
+++ b/mercurial/url.py Mon Oct 07 17:47:55 2013 -0400
@@ -108,8 +108,13 @@
def proxy_open(self, req, proxy, type_):
host = req.get_host().split(':')[0]
- if host in self.no_list:
- return None
+ for e in self.no_list:
+ if host == e:
+ return None
+ if e.startswith('*.') and host.endswith(e[2:]):
+ return None
+ if e.startswith('.') and host.endswith(e[1:]):
+ return None
# work around a bug in Python < 2.4.2
# (it leaves a "\n" at the end of Proxy-authorization headers)
--- a/mercurial/util.h Mon Oct 07 17:47:19 2013 -0400
+++ b/mercurial/util.h Mon Oct 07 17:47:55 2013 -0400
@@ -121,7 +121,12 @@
#ifdef _MSC_VER
/* msvc 6.0 has problems */
#define inline __inline
+typedef signed char int8_t;
+typedef short int16_t;
+typedef long int32_t;
+typedef __int64 int64_t;
typedef unsigned char uint8_t;
+typedef unsigned short uint16_t;
typedef unsigned long uint32_t;
typedef unsigned __int64 uint64_t;
#else
--- a/mercurial/util.py Mon Oct 07 17:47:19 2013 -0400
+++ b/mercurial/util.py Mon Oct 07 17:47:55 2013 -0400
@@ -242,6 +242,10 @@
def __contains__(self, key):
return key in self._cache
+ def clear(self):
+ self._cache.clear()
+ self._order = deque()
+
def lrucachefunc(func):
'''cache most recent results of function calls'''
cache = {}
@@ -466,7 +470,8 @@
return str(val)
origcmd = cmd
cmd = quotecommand(cmd)
- if sys.platform == 'plan9':
+ if sys.platform == 'plan9' and (sys.version_info[0] == 2
+ and sys.version_info[1] < 7):
# subprocess kludge to work around issues in half-baked Python
# ports, notably bichued/python:
if not cwd is None:
--- a/setup.py Mon Oct 07 17:47:19 2013 -0400
+++ b/setup.py Mon Oct 07 17:47:55 2013 -0400
@@ -423,14 +423,21 @@
pymodules = []
+common_depends = ['mercurial/util.h']
+
extmodules = [
- Extension('mercurial.base85', ['mercurial/base85.c']),
- Extension('mercurial.bdiff', ['mercurial/bdiff.c']),
- Extension('mercurial.diffhelpers', ['mercurial/diffhelpers.c']),
- Extension('mercurial.mpatch', ['mercurial/mpatch.c']),
+ Extension('mercurial.base85', ['mercurial/base85.c'],
+ depends=common_depends),
+ Extension('mercurial.bdiff', ['mercurial/bdiff.c'],
+ depends=common_depends),
+ Extension('mercurial.diffhelpers', ['mercurial/diffhelpers.c'],
+ depends=common_depends),
+ Extension('mercurial.mpatch', ['mercurial/mpatch.c'],
+ depends=common_depends),
Extension('mercurial.parsers', ['mercurial/dirs.c',
'mercurial/parsers.c',
- 'mercurial/pathencode.c']),
+ 'mercurial/pathencode.c'],
+ depends=common_depends),
]
osutil_ldflags = []
@@ -443,7 +450,8 @@
pymodules.append('mercurial.pure.osutil')
else:
extmodules.append(Extension('mercurial.osutil', ['mercurial/osutil.c'],
- extra_link_args=osutil_ldflags))
+ extra_link_args=osutil_ldflags,
+ depends=common_depends))
# the -mno-cygwin option has been deprecated for years
Mingw32CCompiler = cygwinccompiler.Mingw32CCompiler
@@ -467,7 +475,8 @@
if hasfunction(cc, 'inotify_add_watch'):
inotify = Extension('hgext.inotify.linux._inotify',
['hgext/inotify/linux/_inotify.c'],
- ['mercurial'])
+ ['mercurial'],
+ depends=common_depends)
inotify.optional = True
extmodules.append(inotify)
packages.extend(['hgext.inotify', 'hgext.inotify.linux'])
--- a/tests/filterpyflakes.py Mon Oct 07 17:47:19 2013 -0400
+++ b/tests/filterpyflakes.py Mon Oct 07 17:47:55 2013 -0400
@@ -46,6 +46,6 @@
continue
lines.append((msgtype, line))
-for msgtype, line in sorted(lines, key = makekey):
+for msgtype, line in sorted(lines, key=makekey):
sys.stdout.write(line)
print
--- a/tests/get-with-headers.py Mon Oct 07 17:47:19 2013 -0400
+++ b/tests/get-with-headers.py Mon Oct 07 17:47:55 2013 -0400
@@ -43,8 +43,9 @@
print "%s: %s" % (h, response.getheader(h))
if not headeronly:
print
- data = response.read()
- sys.stdout.write(data)
+ if response.status != 500:
+ data = response.read()
+ sys.stdout.write(data)
if twice and response.getheader('ETag', None):
tag = response.getheader('ETag')
--- a/tests/run-tests.py Mon Oct 07 17:47:19 2013 -0400
+++ b/tests/run-tests.py Mon Oct 07 17:47:55 2013 -0400
@@ -341,6 +341,7 @@
hgrc.write('[defaults]\n')
hgrc.write('backout = -d "0 0"\n')
hgrc.write('commit = -d "0 0"\n')
+ hgrc.write('shelve = --date "0 0"\n')
hgrc.write('tag = -d "0 0"\n')
if options.inotify:
hgrc.write('[extensions]\n')
@@ -460,6 +461,9 @@
if options.compiler:
compiler = '--compiler ' + options.compiler
pure = options.pure and "--pure" or ""
+ py3 = ''
+ if sys.version_info[0] == 3:
+ py3 = '--c2to3'
# Run installer in hg root
script = os.path.realpath(sys.argv[0])
@@ -472,11 +476,11 @@
# least on Windows for now, deal with .pydistutils.cfg bugs
# when they happen.
nohome = ''
- cmd = ('%(exe)s setup.py %(pure)s clean --all'
+ cmd = ('%(exe)s setup.py %(py3)s %(pure)s clean --all'
' build %(compiler)s --build-base="%(base)s"'
' install --force --prefix="%(prefix)s" --install-lib="%(libdir)s"'
' --install-scripts="%(bindir)s" %(nohome)s >%(logfile)s 2>&1'
- % dict(exe=sys.executable, pure=pure, compiler=compiler,
+ % dict(exe=sys.executable, py3=py3, pure=pure, compiler=compiler,
base=os.path.join(HGTMP, "build"),
prefix=INST, libdir=PYTHONDIR, bindir=BINDIR,
nohome=nohome, logfile=installerrs))
@@ -758,21 +762,19 @@
addsalt(n + 1, False)
# Write out the script and execute it
- fd, name = tempfile.mkstemp(suffix='hg-tst')
- try:
- for l in script:
- os.write(fd, l)
- os.close(fd)
+ name = wd + '.sh'
+ f = open(name, 'w')
+ for l in script:
+ f.write(l)
+ f.close()
- cmd = '%s "%s"' % (options.shell, name)
- vlog("# Running", cmd)
- exitcode, output = run(cmd, wd, options, replacements, env)
- # do not merge output if skipped, return hghave message instead
- # similarly, with --debug, output is None
- if exitcode == SKIPPED_STATUS or output is None:
- return exitcode, output
- finally:
- os.remove(name)
+ cmd = '%s "%s"' % (options.shell, name)
+ vlog("# Running", cmd)
+ exitcode, output = run(cmd, wd, options, replacements, env)
+ # do not merge output if skipped, return hghave message instead
+ # similarly, with --debug, output is None
+ if exitcode == SKIPPED_STATUS or output is None:
+ return exitcode, output
# Merge the script output back into a unified test
@@ -921,8 +923,10 @@
else:
return ignore("doesn't match keyword")
+ if not lctest.startswith("test-"):
+ return skip("not a test file")
for ext, func, out in testtypes:
- if lctest.startswith("test-") and lctest.endswith(ext):
+ if lctest.endswith(ext):
runner = func
ref = os.path.join(TESTDIR, test + out)
break
@@ -1043,7 +1047,7 @@
if _hgpath is not None:
return _hgpath
- cmd = '%s -c "import mercurial; print mercurial.__path__[0]"'
+ cmd = '%s -c "import mercurial; print (mercurial.__path__[0])"'
pipe = os.popen(cmd % PYTHON)
try:
_hgpath = pipe.read().strip()
--- a/tests/test-archive.t Mon Oct 07 17:47:19 2013 -0400
+++ b/tests/test-archive.t Mon Oct 07 17:47:55 2013 -0400
@@ -209,8 +209,7 @@
test-2c0277f05ed4/foo
$ hg archive -r 0 -t tar rev-%r.tar
- $ if [ -f rev-0.tar ]; then
- $ fi
+ $ [ -f rev-0.tar ]
test .hg_archival.txt
--- a/tests/test-casecollision-merge.t Mon Oct 07 17:47:19 2013 -0400
+++ b/tests/test-casecollision-merge.t Mon Oct 07 17:47:55 2013 -0400
@@ -293,7 +293,7 @@
[255]
$ hg update --check
- abort: uncommitted local changes
+ abort: uncommitted changes
[255]
$ hg update --clean
--- a/tests/test-command-template.t Mon Oct 07 17:47:19 2013 -0400
+++ b/tests/test-command-template.t Mon Oct 07 17:47:55 2013 -0400
@@ -500,6 +500,28 @@
1
0
+Missing non-standard names give no error (backward compatibility):
+
+ $ echo "changeset = '{c}'" > t
+ $ hg log --style ./t
+
+Defining non-standard name works:
+
+ $ cat <<EOF > t
+ > changeset = '{c}'
+ > c = q
+ > EOF
+ $ hg log --style ./t
+ 8
+ 7
+ 6
+ 5
+ 4
+ 3
+ 2
+ 1
+ 0
+
ui.style works:
$ echo '[ui]' > .hg/hgrc
--- a/tests/test-commandserver.py.out Mon Oct 07 17:47:19 2013 -0400
+++ b/tests/test-commandserver.py.out Mon Oct 07 17:47:55 2013 -0400
@@ -73,6 +73,7 @@
bundle.mainreporoot=$TESTTMP
defaults.backout=-d "0 0"
defaults.commit=-d "0 0"
+defaults.shelve=--date "0 0"
defaults.tag=-d "0 0"
ui.slash=True
ui.interactive=False
@@ -81,6 +82,7 @@
runcommand -R foo showconfig ui defaults
defaults.backout=-d "0 0"
defaults.commit=-d "0 0"
+defaults.shelve=--date "0 0"
defaults.tag=-d "0 0"
ui.slash=True
ui.interactive=False
--- a/tests/test-convert-filemap.t Mon Oct 07 17:47:19 2013 -0400
+++ b/tests/test-convert-filemap.t Mon Oct 07 17:47:55 2013 -0400
@@ -88,6 +88,32 @@
copied renamed from foo:2ed2a3912a0b24502043eae84ee4b279c18b90dd
$ cd ..
+
+
+Test interaction with startrev and verify that changing it is handled properly:
+
+ $ > empty
+ $ hg convert --filemap empty source movingstart --config convert.hg.startrev=3 -r4
+ initializing destination movingstart repository
+ scanning source...
+ sorting...
+ converting...
+ 1 3: change bar quux
+ 0 4: first merge; change bar baz
+ $ hg convert --filemap empty source movingstart
+ scanning source...
+ sorting...
+ converting...
+ 3 5: change bar baz quux
+ 2 6: change foo baz
+ 1 7: second merge; change bar
+ warning: af455ce4166b3c9c88e6309c2b9332171dcea595 parent 61e22ca76c3b3e93df20338c4e02ce286898e825 is missing
+ warning: cf908b3eeedc301c9272ebae931da966d5b326c7 parent 59e1ab45c888289513b7354484dac8a88217beab is missing
+ 0 8: change foo
+
+
+splitrepo tests
+
$ splitrepo()
> {
> msg="$1"
@@ -384,6 +410,32 @@
o 0 "addb" files: b
+Test rebuilding of map with unknown revisions in shamap - it used to crash
+
+ $ cd branchpruning
+ $ hg up -r 2
+ 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
+ $ hg merge 4
+ 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
+ (branch merge, don't forget to commit)
+ $ hg ci -m 'merging something'
+ $ cd ..
+ $ echo "53792d18237d2b64971fa571936869156655338d 6d955580116e82c4b029bd30f321323bae71a7f0" >> branchpruning-hg2/.hg/shamap
+ $ hg convert --filemap branchpruning/filemap branchpruning branchpruning-hg2 --debug
+ run hg source pre-conversion action
+ run hg sink pre-conversion action
+ scanning source...
+ scanning: 1 revisions
+ sorting...
+ converting...
+ 0 merging something
+ source: 2503605b178fe50e8fbbb0e77b97939540aa8c87
+ converting: 0/1 revisions (0.00%)
+ unknown revmap source: 53792d18237d2b64971fa571936869156655338d
+ run hg sink post-conversion action
+ run hg source post-conversion action
+
+
filemap rename undoing revision rename
$ hg init renameundo
--- a/tests/test-convert.t Mon Oct 07 17:47:19 2013 -0400
+++ b/tests/test-convert.t Mon Oct 07 17:47:55 2013 -0400
@@ -262,7 +262,7 @@
-s --source-type TYPE source repository type
-d --dest-type TYPE destination repository type
- -r --rev REV import up to target revision REV
+ -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
--splicemap FILE splice synthesized history into place
--- a/tests/test-extension.t Mon Oct 07 17:47:19 2013 -0400
+++ b/tests/test-extension.t Mon Oct 07 17:47:55 2013 -0400
@@ -406,17 +406,21 @@
> EOF
$ echo "debugissue811 = $debugpath" >> $HGRCPATH
$ echo "mq=" >> $HGRCPATH
+ $ echo "strip=" >> $HGRCPATH
$ echo "hgext.mq=" >> $HGRCPATH
$ echo "hgext/mq=" >> $HGRCPATH
Show extensions:
+(note that mq force load strip, also checking it's not loaded twice)
$ hg debugextensions
debugissue811
+ strip
mq
Disabled extension commands:
+ $ ORGHGRCPATH=$HGRCPATH
$ HGRCPATH=
$ export HGRCPATH
$ hg help email
@@ -573,3 +577,134 @@
** Python * (glob)
** Mercurial Distributed SCM (*) (glob)
** Extensions loaded: throw
+
+Restore HGRCPATH
+
+ $ HGRCPATH=$ORGHGRCPATH
+ $ export HGRCPATH
+
+Commands handling multiple repositories at a time should invoke only
+"reposetup()" of extensions enabling in the target repository.
+
+ $ mkdir reposetup-test
+ $ cd reposetup-test
+
+ $ cat > $TESTTMP/reposetuptest.py <<EOF
+ > from mercurial import extensions
+ > def reposetup(ui, repo):
+ > ui.write('reposetup() for %s\n' % (repo.root))
+ > EOF
+ $ hg init src
+ $ echo a > src/a
+ $ hg -R src commit -Am '#0 at src/a'
+ adding a
+ $ echo '[extensions]' >> src/.hg/hgrc
+ $ echo '# enable extension locally' >> src/.hg/hgrc
+ $ echo "reposetuptest = $TESTTMP/reposetuptest.py" >> src/.hg/hgrc
+ $ hg -R src status
+ reposetup() for $TESTTMP/reposetup-test/src
+
+ $ hg clone -U src clone-dst1
+ reposetup() for $TESTTMP/reposetup-test/src
+ $ hg init push-dst1
+ $ hg -q -R src push push-dst1
+ reposetup() for $TESTTMP/reposetup-test/src
+ $ hg init pull-src1
+ $ hg -q -R pull-src1 pull src
+ reposetup() for $TESTTMP/reposetup-test/src
+
+ $ echo '[extensions]' >> $HGRCPATH
+ $ echo '# disable extension globally and explicitly' >> $HGRCPATH
+ $ echo 'reposetuptest = !' >> $HGRCPATH
+ $ hg clone -U src clone-dst2
+ reposetup() for $TESTTMP/reposetup-test/src
+ $ hg init push-dst2
+ $ hg -q -R src push push-dst2
+ reposetup() for $TESTTMP/reposetup-test/src
+ $ hg init pull-src2
+ $ hg -q -R pull-src2 pull src
+ reposetup() for $TESTTMP/reposetup-test/src
+
+ $ echo '[extensions]' >> $HGRCPATH
+ $ echo '# enable extension globally' >> $HGRCPATH
+ $ echo "reposetuptest = $TESTTMP/reposetuptest.py" >> $HGRCPATH
+ $ hg clone -U src clone-dst3
+ reposetup() for $TESTTMP/reposetup-test/src
+ reposetup() for $TESTTMP/reposetup-test/clone-dst3
+ $ hg init push-dst3
+ reposetup() for $TESTTMP/reposetup-test/push-dst3
+ $ hg -q -R src push push-dst3
+ reposetup() for $TESTTMP/reposetup-test/src
+ reposetup() for $TESTTMP/reposetup-test/push-dst3
+ $ hg init pull-src3
+ reposetup() for $TESTTMP/reposetup-test/pull-src3
+ $ hg -q -R pull-src3 pull src
+ reposetup() for $TESTTMP/reposetup-test/pull-src3
+ reposetup() for $TESTTMP/reposetup-test/src
+
+ $ echo '[extensions]' >> src/.hg/hgrc
+ $ echo '# disable extension locally' >> src/.hg/hgrc
+ $ echo 'reposetuptest = !' >> src/.hg/hgrc
+ $ hg clone -U src clone-dst4
+ reposetup() for $TESTTMP/reposetup-test/clone-dst4
+ $ hg init push-dst4
+ reposetup() for $TESTTMP/reposetup-test/push-dst4
+ $ hg -q -R src push push-dst4
+ reposetup() for $TESTTMP/reposetup-test/push-dst4
+ $ hg init pull-src4
+ reposetup() for $TESTTMP/reposetup-test/pull-src4
+ $ hg -q -R pull-src4 pull src
+ reposetup() for $TESTTMP/reposetup-test/pull-src4
+
+disabling in command line overlays with all configuration
+ $ hg --config extensions.reposetuptest=! clone -U src clone-dst5
+ $ hg --config extensions.reposetuptest=! init push-dst5
+ $ hg --config extensions.reposetuptest=! -q -R src push push-dst5
+ $ hg --config extensions.reposetuptest=! init pull-src5
+ $ hg --config extensions.reposetuptest=! -q -R pull-src5 pull src
+
+ $ echo '[extensions]' >> $HGRCPATH
+ $ echo '# disable extension globally and explicitly' >> $HGRCPATH
+ $ echo 'reposetuptest = !' >> $HGRCPATH
+ $ hg init parent
+ $ hg init parent/sub1
+ $ echo 1 > parent/sub1/1
+ $ hg -R parent/sub1 commit -Am '#0 at parent/sub1'
+ adding 1
+ $ hg init parent/sub2
+ $ hg init parent/sub2/sub21
+ $ echo 21 > parent/sub2/sub21/21
+ $ hg -R parent/sub2/sub21 commit -Am '#0 at parent/sub2/sub21'
+ adding 21
+ $ cat > parent/sub2/.hgsub <<EOF
+ > sub21 = sub21
+ > EOF
+ $ hg -R parent/sub2 commit -Am '#0 at parent/sub2'
+ adding .hgsub
+ $ hg init parent/sub3
+ $ echo 3 > parent/sub3/3
+ $ hg -R parent/sub3 commit -Am '#0 at parent/sub3'
+ adding 3
+ $ cat > parent/.hgsub <<EOF
+ > sub1 = sub1
+ > sub2 = sub2
+ > sub3 = sub3
+ > EOF
+ $ hg -R parent commit -Am '#0 at parent'
+ adding .hgsub
+ $ echo '[extensions]' >> parent/.hg/hgrc
+ $ echo '# enable extension locally' >> parent/.hg/hgrc
+ $ echo "reposetuptest = $TESTTMP/reposetuptest.py" >> parent/.hg/hgrc
+ $ cp parent/.hg/hgrc parent/sub2/.hg/hgrc
+ $ hg -R parent status -S -A
+ reposetup() for $TESTTMP/reposetup-test/parent
+ reposetup() for $TESTTMP/reposetup-test/parent/sub2
+ C .hgsub
+ C .hgsubstate
+ C sub1/1
+ C sub2/.hgsub
+ C sub2/.hgsubstate
+ C sub2/sub21/21
+ C sub3/3
+
+ $ cd ..
--- a/tests/test-graft.t Mon Oct 07 17:47:19 2013 -0400
+++ b/tests/test-graft.t Mon Oct 07 17:47:55 2013 -0400
@@ -71,7 +71,7 @@
$ hg up -q 0
$ echo foo > a
$ hg graft 1
- abort: outstanding uncommitted changes
+ abort: uncommitted changes
[255]
$ hg revert a
--- a/tests/test-help.t Mon Oct 07 17:47:19 2013 -0400
+++ b/tests/test-help.t Mon Oct 07 17:47:55 2013 -0400
@@ -930,8 +930,8 @@
<form class="search" action="/log">
<p><input name="rev" id="search1" type="text" size="30" /></p>
- <div id="hint">find changesets by author, revision,
- files, or words in the commit message</div>
+ <div id="hint">Find changesets by keywords (author, files, the commit message), revision
+ number or hash, or <a href="/help/revsets">revset expression</a>.</div>
</form>
<table class="bigtable">
<tr><td colspan="2"><h2><a name="main" href="#topics">Topics</a></h2></td></tr>
@@ -1490,8 +1490,8 @@
<form class="search" action="/log">
<p><input name="rev" id="search1" type="text" size="30" /></p>
- <div id="hint">find changesets by author, revision,
- files, or words in the commit message</div>
+ <div id="hint">Find changesets by keywords (author, files, the commit message), revision
+ number or hash, or <a href="/help/revsets">revset expression</a>.</div>
</form>
<div id="doc">
<p>
@@ -1656,8 +1656,8 @@
<form class="search" action="/log">
<p><input name="rev" id="search1" type="text" size="30" /></p>
- <div id="hint">find changesets by author, revision,
- files, or words in the commit message</div>
+ <div id="hint">Find changesets by keywords (author, files, the commit message), revision
+ number or hash, or <a href="/help/revsets">revset expression</a>.</div>
</form>
<div id="doc">
<p>
@@ -1852,8 +1852,8 @@
<form class="search" action="/log">
<p><input name="rev" id="search1" type="text" size="30" /></p>
- <div id="hint">find changesets by author, revision,
- files, or words in the commit message</div>
+ <div id="hint">Find changesets by keywords (author, files, the commit message), revision
+ number or hash, or <a href="/help/revsets">revset expression</a>.</div>
</form>
<div id="doc">
<h1>Specifying Single Revisions</h1>
--- a/tests/test-hgweb-commands.t Mon Oct 07 17:47:19 2013 -0400
+++ b/tests/test-hgweb-commands.t Mon Oct 07 17:47:55 2013 -0400
@@ -258,8 +258,8 @@
<form class="search" action="/log">
<p><input name="rev" id="search1" type="text" size="30" value="" /></p>
- <div id="hint">find changesets by author, revision,
- files, or words in the commit message</div>
+ <div id="hint">Find changesets by keywords (author, files, the commit message), revision
+ number or hash, or <a href="/help/revsets">revset expression</a>.</div>
</form>
<div class="navigate">
@@ -305,6 +305,21 @@
| rev 3: <a href="/shortlog/2ef0ac749a14">(0)</a> <a href="/shortlog/tip">tip</a>
</div>
+ <script type="text/javascript">
+ ajaxScrollInit(
+ '/shortlog/%next%',
+ '', <!-- NEXTHASH
+ function (htmlText, previousVal) {
+ var m = htmlText.match(/'(\w+)', <!-- NEXTHASH/);
+ return m ? m[1] : null;
+ },
+ '.bigtable > tbody:nth-of-type(2)',
+ '<tr class="%class%">\
+ <td colspan="3" style="text-align: center;">%text%</td>\
+ </tr>'
+ );
+ </script>
+
</div>
</div>
@@ -362,8 +377,8 @@
<form class="search" action="/log">
<p><input name="rev" id="search1" type="text" size="30" /></p>
- <div id="hint">find changesets by author, revision,
- files, or words in the commit message</div>
+ <div id="hint">Find changesets by keywords (author, files, the commit message), revision
+ number or hash, or <a href="/help/revsets">revset expression</a>.</div>
</form>
<div class="description">base</div>
@@ -495,11 +510,17 @@
<h2 class="breadcrumb"><a href="/">Mercurial</a> </h2>
<h3>searching for 'base'</h3>
+ <p>
+ Assuming literal keyword search.
+
+
+ </p>
+
<form class="search" action="/log">
<p><input name="rev" id="search1" type="text" size="30" value="base"></p>
- <div id="hint">find changesets by author, revision,
- files, or words in the commit message</div>
+ <div id="hint">Find changesets by keywords (author, files, the commit message), revision
+ number or hash, or <a href="/help/revsets">revset expression</a>.</div>
</form>
<div class="navigate">
@@ -537,6 +558,162 @@
</body>
</html>
+ $ "$TESTDIR/get-with-headers.py" 127.0.0.1:$HGPORT 'log?rev=stable&style=raw' | grep 'revision:'
+ revision: 2
+
+Search with revset syntax
+
+ $ "$TESTDIR/get-with-headers.py" 127.0.0.1:$HGPORT 'log?rev=tip^&style=raw'
+ 200 Script output follows
+
+
+ # HG changesets search
+ # Node ID cad8025a2e87f88c06259790adfa15acb4080123
+ # Query "tip^"
+ # Mode revset expression search
+
+ changeset: 1d22e65f027e5a0609357e7d8e7508cd2ba5d2fe
+ revision: 2
+ user: test
+ date: Thu, 01 Jan 1970 00:00:00 +0000
+ summary: branch
+ branch: stable
+
+
+ $ "$TESTDIR/get-with-headers.py" 127.0.0.1:$HGPORT 'log?rev=last(all(),2)^&style=raw'
+ 200 Script output follows
+
+
+ # HG changesets search
+ # Node ID cad8025a2e87f88c06259790adfa15acb4080123
+ # Query "last(all(),2)^"
+ # Mode revset expression search
+
+ changeset: 1d22e65f027e5a0609357e7d8e7508cd2ba5d2fe
+ revision: 2
+ user: test
+ date: Thu, 01 Jan 1970 00:00:00 +0000
+ summary: branch
+ branch: stable
+
+ changeset: a4f92ed23982be056b9852de5dfe873eaac7f0de
+ revision: 1
+ user: test
+ date: Thu, 01 Jan 1970 00:00:00 +0000
+ summary: Added tag 1.0 for changeset 2ef0ac749a14
+ branch: default
+
+
+ $ "$TESTDIR/get-with-headers.py" 127.0.0.1:$HGPORT 'log?rev=last(all(,2)^&style=raw'
+ 200 Script output follows
+
+
+ # HG changesets search
+ # Node ID cad8025a2e87f88c06259790adfa15acb4080123
+ # Query "last(all(,2)^"
+ # Mode literal keyword search
+
+
+ $ "$TESTDIR/get-with-headers.py" 127.0.0.1:$HGPORT 'log?rev=last(al(),2)^&style=raw'
+ 200 Script output follows
+
+
+ # HG changesets search
+ # Node ID cad8025a2e87f88c06259790adfa15acb4080123
+ # Query "last(al(),2)^"
+ # Mode literal keyword search
+
+
+ $ "$TESTDIR/get-with-headers.py" 127.0.0.1:$HGPORT 'log?rev=bookmark(anotherthing)&style=raw'
+ 200 Script output follows
+
+
+ # HG changesets search
+ # Node ID cad8025a2e87f88c06259790adfa15acb4080123
+ # Query "bookmark(anotherthing)"
+ # Mode revset expression search
+
+ changeset: 2ef0ac749a14e4f57a5a822464a0902c6f7f448f
+ revision: 0
+ user: test
+ date: Thu, 01 Jan 1970 00:00:00 +0000
+ summary: base
+ tag: 1.0
+ bookmark: anotherthing
+
+
+ $ "$TESTDIR/get-with-headers.py" 127.0.0.1:$HGPORT 'log?rev=bookmark(abc)&style=raw'
+ 200 Script output follows
+
+
+ # HG changesets search
+ # Node ID cad8025a2e87f88c06259790adfa15acb4080123
+ # Query "bookmark(abc)"
+ # Mode literal keyword search
+
+
+ $ "$TESTDIR/get-with-headers.py" 127.0.0.1:$HGPORT 'log?rev=deadbeef:&style=raw'
+ 200 Script output follows
+
+
+ # HG changesets search
+ # Node ID cad8025a2e87f88c06259790adfa15acb4080123
+ # Query "deadbeef:"
+ # Mode literal keyword search
+
+
+
+ $ "$TESTDIR/get-with-headers.py" 127.0.0.1:$HGPORT 'log?rev=user("test")&style=raw'
+ 200 Script output follows
+
+
+ # HG changesets search
+ # Node ID cad8025a2e87f88c06259790adfa15acb4080123
+ # Query "user("test")"
+ # Mode revset expression search
+
+ changeset: cad8025a2e87f88c06259790adfa15acb4080123
+ revision: 3
+ user: test
+ date: Thu, 01 Jan 1970 00:00:00 +0000
+ summary: branch commit with null character: \x00 (esc)
+ branch: unstable
+ tag: tip
+ bookmark: something
+
+ changeset: 1d22e65f027e5a0609357e7d8e7508cd2ba5d2fe
+ revision: 2
+ user: test
+ date: Thu, 01 Jan 1970 00:00:00 +0000
+ summary: branch
+ branch: stable
+
+ changeset: a4f92ed23982be056b9852de5dfe873eaac7f0de
+ revision: 1
+ user: test
+ date: Thu, 01 Jan 1970 00:00:00 +0000
+ summary: Added tag 1.0 for changeset 2ef0ac749a14
+ branch: default
+
+ changeset: 2ef0ac749a14e4f57a5a822464a0902c6f7f448f
+ revision: 0
+ user: test
+ date: Thu, 01 Jan 1970 00:00:00 +0000
+ summary: base
+ tag: 1.0
+ bookmark: anotherthing
+
+
+ $ "$TESTDIR/get-with-headers.py" 127.0.0.1:$HGPORT 'log?rev=user("re:test")&style=raw'
+ 200 Script output follows
+
+
+ # HG changesets search
+ # Node ID cad8025a2e87f88c06259790adfa15acb4080123
+ # Query "user("re:test")"
+ # Mode literal keyword search
+
+
File-related
@@ -614,8 +791,8 @@
<form class="search" action="/log">
<p><input name="rev" id="search1" type="text" size="30" /></p>
- <div id="hint">find changesets by author, revision,
- files, or words in the commit message</div>
+ <div id="hint">Find changesets by keywords (author, files, the commit message), revision
+ number or hash, or <a href="/help/revsets">revset expression</a>.</div>
</form>
<div class="description">Added tag 1.0 for changeset 2ef0ac749a14</div>
@@ -637,7 +814,6 @@
<th class="author">children</th>
<td class="author"><a href="/file/1d22e65f027e/foo">1d22e65f027e</a> </td>
</tr>
-
</table>
<div class="overflow">
@@ -1256,8 +1432,10 @@
Graph json escape of multibyte character
- $ "$TESTDIR/get-with-headers.py" 127.0.0.1:$HGPORT 'graph/' \
- > | grep -a '^var data ='
+ $ "$TESTDIR/get-with-headers.py" 127.0.0.1:$HGPORT 'graph/' > out
+ >>> for line in open("out"):
+ ... if line.startswith("var data ="):
+ ... print line,
var data = [["061dd13ba3c3", [0, 1], [[0, 0, 1, -1, ""]], "\\u80fd", "test", "1970-01-01", ["unstable", true], ["tip"], ["something"]], ["cad8025a2e87", [0, 1], [[0, 0, 1, 3, "FF0000"]], "branch commit with null character: \x00", "test", "1970-01-01", ["unstable", false], [], []], ["1d22e65f027e", [0, 1], [[0, 0, 1, 3, ""]], "branch", "test", "1970-01-01", ["stable", true], [], []], ["a4f92ed23982", [0, 1], [[0, 0, 1, 3, ""]], "Added tag 1.0 for changeset 2ef0ac749a14", "test", "1970-01-01", ["default", true], [], []], ["2ef0ac749a14", [0, 1], [], "base", "test", "1970-01-01", ["default", false], ["1.0"], ["anotherthing"]]]; (esc)
capabilities
--- a/tests/test-hgweb-descend-empties.t Mon Oct 07 17:47:19 2013 -0400
+++ b/tests/test-hgweb-descend-empties.t Mon Oct 07 17:47:55 2013 -0400
@@ -76,8 +76,8 @@
<form class="search" action="/log">
<p><input name="rev" id="search1" type="text" size="30" /></p>
- <div id="hint">find changesets by author, revision,
- files, or words in the commit message</div>
+ <div id="hint">Find changesets by keywords (author, files, the commit message), revision
+ number or hash, or <a href="/help/revsets">revset expression</a>.</div>
</form>
<table class="bigtable">
--- a/tests/test-hgweb-diffs.t Mon Oct 07 17:47:19 2013 -0400
+++ b/tests/test-hgweb-diffs.t Mon Oct 07 17:47:55 2013 -0400
@@ -84,8 +84,8 @@
<form class="search" action="/log">
<p><input name="rev" id="search1" type="text" size="30" /></p>
- <div id="hint">find changesets by author, revision,
- files, or words in the commit message</div>
+ <div id="hint">Find changesets by keywords (author, files, the commit message), revision
+ number or hash, or <a href="/help/revsets">revset expression</a>.</div>
</form>
<div class="description">a</div>
@@ -246,8 +246,8 @@
<form class="search" action="/log">
<p></p>
<p><input name="rev" id="search1" type="text" size="30" /></p>
- <div id="hint">find changesets by author, revision,
- files, or words in the commit message</div>
+ <div id="hint">Find changesets by keywords (author, files, the commit message), revision
+ number or hash, or <a href="/help/revsets">revset expression</a>.</div>
</form>
<div class="description">b</div>
@@ -269,7 +269,6 @@
<th>children</th>
<td></td>
</tr>
-
</table>
<div class="overflow">
@@ -349,8 +348,8 @@
<form class="search" action="/log">
<p><input name="rev" id="search1" type="text" size="30" /></p>
- <div id="hint">find changesets by author, revision,
- files, or words in the commit message</div>
+ <div id="hint">Find changesets by keywords (author, files, the commit message), revision
+ number or hash, or <a href="/help/revsets">revset expression</a>.</div>
</form>
<div class="description">a</div>
@@ -515,8 +514,8 @@
<form class="search" action="/log">
<p></p>
<p><input name="rev" id="search1" type="text" size="30" /></p>
- <div id="hint">find changesets by author, revision,
- files, or words in the commit message</div>
+ <div id="hint">Find changesets by keywords (author, files, the commit message), revision
+ number or hash, or <a href="/help/revsets">revset expression</a>.</div>
</form>
<div class="description">b</div>
@@ -538,7 +537,6 @@
<th>children</th>
<td></td>
</tr>
-
</table>
<div class="overflow">
@@ -615,8 +613,8 @@
<form class="search" action="/log">
<p></p>
<p><input name="rev" id="search1" type="text" size="30" /></p>
- <div id="hint">find changesets by author, revision,
- files, or words in the commit message</div>
+ <div id="hint">Find changesets by keywords (author, files, the commit message), revision
+ number or hash, or <a href="/help/revsets">revset expression</a>.</div>
</form>
<div class="description">a</div>
@@ -638,7 +636,6 @@
<th>children</th>
<td></td>
</tr>
-
</table>
<div class="overflow">
@@ -737,8 +734,8 @@
<form class="search" action="/log">
<p></p>
<p><input name="rev" id="search1" type="text" size="30" /></p>
- <div id="hint">find changesets by author, revision,
- files, or words in the commit message</div>
+ <div id="hint">Find changesets by keywords (author, files, the commit message), revision
+ number or hash, or <a href="/help/revsets">revset expression</a>.</div>
</form>
<div class="description">c</div>
@@ -760,7 +757,6 @@
<th>children</th>
<td></td>
</tr>
-
</table>
<div class="overflow">
@@ -861,8 +857,8 @@
<form class="search" action="/log">
<p></p>
<p><input name="rev" id="search1" type="text" size="30" /></p>
- <div id="hint">find changesets by author, revision,
- files, or words in the commit message</div>
+ <div id="hint">Find changesets by keywords (author, files, the commit message), revision
+ number or hash, or <a href="/help/revsets">revset expression</a>.</div>
</form>
<div class="description">d</div>
@@ -884,7 +880,6 @@
<th>children</th>
<td></td>
</tr>
-
</table>
<div class="overflow">
--- a/tests/test-hgweb-empty.t Mon Oct 07 17:47:19 2013 -0400
+++ b/tests/test-hgweb-empty.t Mon Oct 07 17:47:55 2013 -0400
@@ -63,8 +63,8 @@
<form class="search" action="/log">
<p><input name="rev" id="search1" type="text" size="30" value="" /></p>
- <div id="hint">find changesets by author, revision,
- files, or words in the commit message</div>
+ <div id="hint">Find changesets by keywords (author, files, the commit message), revision
+ number or hash, or <a href="/help/revsets">revset expression</a>.</div>
</form>
<div class="navigate">
@@ -90,6 +90,21 @@
| rev -1:
</div>
+ <script type="text/javascript">
+ ajaxScrollInit(
+ '/shortlog/%next%',
+ '', <!-- NEXTHASH
+ function (htmlText, previousVal) {
+ var m = htmlText.match(/'(\w+)', <!-- NEXTHASH/);
+ return m ? m[1] : null;
+ },
+ '.bigtable > tbody:nth-of-type(2)',
+ '<tr class="%class%">\
+ <td colspan="3" style="text-align: center;">%text%</td>\
+ </tr>'
+ );
+ </script>
+
</div>
</div>
@@ -158,8 +173,8 @@
<form class="search" action="/log">
<p><input name="rev" id="search1" type="text" size="30" value="" /></p>
- <div id="hint">find changesets by author, revision,
- files, or words in the commit message</div>
+ <div id="hint">Find changesets by keywords (author, files, the commit message), revision
+ number or hash, or <a href="/help/revsets">revset expression</a>.</div>
</form>
<div class="navigate">
@@ -185,6 +200,21 @@
| rev -1:
</div>
+ <script type="text/javascript">
+ ajaxScrollInit(
+ '/shortlog/%next%',
+ '', <!-- NEXTHASH
+ function (htmlText, previousVal) {
+ var m = htmlText.match(/'(\w+)', <!-- NEXTHASH/);
+ return m ? m[1] : null;
+ },
+ '.bigtable > tbody:nth-of-type(2)',
+ '<tr class="%class%">\
+ <td colspan="3" style="text-align: center;">%text%</td>\
+ </tr>'
+ );
+ </script>
+
</div>
</div>
@@ -249,8 +279,8 @@
<form class="search" action="/log">
<p><input name="rev" id="search1" type="text" size="30" /></p>
- <div id="hint">find changesets by author, revision,
- files, or words in the commit message</div>
+ <div id="hint">Find changesets by keywords (author, files, the commit message), revision
+ number or hash, or <a href="/help/revsets">revset expression</a>.</div>
</form>
<div class="navigate">
@@ -329,6 +359,17 @@
| rev -1:
</div>
+ <script type="text/javascript">
+ ajaxScrollInit(
+ '/graph/-1?revcount=%next%',
+ 60+60,
+ function (htmlText, previousVal) { return previousVal + 60; },
+ '#wrapper',
+ '<div class="%class%" style="text-align: center;">%text%</div>',
+ 'graph'
+ );
+ </script>
+
</div>
</div>
@@ -385,8 +426,8 @@
<form class="search" action="/log">
<p><input name="rev" id="search1" type="text" size="30" /></p>
- <div id="hint">find changesets by author, revision,
- files, or words in the commit message</div>
+ <div id="hint">Find changesets by keywords (author, files, the commit message), revision
+ number or hash, or <a href="/help/revsets">revset expression</a>.</div>
</form>
<table class="bigtable">
--- a/tests/test-hgweb-filelog.t Mon Oct 07 17:47:19 2013 -0400
+++ b/tests/test-hgweb-filelog.t Mon Oct 07 17:47:55 2013 -0400
@@ -170,8 +170,8 @@
<form class="search" action="/log">
<p><input name="rev" id="search1" type="text" size="30" /></p>
- <div id="hint">find changesets by author, revision,
- files, or words in the commit message</div>
+ <div id="hint">Find changesets by keywords (author, files, the commit message), revision
+ number or hash, or <a href="/help/revsets">revset expression</a>.</div>
</form>
<div class="navigate">
@@ -279,8 +279,8 @@
<form class="search" action="/log">
<p><input name="rev" id="search1" type="text" size="30" /></p>
- <div id="hint">find changesets by author, revision,
- files, or words in the commit message</div>
+ <div id="hint">Find changesets by keywords (author, files, the commit message), revision
+ number or hash, or <a href="/help/revsets">revset expression</a>.</div>
</form>
<div class="navigate">
@@ -388,8 +388,8 @@
<form class="search" action="/log">
<p><input name="rev" id="search1" type="text" size="30" /></p>
- <div id="hint">find changesets by author, revision,
- files, or words in the commit message</div>
+ <div id="hint">Find changesets by keywords (author, files, the commit message), revision
+ number or hash, or <a href="/help/revsets">revset expression</a>.</div>
</form>
<div class="navigate">
@@ -492,8 +492,8 @@
<form class="search" action="/log">
<p><input name="rev" id="search1" type="text" size="30" /></p>
- <div id="hint">find changesets by author, revision,
- files, or words in the commit message</div>
+ <div id="hint">Find changesets by keywords (author, files, the commit message), revision
+ number or hash, or <a href="/help/revsets">revset expression</a>.</div>
</form>
<div class="navigate">
@@ -576,8 +576,8 @@
<form class="search" action="/log">
<p><input name="rev" id="search1" type="text" size="30"></p>
- <div id="hint">find changesets by author, revision,
- files, or words in the commit message</div>
+ <div id="hint">Find changesets by keywords (author, files, the commit message), revision
+ number or hash, or <a href="/help/revsets">revset expression</a>.</div>
</form>
<div class="description">
--- a/tests/test-hgweb-removed.t Mon Oct 07 17:47:19 2013 -0400
+++ b/tests/test-hgweb-removed.t Mon Oct 07 17:47:55 2013 -0400
@@ -65,8 +65,8 @@
<form class="search" action="/log">
<p><input name="rev" id="search1" type="text" size="30" /></p>
- <div id="hint">find changesets by author, revision,
- files, or words in the commit message</div>
+ <div id="hint">Find changesets by keywords (author, files, the commit message), revision
+ number or hash, or <a href="/help/revsets">revset expression</a>.</div>
</form>
<div class="description">del</div>
@@ -190,8 +190,8 @@
<form class="search" action="/log">
<p></p>
<p><input name="rev" id="search1" type="text" size="30" /></p>
- <div id="hint">find changesets by author, revision,
- files, or words in the commit message</div>
+ <div id="hint">Find changesets by keywords (author, files, the commit message), revision
+ number or hash, or <a href="/help/revsets">revset expression</a>.</div>
</form>
<div class="description">del</div>
@@ -213,7 +213,6 @@
<th>children</th>
<td></td>
</tr>
-
</table>
<div class="overflow">
--- a/tests/test-hgweb.t Mon Oct 07 17:47:19 2013 -0400
+++ b/tests/test-hgweb.t Mon Oct 07 17:47:55 2013 -0400
@@ -81,8 +81,8 @@
<form class="search" action="/log">
<p><input name="rev" id="search1" type="text" size="30"></p>
- <div id="hint">find changesets by author, revision,
- files, or words in the commit message</div>
+ <div id="hint">Find changesets by keywords (author, files, the commit message), revision
+ number or hash, or <a href="/help/revsets">revset expression</a>.</div>
</form>
<div class="description">
@@ -171,8 +171,8 @@
<form class="search" action="/log">
<p><input name="rev" id="search1" type="text" size="30"></p>
- <div id="hint">find changesets by author, revision,
- files, or words in the commit message</div>
+ <div id="hint">Find changesets by keywords (author, files, the commit message), revision
+ number or hash, or <a href="/help/revsets">revset expression</a>.</div>
</form>
<div class="description">
@@ -249,8 +249,8 @@
<form class="search" action="/log">
<p><input name="rev" id="search1" type="text" size="30" /></p>
- <div id="hint">find changesets by author, revision,
- files, or words in the commit message</div>
+ <div id="hint">Find changesets by keywords (author, files, the commit message), revision
+ number or hash, or <a href="/help/revsets">revset expression</a>.</div>
</form>
<table class="bigtable">
--- a/tests/test-highlight.t Mon Oct 07 17:47:19 2013 -0400
+++ b/tests/test-highlight.t Mon Oct 07 17:47:55 2013 -0400
@@ -109,8 +109,8 @@
<form class="search" action="/log">
<p><input name="rev" id="search1" type="text" size="30" /></p>
- <div id="hint">find changesets by author, revision,
- files, or words in the commit message</div>
+ <div id="hint">Find changesets by keywords (author, files, the commit message), revision
+ number or hash, or <a href="/help/revsets">revset expression</a>.</div>
</form>
<div class="description">a</div>
@@ -132,7 +132,6 @@
<th class="author">children</th>
<td class="author"></td>
</tr>
-
</table>
<div class="overflow">
@@ -241,8 +240,8 @@
<form class="search" action="/log">
<p><input name="rev" id="search1" type="text" size="30" /></p>
- <div id="hint">find changesets by author, revision,
- files, or words in the commit message</div>
+ <div id="hint">Find changesets by keywords (author, files, the commit message), revision
+ number or hash, or <a href="/help/revsets">revset expression</a>.</div>
</form>
<div class="description">a</div>
@@ -264,7 +263,6 @@
<th class="author">children</th>
<td class="author"></td>
</tr>
-
</table>
<div class="overflow">
--- a/tests/test-import-merge.t Mon Oct 07 17:47:19 2013 -0400
+++ b/tests/test-import-merge.t Mon Oct 07 17:47:55 2013 -0400
@@ -129,7 +129,9 @@
$ echo a>>a
$ hg ci -m3
$ hg export 2 | head -7 > ../a.patch
- $ hg export tip | tail -n +8 >> ../a.patch
+ $ hg export tip > out
+ >>> apatch = open("../a.patch", "a")
+ >>> apatch.write("".join(open("out").readlines()[7:]))
$ cd ..
$ hg clone -qr0 repo3 repo3-clone
--- a/tests/test-issue1502.t Mon Oct 07 17:47:19 2013 -0400
+++ b/tests/test-issue1502.t Mon Oct 07 17:47:55 2013 -0400
@@ -19,7 +19,8 @@
adding manifests
adding file changes
added 1 changesets with 1 changes to 1 files (+1 heads)
- not updating: crosses branches (merge branches or update --check to force update)
+ not updating: not a linear update
+ (merge or update --check to force update)
$ hg -R foo1 book branchy
$ hg -R foo1 book
--- a/tests/test-largefiles.t Mon Oct 07 17:47:19 2013 -0400
+++ b/tests/test-largefiles.t Mon Oct 07 17:47:55 2013 -0400
@@ -1104,7 +1104,7 @@
"update --check" refuses to update with uncommitted changes.
$ hg update --check 8
- abort: uncommitted local changes
+ abort: uncommitted changes
[255]
"update --clean" leaves correct largefiles in working copy, even when there is
@@ -2191,3 +2191,64 @@
$ cd ..
+
+Check whether "largefiles" feature is supported only in repositories
+enabling largefiles extension.
+
+ $ mkdir individualenabling
+ $ cd individualenabling
+
+ $ hg init enabledlocally
+ $ echo large > enabledlocally/large
+ $ hg -R enabledlocally add --large enabledlocally/large
+ $ hg -R enabledlocally commit -m '#0'
+ Invoking status precommit hook
+ A large
+
+ $ hg init notenabledlocally
+ $ echo large > notenabledlocally/large
+ $ hg -R notenabledlocally add --large notenabledlocally/large
+ $ hg -R notenabledlocally commit -m '#0'
+ Invoking status precommit hook
+ A large
+
+ $ cat >> $HGRCPATH <<EOF
+ > [extensions]
+ > # disable globally
+ > largefiles=!
+ > EOF
+ $ cat >> enabledlocally/.hg/hgrc <<EOF
+ > [extensions]
+ > # enable locally
+ > largefiles=
+ > EOF
+ $ hg -R enabledlocally root
+ $TESTTMP/individualenabling/enabledlocally
+ $ hg -R notenabledlocally root
+ abort: unknown repository format: requires features 'largefiles' (upgrade Mercurial)!
+ [255]
+
+ $ hg init push-dst
+ $ hg -R enabledlocally push push-dst
+ pushing to push-dst
+ abort: required features are not supported in the destination: largefiles
+ [255]
+
+ $ hg init pull-src
+ $ hg -R pull-src pull enabledlocally
+ pulling from enabledlocally
+ abort: required features are not supported in the destination: largefiles
+ [255]
+
+ $ hg clone enabledlocally clone-dst
+ abort: unknown repository format: requires features 'largefiles' (upgrade Mercurial)!
+ [255]
+ $ test -d clone-dst
+ [1]
+ $ hg clone --pull enabledlocally clone-pull-dst
+ abort: required features are not supported in the destination: largefiles
+ [255]
+ $ test -d clone-pull-dst
+ [1]
+
+ $ cd ..
--- a/tests/test-lrucachedict.py Mon Oct 07 17:47:19 2013 -0400
+++ b/tests/test-lrucachedict.py Mon Oct 07 17:47:55 2013 -0400
@@ -31,5 +31,8 @@
d['f'] = 'vf'
printifpresent(d, ['b', 'c', 'd', 'e', 'f'])
+ d.clear()
+ printifpresent(d, ['b', 'c', 'd', 'e', 'f'])
+
if __name__ == '__main__':
test_lrucachedict()
--- a/tests/test-lrucachedict.py.out Mon Oct 07 17:47:19 2013 -0400
+++ b/tests/test-lrucachedict.py.out Mon Oct 07 17:47:55 2013 -0400
@@ -24,3 +24,8 @@
'e' in d: False
'f' in d: True
d['f']: vf
+'b' in d: False
+'c' in d: False
+'d' in d: False
+'e' in d: False
+'f' in d: False
--- a/tests/test-merge-force.t Mon Oct 07 17:47:19 2013 -0400
+++ b/tests/test-merge-force.t Mon Oct 07 17:47:55 2013 -0400
@@ -19,7 +19,7 @@
Should fail, since there are deleted files:
$ hg merge
- abort: outstanding uncommitted changes
+ abort: uncommitted changes
(use 'hg status' to list changes)
[255]
--- a/tests/test-merge-subrepos.t Mon Oct 07 17:47:19 2013 -0400
+++ b/tests/test-merge-subrepos.t Mon Oct 07 17:47:55 2013 -0400
@@ -21,5 +21,5 @@
Should fail, since there are added files to subrepo:
$ hg merge
- abort: outstanding uncommitted changes in subrepository 'subrepo'
+ abort: uncommitted changes in subrepository 'subrepo'
[255]
--- a/tests/test-merge1.t Mon Oct 07 17:47:19 2013 -0400
+++ b/tests/test-merge1.t Mon Oct 07 17:47:55 2013 -0400
@@ -140,7 +140,7 @@
$ echo This is file b22 > b
merge fails
$ hg merge 2
- abort: outstanding uncommitted changes
+ abort: uncommitted changes
(use 'hg status' to list changes)
[255]
merge expected!
@@ -177,7 +177,7 @@
$ echo This is file b33 > b
merge of b should fail
$ hg merge 2
- abort: outstanding uncommitted changes
+ abort: uncommitted changes
(use 'hg status' to list changes)
[255]
merge of b expected
--- a/tests/test-merge5.t Mon Oct 07 17:47:19 2013 -0400
+++ b/tests/test-merge5.t Mon Oct 07 17:47:55 2013 -0400
@@ -14,11 +14,12 @@
$ hg update 1
1 files updated, 0 files merged, 0 files removed, 0 files unresolved
$ hg update
- abort: crosses branches (merge branches or update --check to force update)
+ abort: not a linear update
+ (merge or update --check to force update)
[255]
$ rm b
$ hg update -c
- abort: uncommitted local changes
+ abort: uncommitted changes
[255]
$ hg revert b
$ hg update -c
@@ -32,7 +33,8 @@
Should abort:
$ hg update -y 1
- abort: crosses branches (merge branches or use --clean to discard changes)
+ abort: uncommitted changes
+ (commit or update --clean to discard changes)
[255]
$ mv c a
--- a/tests/test-mq-strip.t Mon Oct 07 17:47:19 2013 -0400
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,503 +0,0 @@
- $ echo "[extensions]" >> $HGRCPATH
- $ echo "mq=" >> $HGRCPATH
- $ echo "graphlog=" >> $HGRCPATH
-
- $ restore() {
- > hg unbundle -q .hg/strip-backup/*
- > rm .hg/strip-backup/*
- > }
- $ teststrip() {
- > hg up -C $1
- > echo % before update $1, strip $2
- > hg parents
- > hg --traceback strip $2
- > echo % after update $1, strip $2
- > hg parents
- > restore
- > }
-
- $ hg init test
- $ cd test
-
- $ echo foo > bar
- $ hg ci -Ama
- adding bar
-
- $ echo more >> bar
- $ hg ci -Amb
-
- $ echo blah >> bar
- $ hg ci -Amc
-
- $ hg up 1
- 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
- $ echo blah >> bar
- $ hg ci -Amd
- created new head
-
- $ echo final >> bar
- $ hg ci -Ame
-
- $ hg log
- changeset: 4:443431ffac4f
- tag: tip
- user: test
- date: Thu Jan 01 00:00:00 1970 +0000
- summary: e
-
- changeset: 3:65bd5f99a4a3
- parent: 1:ef3a871183d7
- user: test
- date: Thu Jan 01 00:00:00 1970 +0000
- summary: d
-
- changeset: 2:264128213d29
- user: test
- date: Thu Jan 01 00:00:00 1970 +0000
- summary: c
-
- changeset: 1:ef3a871183d7
- user: test
- date: Thu Jan 01 00:00:00 1970 +0000
- summary: b
-
- changeset: 0:9ab35a2d17cb
- user: test
- date: Thu Jan 01 00:00:00 1970 +0000
- summary: a
-
-
- $ teststrip 4 4
- 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
- % before update 4, strip 4
- changeset: 4:443431ffac4f
- tag: tip
- user: test
- date: Thu Jan 01 00:00:00 1970 +0000
- summary: e
-
- 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
- saved backup bundle to $TESTTMP/test/.hg/strip-backup/*-backup.hg (glob)
- % after update 4, strip 4
- changeset: 3:65bd5f99a4a3
- tag: tip
- parent: 1:ef3a871183d7
- user: test
- date: Thu Jan 01 00:00:00 1970 +0000
- summary: d
-
- $ teststrip 4 3
- 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
- % before update 4, strip 3
- changeset: 4:443431ffac4f
- tag: tip
- user: test
- date: Thu Jan 01 00:00:00 1970 +0000
- summary: e
-
- 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
- saved backup bundle to $TESTTMP/test/.hg/strip-backup/*-backup.hg (glob)
- % after update 4, strip 3
- changeset: 1:ef3a871183d7
- user: test
- date: Thu Jan 01 00:00:00 1970 +0000
- summary: b
-
- $ teststrip 1 4
- 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
- % before update 1, strip 4
- changeset: 1:ef3a871183d7
- user: test
- date: Thu Jan 01 00:00:00 1970 +0000
- summary: b
-
- saved backup bundle to $TESTTMP/test/.hg/strip-backup/*-backup.hg (glob)
- % after update 1, strip 4
- changeset: 1:ef3a871183d7
- user: test
- date: Thu Jan 01 00:00:00 1970 +0000
- summary: b
-
- $ teststrip 4 2
- 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
- % before update 4, strip 2
- changeset: 4:443431ffac4f
- tag: tip
- user: test
- date: Thu Jan 01 00:00:00 1970 +0000
- summary: e
-
- saved backup bundle to $TESTTMP/test/.hg/strip-backup/*-backup.hg (glob)
- % after update 4, strip 2
- changeset: 3:443431ffac4f
- tag: tip
- user: test
- date: Thu Jan 01 00:00:00 1970 +0000
- summary: e
-
- $ teststrip 4 1
- 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
- % before update 4, strip 1
- changeset: 4:264128213d29
- tag: tip
- parent: 1:ef3a871183d7
- user: test
- date: Thu Jan 01 00:00:00 1970 +0000
- summary: c
-
- 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
- saved backup bundle to $TESTTMP/test/.hg/strip-backup/*-backup.hg (glob)
- % after update 4, strip 1
- changeset: 0:9ab35a2d17cb
- tag: tip
- user: test
- date: Thu Jan 01 00:00:00 1970 +0000
- summary: a
-
- $ teststrip null 4
- 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
- % before update null, strip 4
- saved backup bundle to $TESTTMP/test/.hg/strip-backup/*-backup.hg (glob)
- % after update null, strip 4
-
- $ hg log
- changeset: 4:264128213d29
- tag: tip
- parent: 1:ef3a871183d7
- user: test
- date: Thu Jan 01 00:00:00 1970 +0000
- summary: c
-
- changeset: 3:443431ffac4f
- user: test
- date: Thu Jan 01 00:00:00 1970 +0000
- summary: e
-
- changeset: 2:65bd5f99a4a3
- user: test
- date: Thu Jan 01 00:00:00 1970 +0000
- summary: d
-
- changeset: 1:ef3a871183d7
- user: test
- date: Thu Jan 01 00:00:00 1970 +0000
- summary: b
-
- changeset: 0:9ab35a2d17cb
- user: test
- date: Thu Jan 01 00:00:00 1970 +0000
- summary: a
-
-
- $ hg up -C 2
- 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
- $ hg merge 4
- 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
- (branch merge, don't forget to commit)
-
-before strip of merge parent
-
- $ hg parents
- changeset: 2:65bd5f99a4a3
- user: test
- date: Thu Jan 01 00:00:00 1970 +0000
- summary: d
-
- changeset: 4:264128213d29
- tag: tip
- parent: 1:ef3a871183d7
- user: test
- date: Thu Jan 01 00:00:00 1970 +0000
- summary: c
-
- $ hg strip 4
- 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
- saved backup bundle to $TESTTMP/test/.hg/strip-backup/*-backup.hg (glob)
-
-after strip of merge parent
-
- $ hg parents
- changeset: 1:ef3a871183d7
- user: test
- date: Thu Jan 01 00:00:00 1970 +0000
- summary: b
-
- $ restore
-
- $ hg up
- 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
- $ hg glog
- @ changeset: 4:264128213d29
- | tag: tip
- | parent: 1:ef3a871183d7
- | user: test
- | date: Thu Jan 01 00:00:00 1970 +0000
- | summary: c
- |
- | o changeset: 3:443431ffac4f
- | | user: test
- | | date: Thu Jan 01 00:00:00 1970 +0000
- | | summary: e
- | |
- | o changeset: 2:65bd5f99a4a3
- |/ user: test
- | date: Thu Jan 01 00:00:00 1970 +0000
- | summary: d
- |
- o changeset: 1:ef3a871183d7
- | user: test
- | date: Thu Jan 01 00:00:00 1970 +0000
- | summary: b
- |
- o changeset: 0:9ab35a2d17cb
- user: test
- date: Thu Jan 01 00:00:00 1970 +0000
- summary: a
-
-
-2 is parent of 3, only one strip should happen
-
- $ hg strip "roots(2)" 3
- saved backup bundle to $TESTTMP/test/.hg/strip-backup/*-backup.hg (glob)
- $ hg glog
- @ changeset: 2:264128213d29
- | tag: tip
- | user: test
- | date: Thu Jan 01 00:00:00 1970 +0000
- | summary: c
- |
- o changeset: 1:ef3a871183d7
- | user: test
- | date: Thu Jan 01 00:00:00 1970 +0000
- | summary: b
- |
- o changeset: 0:9ab35a2d17cb
- user: test
- date: Thu Jan 01 00:00:00 1970 +0000
- summary: a
-
- $ restore
- $ hg glog
- o changeset: 4:443431ffac4f
- | tag: tip
- | user: test
- | date: Thu Jan 01 00:00:00 1970 +0000
- | summary: e
- |
- o changeset: 3:65bd5f99a4a3
- | parent: 1:ef3a871183d7
- | user: test
- | date: Thu Jan 01 00:00:00 1970 +0000
- | summary: d
- |
- | @ changeset: 2:264128213d29
- |/ user: test
- | date: Thu Jan 01 00:00:00 1970 +0000
- | summary: c
- |
- o changeset: 1:ef3a871183d7
- | user: test
- | date: Thu Jan 01 00:00:00 1970 +0000
- | summary: b
- |
- o changeset: 0:9ab35a2d17cb
- user: test
- date: Thu Jan 01 00:00:00 1970 +0000
- summary: a
-
-
-2 different branches: 2 strips
-
- $ hg strip 2 4
- 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
- saved backup bundle to $TESTTMP/test/.hg/strip-backup/*-backup.hg (glob)
- $ hg glog
- o changeset: 2:65bd5f99a4a3
- | tag: tip
- | user: test
- | date: Thu Jan 01 00:00:00 1970 +0000
- | summary: d
- |
- @ changeset: 1:ef3a871183d7
- | user: test
- | date: Thu Jan 01 00:00:00 1970 +0000
- | summary: b
- |
- o changeset: 0:9ab35a2d17cb
- user: test
- date: Thu Jan 01 00:00:00 1970 +0000
- summary: a
-
- $ restore
-
-2 different branches and a common ancestor: 1 strip
-
- $ hg strip 1 "2|4"
- 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
- saved backup bundle to $TESTTMP/test/.hg/strip-backup/*-backup.hg (glob)
- $ restore
-
-stripping an empty revset
-
- $ hg strip "1 and not 1"
- abort: empty revision set
- [255]
-
-remove branchy history for qimport tests
-
- $ hg strip 3
- saved backup bundle to $TESTTMP/test/.hg/strip-backup/*-backup.hg (glob)
-
-
-strip of applied mq should cleanup status file
-
- $ hg up -C 3
- 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
- $ echo fooagain >> bar
- $ hg ci -mf
- $ hg qimport -r tip:2
-
-applied patches before strip
-
- $ hg qapplied
- 2.diff
- 3.diff
- 4.diff
-
-stripping revision in queue
-
- $ hg strip 3
- 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
- saved backup bundle to $TESTTMP/test/.hg/strip-backup/*-backup.hg (glob)
-
-applied patches after stripping rev in queue
-
- $ hg qapplied
- 2.diff
-
-stripping ancestor of queue
-
- $ hg strip 1
- 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
- saved backup bundle to $TESTTMP/test/.hg/strip-backup/*-backup.hg (glob)
-
-applied patches after stripping ancestor of queue
-
- $ hg qapplied
-
-Verify strip protects against stripping wc parent when there are uncommited mods
-
- $ echo b > b
- $ hg add b
- $ hg ci -m 'b'
- $ hg log --graph
- @ changeset: 1:7519abd79d14
- | tag: tip
- | user: test
- | date: Thu Jan 01 00:00:00 1970 +0000
- | summary: b
- |
- o changeset: 0:9ab35a2d17cb
- user: test
- date: Thu Jan 01 00:00:00 1970 +0000
- summary: a
-
-
- $ echo c > b
- $ echo c > bar
- $ hg strip tip
- abort: local changes found
- [255]
- $ hg strip tip --keep
- saved backup bundle to $TESTTMP/test/.hg/strip-backup/*-backup.hg (glob)
- $ hg log --graph
- @ changeset: 0:9ab35a2d17cb
- tag: tip
- user: test
- date: Thu Jan 01 00:00:00 1970 +0000
- summary: a
-
- $ hg status
- M bar
- ? b
-
-Strip adds, removes, modifies with --keep
-
- $ touch b
- $ hg add b
- $ hg commit -mb
- $ touch c
-
-... with a clean working dir
-
- $ hg add c
- $ hg rm bar
- $ hg commit -mc
- $ hg status
- $ hg strip --keep tip
- saved backup bundle to $TESTTMP/test/.hg/strip-backup/*-backup.hg (glob)
- $ hg status
- ! bar
- ? c
-
-... with a dirty working dir
-
- $ hg add c
- $ hg rm bar
- $ hg commit -mc
- $ hg status
- $ echo b > b
- $ echo d > d
- $ hg strip --keep tip
- saved backup bundle to $TESTTMP/test/.hg/strip-backup/*-backup.hg (glob)
- $ hg status
- M b
- ! bar
- ? c
- ? d
- $ cd ..
-
-stripping many nodes on a complex graph (issue3299)
-
- $ hg init issue3299
- $ cd issue3299
- $ hg debugbuilddag '@a.:a@b.:b.:x<a@a.:a<b@b.:b<a@a.:a'
- $ hg strip 'not ancestors(x)'
- saved backup bundle to $TESTTMP/issue3299/.hg/strip-backup/*-backup.hg (glob)
-
-test hg strip -B bookmark
-
- $ cd ..
- $ hg init bookmarks
- $ cd bookmarks
- $ hg debugbuilddag '..<2.*1/2:m<2+3:c<m+3:a<2.:b'
- $ hg bookmark -r 'a' 'todelete'
- $ hg bookmark -r 'b' 'B'
- $ hg bookmark -r 'b' 'nostrip'
- $ hg bookmark -r 'c' 'delete'
- $ hg up -C todelete
- 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
- $ hg strip -B nostrip
- bookmark 'nostrip' deleted
- abort: empty revision set
- [255]
- $ hg strip -B todelete
- bookmark 'todelete' deleted
- 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
- saved backup bundle to $TESTTMP/bookmarks/.hg/strip-backup/*-backup.hg (glob)
- $ hg id -ir dcbb326fdec2
- abort: unknown revision 'dcbb326fdec2'!
- [255]
- $ hg id -ir d62d843c9a01
- d62d843c9a01
- $ hg bookmarks
- B 9:ff43616e5d0f
- delete 6:2702dd0c91e7
- $ hg strip -B delete
- bookmark 'delete' deleted
- saved backup bundle to $TESTTMP/bookmarks/.hg/strip-backup/*-backup.hg (glob)
- $ hg id -ir 6:2702dd0c91e7
- abort: unknown revision '2702dd0c91e7'!
- [255]
-
- $ cd ..
--- a/tests/test-mq-subrepo.t Mon Oct 07 17:47:19 2013 -0400
+++ b/tests/test-mq-subrepo.t Mon Oct 07 17:47:55 2013 -0400
@@ -213,6 +213,7 @@
handle subrepos safely on qpush/qpop
+(and we cannot qpop / qpush with a modified subrepo)
$ mkrepo repo-2499-qpush
$ mksubrepo sub
@@ -220,31 +221,58 @@
$ hg -R sub ci -m0sub
$ echo sub = sub > .hgsub
$ hg add .hgsub
- $ hg qnew -m0 0.diff
+ $ hg commit -m0
$ hg debugsub
path sub
source sub
revision b2fdb12cd82b021c3b7053d67802e77b6eeaee31
+ $ echo foo > ./sub/a
+ $ hg -R sub commit -m foo
+ $ hg commit -m1
+ $ hg qimport -r "0:tip"
+ $ hg -R sub id --id
+ aa037b301eba
qpop
+ $ hg -R sub update 0000
+ 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
$ hg qpop
- popping 0.diff
- patch queue now empty
- $ hg status -AS
- $ hg debugsub
-
-qpush
- $ hg qpush
- applying 0.diff
+ abort: local changed subrepos found, refresh first
+ [255]
+ $ hg revert sub
+ reverting subrepo sub
+ adding sub/a
+ $ hg qpop
+ popping 1.diff
now at: 0.diff
$ hg status -AS
C .hgsub
C .hgsubstate
C sub/a
- $ hg debugsub
- path sub
- source sub
- revision b2fdb12cd82b021c3b7053d67802e77b6eeaee31
+ $ hg -R sub id --id
+ b2fdb12cd82b
+
+qpush
+ $ hg -R sub update 0000
+ 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
+ $ hg qpush
+ abort: local changed subrepos found, refresh first
+ [255]
+ $ hg revert sub
+ reverting subrepo sub
+ adding sub/a
+ $ hg qpush
+ applying 1.diff
+ subrepository sub diverged (local revision: b2fdb12cd82b, remote revision: aa037b301eba)
+ (M)erge, keep (l)ocal or keep (r)emote? m
+ 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
+ now at: 1.diff
+ $ hg status -AS
+ C .hgsub
+ C .hgsubstate
+ C sub/a
+ $ hg -R sub id --id
+ aa037b301eba
$ cd ..
--- a/tests/test-mq.t Mon Oct 07 17:47:19 2013 -0400
+++ b/tests/test-mq.t Mon Oct 07 17:47:55 2013 -0400
@@ -67,6 +67,9 @@
changes will be tolerated and preserved. If incompatible options such as
-f/--force or --exact are passed, this setting is ignored.
+ This extension used to provide a strip command. This command now lives in the
+ strip extension.
+
list of commands:
qapplied print the patches already applied
@@ -91,7 +94,6 @@
qseries print the entire series file
qtop print the name of the current patch
qunapplied print the patches not yet applied
- strip strip changesets and all their descendants from the repository
use "hg -v help mq" to show builtin aliases and global options
--- a/tests/test-parse-date.t Mon Oct 07 17:47:19 2013 -0400
+++ b/tests/test-parse-date.t Mon Oct 07 17:47:55 2013 -0400
@@ -242,7 +242,7 @@
>>> yesterday = (datetime.date.today() - datetime.timedelta(days=1)).strftime("%b %d")
>>> dates = open('dates', 'w')
>>> dates.write(today + '\n')
- >>> dates.write(yesterday)
+ >>> dates.write(yesterday + '\n')
>>> dates.close()
$ hg ci -d "`sed -n '1p' dates`" -m "today is a good day to code"
$ hg log -d today --template '{desc}\n'
--- a/tests/test-progress.t Mon Oct 07 17:47:19 2013 -0400
+++ b/tests/test-progress.t Mon Oct 07 17:47:55 2013 -0400
@@ -1,6 +1,14 @@
$ cat > loop.py <<EOF
> from mercurial import commands
+ > import time
+ > class incrementingtime(object):
+ > def __init__(self):
+ > self._time = 0.0
+ > def __call__(self):
+ > self._time += 0.25
+ > return self._time
+ > time.time = incrementingtime()
>
> def loop(ui, loops, **opts):
> loops = int(loops)
@@ -19,9 +27,14 @@
> if opts.get('parallel'):
> ui.progress('other', i, 'other.%d' % i, 'othernum', total)
> if nested:
- > for j in range(2):
- > ui.progress('nested', j, 'nested.%d' % j, 'nestnum', 2)
- > ui.progress('nested', None, 'nested.done', 'nestnum', 2)
+ > nested_steps = 2
+ > if i and i % 4 == 0:
+ > nested_steps = 5
+ > for j in range(nested_steps):
+ > ui.progress(
+ > 'nested', j, 'nested.%d' % j, 'nestnum', nested_steps)
+ > ui.progress(
+ > 'nested', None, 'nested.done', 'nestnum', nested_steps)
> ui.progress('loop', None, 'loop.done', 'loopnum', total)
>
> commands.norepo += " loop"
@@ -69,6 +82,24 @@
loop [===============================> ] 2/3\r (no-eol) (esc)
\r (no-eol) (esc)
+Test nested long-lived topic which has the same name as a short-lived
+peer. We shouldn't get stuck showing the short-lived inner steps, and
+should go back to skipping the inner steps when the slow nested step
+finishes.
+
+ $ hg -y loop 7 --nested
+ \r (no-eol) (esc)
+ loop [ ] 0/7\r (no-eol) (esc)
+ loop [=====> ] 1/7\r (no-eol) (esc)
+ loop [============> ] 2/7\r (no-eol) (esc)
+ loop [===================> ] 3/7\r (no-eol) (esc)
+ loop [==========================> ] 4/7\r (no-eol) (esc)
+ nested [==========================> ] 3/5\r (no-eol) (esc)
+ nested [===================================> ] 4/5\r (no-eol) (esc)
+ loop [=================================> ] 5/7\r (no-eol) (esc)
+ loop [========================================> ] 6/7\r (no-eol) (esc)
+ \r (no-eol) (esc)
+
$ hg --config progress.changedelay=0 -y loop 3 --nested
\r (no-eol) (esc)
--- a/tests/test-pull-update.t Mon Oct 07 17:47:19 2013 -0400
+++ b/tests/test-pull-update.t Mon Oct 07 17:47:55 2013 -0400
@@ -25,7 +25,8 @@
adding manifests
adding file changes
added 1 changesets with 1 changes to 1 files (+1 heads)
- not updating: crosses branches (merge branches or update --check to force update)
+ not updating: not a linear update
+ (merge or update --check to force update)
$ cd ../tt
@@ -38,7 +39,8 @@
adding manifests
adding file changes
added 1 changesets with 1 changes to 1 files (+1 heads)
- not updating: crosses branches (merge branches or update --check to force update)
+ not updating: not a linear update
+ (merge or update --check to force update)
$ HGMERGE=true hg merge
merging foo
--- a/tests/test-push-warn.t Mon Oct 07 17:47:19 2013 -0400
+++ b/tests/test-push-warn.t Mon Oct 07 17:47:55 2013 -0400
@@ -354,6 +354,29 @@
adding file changes
added 1 changesets with 1 changes to 1 files
+Pushing muliple headed new branch:
+
+ $ echo 14 > foo
+ $ hg -q branch f
+ $ hg -q ci -m 14
+ $ echo 15 > foo
+ $ hg -q ci -m 15
+ $ hg -q up 14
+ $ echo 16 > foo
+ $ hg -q ci -m 16
+ $ hg push --branch f --new-branch ../f
+ pushing to ../f
+ searching for changes
+ abort: push creates multiple headed new branch 'f'
+ (merge or see "hg help push" for detail about pushing new heads)
+ [255]
+ $ hg push --branch f --new-branch --force ../f
+ pushing to ../f
+ searching for changes
+ adding changesets
+ adding manifests
+ adding file changes
+ added 3 changesets with 3 changes to 1 files (+1 heads)
Checking prepush logic does not allow silently pushing
multiple new heads:
--- a/tests/test-rebase-obsolete.t Mon Oct 07 17:47:19 2013 -0400
+++ b/tests/test-rebase-obsolete.t Mon Oct 07 17:47:55 2013 -0400
@@ -178,9 +178,9 @@
42ccdea3bb16d28e1848c95fe2e44c000f3f21b1 0 {'date': '*', 'user': 'test'} (glob)
5fddd98957c8a54a4d436dfe1da9d87f21a1b97b 5ae4c968c6aca831df823664e706c9d4aa34473d 0 {'date': '*', 'user': 'test'} (glob)
32af7686d403cf45b5d95f2d70cebea587ac806a 0 {'date': '*', 'user': 'test'} (glob)
- 08483444fef91d6224f6655ee586a65d263ad34c cbc07f26687521cecfc9a141bf5ecfc0fd2b8531 0 {'date': '* *', 'user': 'test'} (glob)
+ 08483444fef91d6224f6655ee586a65d263ad34c 4596109a6a4328c398bde3a4a3b6737cfade3003 0 {'date': '* *', 'user': 'test'} (glob)
$ hg log -G
- @ 11:cbc07f266875 D
+ @ 11:4596109a6a43 D
|
| o 10:5ae4c968c6ac C
| |
@@ -203,17 +203,17 @@
42ccdea3bb16d28e1848c95fe2e44c000f3f21b1 0 {'date': '* *', 'user': 'test'} (glob)
5fddd98957c8a54a4d436dfe1da9d87f21a1b97b 5ae4c968c6aca831df823664e706c9d4aa34473d 0 {'date': '* *', 'user': 'test'} (glob)
32af7686d403cf45b5d95f2d70cebea587ac806a 0 {'date': '* *', 'user': 'test'} (glob)
- 08483444fef91d6224f6655ee586a65d263ad34c cbc07f26687521cecfc9a141bf5ecfc0fd2b8531 0 {'date': '* *', 'user': 'test'} (glob)
- 8877864f1edb05d0e07dc4ba77b67a80a7b86672 b1861c79d66ec3aa1b607ac3c9fb819e38b12238 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 dd4be135457a404ce5541de427ae1d98a28f4acd 0 {'date': '* *', 'user': 'test'} (glob)
+ 5ae4c968c6aca831df823664e706c9d4aa34473d 98f6af4ee9539e14da4465128f894c274900b6e5 0 {'date': '* *', 'user': 'test'} (glob)
$ hg log --rev 'divergent()'
$ hg log -G
- @ 13:dd4be135457a C
+ @ 13:98f6af4ee953 C
|
- o 12:b1861c79d66e B
+ o 12:462a34d07e59 B
|
- o 11:cbc07f266875 D
+ o 11:4596109a6a43 D
|
o 7:02de42196ebe H
|
@@ -225,7 +225,22 @@
|/
o 0:cd010b8cd998 A
-
+ $ hg log --style default --debug -r 4596109a6a4328c398bde3a4a3b6737cfade3003
+ changeset: 11:4596109a6a4328c398bde3a4a3b6737cfade3003
+ phase: draft
+ parent: 7:02de42196ebee42ef284b6780a87cdc96e8eaab6
+ parent: -1:0000000000000000000000000000000000000000
+ manifest: 11:a91006e3a02f1edf631f7018e6e5684cf27dd905
+ user: Nicolas Dumazet <nicdumz.commits@gmail.com>
+ date: Sat Apr 30 15:24:48 2011 +0200
+ files+: D
+ extra: branch=default
+ extra: rebase_source=08483444fef91d6224f6655ee586a65d263ad34c
+ extra: source=32af7686d403cf45b5d95f2d70cebea587ac806a
+ description:
+ D
+
+
$ cd ..
collapse rebase
--- a/tests/test-requires.t Mon Oct 07 17:47:19 2013 -0400
+++ b/tests/test-requires.t Mon Oct 07 17:47:55 2013 -0400
@@ -15,5 +15,55 @@
$ hg tip
abort: unknown repository format: requires features 'indoor-pool', 'outdoor-pool' (upgrade Mercurial)!
[255]
+ $ cd ..
+
+Test checking between features supported locally and ones required in
+another repository of push/pull/clone on localhost:
+
+ $ mkdir supported-locally
+ $ cd supported-locally
+
+ $ hg init supported
+ $ echo a > supported/a
+ $ hg -R supported commit -Am '#0 at supported'
+ adding a
+
+ $ echo 'featuresetup-test' >> supported/.hg/requires
+ $ cat > $TESTTMP/supported-locally/supportlocally.py <<EOF
+ > from mercurial import localrepo, extensions
+ > def featuresetup(ui, supported):
+ > for name, module in extensions.extensions(ui):
+ > if __name__ == module.__name__:
+ > # support specific feature locally
+ > supported |= set(['featuresetup-test'])
+ > return
+ > def uisetup(ui):
+ > localrepo.localrepository.featuresetupfuncs.add(featuresetup)
+ > EOF
+ $ cat > supported/.hg/hgrc <<EOF
+ > [extensions]
+ > # enable extension locally
+ > supportlocally = $TESTTMP/supported-locally/supportlocally.py
+ > EOF
+ $ hg -R supported status
+
+ $ hg init push-dst
+ $ hg -R supported push push-dst
+ pushing to push-dst
+ abort: required features are not supported in the destination: featuresetup-test
+ [255]
+
+ $ hg init pull-src
+ $ hg -R pull-src pull supported
+ pulling from supported
+ abort: required features are not supported in the destination: featuresetup-test
+ [255]
+
+ $ hg clone supported clone-dst
+ abort: unknown repository format: requires features 'featuresetup-test' (upgrade Mercurial)!
+ [255]
+ $ hg clone --pull supported clone-dst
+ abort: required features are not supported in the destination: featuresetup-test
+ [255]
$ cd ..
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/test-shelve.t Mon Oct 07 17:47:55 2013 -0400
@@ -0,0 +1,440 @@
+ $ echo "[extensions]" >> $HGRCPATH
+ $ echo "mq=" >> $HGRCPATH
+ $ echo "shelve=" >> $HGRCPATH
+ $ echo "[defaults]" >> $HGRCPATH
+ $ echo "diff = --nodates --git" >> $HGRCPATH
+ $ echo "qnew = --date '0 0'" >> $HGRCPATH
+
+ $ hg init repo
+ $ cd repo
+ $ mkdir a b
+ $ echo a > a/a
+ $ echo b > b/b
+ $ echo c > c
+ $ echo d > d
+ $ echo x > x
+ $ hg addremove -q
+
+shelving in an empty repo should be possible
+
+ $ hg shelve
+ shelved as default
+ 0 files updated, 0 files merged, 5 files removed, 0 files unresolved
+
+ $ hg unshelve
+ unshelving change 'default'
+ adding changesets
+ adding manifests
+ adding file changes
+ added 1 changesets with 5 changes to 5 files
+ 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
+
+ $ hg commit -q -m 'initial commit'
+
+ $ hg shelve
+ nothing changed
+ [1]
+
+create an mq patch - shelving should work fine with a patch applied
+
+ $ echo n > n
+ $ hg add n
+ $ hg commit n -m second
+ $ hg qnew second.patch
+
+shelve a change that we will delete later
+
+ $ echo a >> a/a
+ $ hg shelve
+ shelved as default
+ 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
+
+set up some more complex changes to shelve
+
+ $ echo a >> a/a
+ $ hg mv b b.rename
+ moving b/b to b.rename/b (glob)
+ $ hg cp c c.copy
+ $ hg status -C
+ M a/a
+ A b.rename/b
+ b/b
+ A c.copy
+ c
+ R b/b
+
+prevent some foot-shooting
+
+ $ hg shelve -n foo/bar
+ abort: shelved change names may not contain slashes
+ [255]
+ $ hg shelve -n .baz
+ abort: shelved change names may not start with '.'
+ [255]
+
+the common case - no options or filenames
+
+ $ hg shelve
+ shelved as default-01
+ 2 files updated, 0 files merged, 2 files removed, 0 files unresolved
+ $ hg status -C
+
+ensure that our shelved changes exist
+
+ $ hg shelve -l
+ default-01 (*) [mq]: second.patch (glob)
+ default (*) [mq]: second.patch (glob)
+
+ $ hg shelve -l -p default
+ default (*) [mq]: second.patch (glob)
+
+ diff --git a/a/a b/a/a
+ --- a/a/a
+ +++ b/a/a
+ @@ -1,1 +1,2 @@
+ a
+ +a
+
+delete our older shelved change
+
+ $ hg shelve -d default
+ $ hg qfinish -a -q
+
+local edits should prevent a shelved change from applying
+
+ $ echo e>>a/a
+ $ hg unshelve
+ unshelving change 'default-01'
+ the following shelved files have been modified:
+ a/a
+ you must commit, revert, or shelve your changes before you can proceed
+ abort: cannot unshelve due to local changes
+
+ [255]
+
+ $ hg revert -C a/a
+
+apply it and make sure our state is as expected
+
+ $ hg unshelve
+ unshelving change 'default-01'
+ adding changesets
+ adding manifests
+ adding file changes
+ added 1 changesets with 3 changes to 8 files
+ 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
+ $ hg status -C
+ M a/a
+ A b.rename/b
+ b/b
+ A c.copy
+ c
+ R b/b
+ $ hg shelve -l
+
+ $ hg unshelve
+ abort: no shelved changes to apply!
+ [255]
+ $ hg unshelve foo
+ abort: shelved change 'foo' not found
+ [255]
+
+named shelves, specific filenames, and "commit messages" should all work
+
+ $ hg status -C
+ M a/a
+ A b.rename/b
+ b/b
+ A c.copy
+ c
+ R b/b
+ $ hg shelve -q -n wibble -m wat a
+
+expect "a" to no longer be present, but status otherwise unchanged
+
+ $ hg status -C
+ A b.rename/b
+ b/b
+ A c.copy
+ c
+ R b/b
+ $ hg shelve -l --stat
+ wibble (*) wat (glob)
+ a/a | 1 +
+ 1 files changed, 1 insertions(+), 0 deletions(-)
+
+and now "a/a" should reappear
+
+ $ hg unshelve -q wibble
+ $ hg status -C
+ M a/a
+ A b.rename/b
+ b/b
+ A c.copy
+ c
+ R b/b
+
+cause unshelving to result in a merge with 'a' conflicting
+
+ $ hg shelve -q
+ $ echo c>>a/a
+ $ hg commit -m second
+ $ hg tip --template '{files}\n'
+ a/a
+
+add an unrelated change that should be preserved
+
+ $ mkdir foo
+ $ echo foo > foo/foo
+ $ hg add foo/foo
+
+force a conflicted merge to occur
+
+ $ hg unshelve
+ unshelving change 'default'
+ adding changesets
+ adding manifests
+ adding file changes
+ added 1 changesets with 3 changes to 8 files (+1 heads)
+ merging a/a
+ warning: conflicts during merge.
+ merging a/a incomplete! (edit conflicts, then use 'hg resolve --mark')
+ 2 files updated, 0 files merged, 1 files removed, 1 files unresolved
+ use 'hg resolve' to retry unresolved file merges or 'hg update -C .' to abandon
+ unresolved conflicts (see 'hg resolve', then 'hg unshelve --continue')
+ [1]
+
+ensure that we have a merge with unresolved conflicts
+
+ $ hg heads -q
+ 4:cebf2b8de087
+ 3:2e69b451d1ea
+ $ hg parents -q
+ 3:2e69b451d1ea
+ 4:cebf2b8de087
+ $ hg status
+ M a/a
+ M b.rename/b
+ M c.copy
+ A foo/foo
+ R b/b
+ ? a/a.orig
+ $ hg diff
+ diff --git a/a/a b/a/a
+ --- a/a/a
+ +++ b/a/a
+ @@ -1,2 +1,6 @@
+ a
+ +<<<<<<< local
+ c
+ +=======
+ +a
+ +>>>>>>> other
+ diff --git a/b.rename/b b/b.rename/b
+ --- /dev/null
+ +++ b/b.rename/b
+ @@ -0,0 +1,1 @@
+ +b
+ diff --git a/b/b b/b/b
+ deleted file mode 100644
+ --- a/b/b
+ +++ /dev/null
+ @@ -1,1 +0,0 @@
+ -b
+ diff --git a/c.copy b/c.copy
+ --- /dev/null
+ +++ b/c.copy
+ @@ -0,0 +1,1 @@
+ +c
+ diff --git a/foo/foo b/foo/foo
+ new file mode 100644
+ --- /dev/null
+ +++ b/foo/foo
+ @@ -0,0 +1,1 @@
+ +foo
+ $ hg resolve -l
+ U a/a
+
+ $ hg shelve
+ abort: unshelve already in progress
+ (use 'hg unshelve --continue' or 'hg unshelve --abort')
+ [255]
+
+abort the unshelve and be happy
+
+ $ hg status
+ M a/a
+ M b.rename/b
+ M c.copy
+ A foo/foo
+ R b/b
+ ? a/a.orig
+ $ hg unshelve -a
+ unshelve of 'default' aborted
+ $ hg heads -q
+ 3:2e69b451d1ea
+ $ hg parents
+ changeset: 3:2e69b451d1ea
+ tag: tip
+ user: test
+ date: Thu Jan 01 00:00:00 1970 +0000
+ summary: second
+
+ $ hg resolve -l
+ $ hg status
+ A foo/foo
+ ? a/a.orig
+
+try to continue with no unshelve underway
+
+ $ hg unshelve -c
+ abort: no unshelve operation underway
+ [255]
+ $ hg status
+ A foo/foo
+ ? a/a.orig
+
+redo the unshelve to get a conflict
+
+ $ hg unshelve -q
+ warning: conflicts during merge.
+ merging a/a incomplete! (edit conflicts, then use 'hg resolve --mark')
+ unresolved conflicts (see 'hg resolve', then 'hg unshelve --continue')
+ [1]
+
+attempt to continue
+
+ $ hg unshelve -c
+ abort: unresolved conflicts, can't continue
+ (see 'hg resolve', then 'hg unshelve --continue')
+ [255]
+
+ $ hg revert -r . a/a
+ $ hg resolve -m a/a
+
+ $ hg unshelve -c
+ unshelve of 'default' complete
+
+ensure the repo is as we hope
+
+ $ hg parents
+ changeset: 3:2e69b451d1ea
+ tag: tip
+ user: test
+ date: Thu Jan 01 00:00:00 1970 +0000
+ summary: second
+
+ $ hg heads -q
+ 3:2e69b451d1ea
+
+ $ hg status -C
+ M a/a
+ M b.rename/b
+ b/b
+ M c.copy
+ c
+ A foo/foo
+ R b/b
+ ? a/a.orig
+
+there should be no shelves left
+
+ $ hg shelve -l
+
+ $ hg commit -m whee a/a
+
+#if execbit
+
+ensure that metadata-only changes are shelved
+
+ $ chmod +x a/a
+ $ hg shelve -q -n execbit a/a
+ $ hg status a/a
+ $ hg unshelve -q execbit
+ $ hg status a/a
+ M a/a
+ $ hg revert a/a
+
+#endif
+
+#if symlink
+
+ $ rm a/a
+ $ ln -s foo a/a
+ $ hg shelve -q -n symlink a/a
+ $ hg status a/a
+ $ hg unshelve -q symlink
+ $ hg status a/a
+ M a/a
+ $ hg revert a/a
+
+#endif
+
+set up another conflict between a commit and a shelved change
+
+ $ hg revert -q -C -a
+ $ echo a >> a/a
+ $ hg shelve -q
+ $ echo x >> a/a
+ $ hg ci -m 'create conflict'
+ $ hg add foo/foo
+
+if we resolve a conflict while unshelving, the unshelve should succeed
+
+ $ HGMERGE=true hg unshelve
+ unshelving change 'default'
+ adding changesets
+ adding manifests
+ adding file changes
+ added 1 changesets with 1 changes to 6 files (+1 heads)
+ merging a/a
+ 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
+ $ hg parents -q
+ 5:01ba9745dc5a
+ $ hg shelve -l
+ $ hg status
+ M a/a
+ A foo/foo
+ $ cat a/a
+ a
+ c
+ x
+
+test keep and cleanup
+
+ $ hg shelve
+ shelved as default
+ 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
+ $ hg shelve --list
+ default (*) create conflict (glob)
+ $ hg unshelve --keep
+ unshelving change 'default'
+ adding changesets
+ adding manifests
+ adding file changes
+ added 1 changesets with 1 changes to 7 files
+ 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
+ $ hg shelve --list
+ default (*) create conflict (glob)
+ $ hg shelve --cleanup
+ $ hg shelve --list
+
+test bookmarks
+
+ $ hg bookmark test
+ $ hg bookmark
+ * test 5:01ba9745dc5a
+ $ hg shelve
+ shelved as test
+ 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
+ $ hg bookmark
+ * test 5:01ba9745dc5a
+ $ hg unshelve
+ unshelving change 'test'
+ adding changesets
+ adding manifests
+ adding file changes
+ added 1 changesets with 1 changes to 7 files
+ 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
+ $ hg bookmark
+ * test 5:01ba9745dc5a
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/test-strip.t Mon Oct 07 17:47:55 2013 -0400
@@ -0,0 +1,504 @@
+ $ echo "[extensions]" >> $HGRCPATH
+ $ echo "strip=" >> $HGRCPATH
+ $ echo "graphlog=" >> $HGRCPATH
+
+ $ restore() {
+ > hg unbundle -q .hg/strip-backup/*
+ > rm .hg/strip-backup/*
+ > }
+ $ teststrip() {
+ > hg up -C $1
+ > echo % before update $1, strip $2
+ > hg parents
+ > hg --traceback strip $2
+ > echo % after update $1, strip $2
+ > hg parents
+ > restore
+ > }
+
+ $ hg init test
+ $ cd test
+
+ $ echo foo > bar
+ $ hg ci -Ama
+ adding bar
+
+ $ echo more >> bar
+ $ hg ci -Amb
+
+ $ echo blah >> bar
+ $ hg ci -Amc
+
+ $ hg up 1
+ 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
+ $ echo blah >> bar
+ $ hg ci -Amd
+ created new head
+
+ $ echo final >> bar
+ $ hg ci -Ame
+
+ $ hg log
+ changeset: 4:443431ffac4f
+ tag: tip
+ user: test
+ date: Thu Jan 01 00:00:00 1970 +0000
+ summary: e
+
+ changeset: 3:65bd5f99a4a3
+ parent: 1:ef3a871183d7
+ user: test
+ date: Thu Jan 01 00:00:00 1970 +0000
+ summary: d
+
+ changeset: 2:264128213d29
+ user: test
+ date: Thu Jan 01 00:00:00 1970 +0000
+ summary: c
+
+ changeset: 1:ef3a871183d7
+ user: test
+ date: Thu Jan 01 00:00:00 1970 +0000
+ summary: b
+
+ changeset: 0:9ab35a2d17cb
+ user: test
+ date: Thu Jan 01 00:00:00 1970 +0000
+ summary: a
+
+
+ $ teststrip 4 4
+ 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
+ % before update 4, strip 4
+ changeset: 4:443431ffac4f
+ tag: tip
+ user: test
+ date: Thu Jan 01 00:00:00 1970 +0000
+ summary: e
+
+ 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
+ saved backup bundle to $TESTTMP/test/.hg/strip-backup/*-backup.hg (glob)
+ % after update 4, strip 4
+ changeset: 3:65bd5f99a4a3
+ tag: tip
+ parent: 1:ef3a871183d7
+ user: test
+ date: Thu Jan 01 00:00:00 1970 +0000
+ summary: d
+
+ $ teststrip 4 3
+ 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
+ % before update 4, strip 3
+ changeset: 4:443431ffac4f
+ tag: tip
+ user: test
+ date: Thu Jan 01 00:00:00 1970 +0000
+ summary: e
+
+ 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
+ saved backup bundle to $TESTTMP/test/.hg/strip-backup/*-backup.hg (glob)
+ % after update 4, strip 3
+ changeset: 1:ef3a871183d7
+ user: test
+ date: Thu Jan 01 00:00:00 1970 +0000
+ summary: b
+
+ $ teststrip 1 4
+ 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
+ % before update 1, strip 4
+ changeset: 1:ef3a871183d7
+ user: test
+ date: Thu Jan 01 00:00:00 1970 +0000
+ summary: b
+
+ saved backup bundle to $TESTTMP/test/.hg/strip-backup/*-backup.hg (glob)
+ % after update 1, strip 4
+ changeset: 1:ef3a871183d7
+ user: test
+ date: Thu Jan 01 00:00:00 1970 +0000
+ summary: b
+
+ $ teststrip 4 2
+ 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
+ % before update 4, strip 2
+ changeset: 4:443431ffac4f
+ tag: tip
+ user: test
+ date: Thu Jan 01 00:00:00 1970 +0000
+ summary: e
+
+ saved backup bundle to $TESTTMP/test/.hg/strip-backup/*-backup.hg (glob)
+ % after update 4, strip 2
+ changeset: 3:443431ffac4f
+ tag: tip
+ user: test
+ date: Thu Jan 01 00:00:00 1970 +0000
+ summary: e
+
+ $ teststrip 4 1
+ 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
+ % before update 4, strip 1
+ changeset: 4:264128213d29
+ tag: tip
+ parent: 1:ef3a871183d7
+ user: test
+ date: Thu Jan 01 00:00:00 1970 +0000
+ summary: c
+
+ 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
+ saved backup bundle to $TESTTMP/test/.hg/strip-backup/*-backup.hg (glob)
+ % after update 4, strip 1
+ changeset: 0:9ab35a2d17cb
+ tag: tip
+ user: test
+ date: Thu Jan 01 00:00:00 1970 +0000
+ summary: a
+
+ $ teststrip null 4
+ 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
+ % before update null, strip 4
+ saved backup bundle to $TESTTMP/test/.hg/strip-backup/*-backup.hg (glob)
+ % after update null, strip 4
+
+ $ hg log
+ changeset: 4:264128213d29
+ tag: tip
+ parent: 1:ef3a871183d7
+ user: test
+ date: Thu Jan 01 00:00:00 1970 +0000
+ summary: c
+
+ changeset: 3:443431ffac4f
+ user: test
+ date: Thu Jan 01 00:00:00 1970 +0000
+ summary: e
+
+ changeset: 2:65bd5f99a4a3
+ user: test
+ date: Thu Jan 01 00:00:00 1970 +0000
+ summary: d
+
+ changeset: 1:ef3a871183d7
+ user: test
+ date: Thu Jan 01 00:00:00 1970 +0000
+ summary: b
+
+ changeset: 0:9ab35a2d17cb
+ user: test
+ date: Thu Jan 01 00:00:00 1970 +0000
+ summary: a
+
+
+ $ hg up -C 2
+ 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
+ $ hg merge 4
+ 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
+ (branch merge, don't forget to commit)
+
+before strip of merge parent
+
+ $ hg parents
+ changeset: 2:65bd5f99a4a3
+ user: test
+ date: Thu Jan 01 00:00:00 1970 +0000
+ summary: d
+
+ changeset: 4:264128213d29
+ tag: tip
+ parent: 1:ef3a871183d7
+ user: test
+ date: Thu Jan 01 00:00:00 1970 +0000
+ summary: c
+
+ $ hg strip 4
+ 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
+ saved backup bundle to $TESTTMP/test/.hg/strip-backup/*-backup.hg (glob)
+
+after strip of merge parent
+
+ $ hg parents
+ changeset: 1:ef3a871183d7
+ user: test
+ date: Thu Jan 01 00:00:00 1970 +0000
+ summary: b
+
+ $ restore
+
+ $ hg up
+ 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
+ $ hg glog
+ @ changeset: 4:264128213d29
+ | tag: tip
+ | parent: 1:ef3a871183d7
+ | user: test
+ | date: Thu Jan 01 00:00:00 1970 +0000
+ | summary: c
+ |
+ | o changeset: 3:443431ffac4f
+ | | user: test
+ | | date: Thu Jan 01 00:00:00 1970 +0000
+ | | summary: e
+ | |
+ | o changeset: 2:65bd5f99a4a3
+ |/ user: test
+ | date: Thu Jan 01 00:00:00 1970 +0000
+ | summary: d
+ |
+ o changeset: 1:ef3a871183d7
+ | user: test
+ | date: Thu Jan 01 00:00:00 1970 +0000
+ | summary: b
+ |
+ o changeset: 0:9ab35a2d17cb
+ user: test
+ date: Thu Jan 01 00:00:00 1970 +0000
+ summary: a
+
+
+2 is parent of 3, only one strip should happen
+
+ $ hg strip "roots(2)" 3
+ saved backup bundle to $TESTTMP/test/.hg/strip-backup/*-backup.hg (glob)
+ $ hg glog
+ @ changeset: 2:264128213d29
+ | tag: tip
+ | user: test
+ | date: Thu Jan 01 00:00:00 1970 +0000
+ | summary: c
+ |
+ o changeset: 1:ef3a871183d7
+ | user: test
+ | date: Thu Jan 01 00:00:00 1970 +0000
+ | summary: b
+ |
+ o changeset: 0:9ab35a2d17cb
+ user: test
+ date: Thu Jan 01 00:00:00 1970 +0000
+ summary: a
+
+ $ restore
+ $ hg glog
+ o changeset: 4:443431ffac4f
+ | tag: tip
+ | user: test
+ | date: Thu Jan 01 00:00:00 1970 +0000
+ | summary: e
+ |
+ o changeset: 3:65bd5f99a4a3
+ | parent: 1:ef3a871183d7
+ | user: test
+ | date: Thu Jan 01 00:00:00 1970 +0000
+ | summary: d
+ |
+ | @ changeset: 2:264128213d29
+ |/ user: test
+ | date: Thu Jan 01 00:00:00 1970 +0000
+ | summary: c
+ |
+ o changeset: 1:ef3a871183d7
+ | user: test
+ | date: Thu Jan 01 00:00:00 1970 +0000
+ | summary: b
+ |
+ o changeset: 0:9ab35a2d17cb
+ user: test
+ date: Thu Jan 01 00:00:00 1970 +0000
+ summary: a
+
+
+2 different branches: 2 strips
+
+ $ hg strip 2 4
+ 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
+ saved backup bundle to $TESTTMP/test/.hg/strip-backup/*-backup.hg (glob)
+ $ hg glog
+ o changeset: 2:65bd5f99a4a3
+ | tag: tip
+ | user: test
+ | date: Thu Jan 01 00:00:00 1970 +0000
+ | summary: d
+ |
+ @ changeset: 1:ef3a871183d7
+ | user: test
+ | date: Thu Jan 01 00:00:00 1970 +0000
+ | summary: b
+ |
+ o changeset: 0:9ab35a2d17cb
+ user: test
+ date: Thu Jan 01 00:00:00 1970 +0000
+ summary: a
+
+ $ restore
+
+2 different branches and a common ancestor: 1 strip
+
+ $ hg strip 1 "2|4"
+ 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
+ saved backup bundle to $TESTTMP/test/.hg/strip-backup/*-backup.hg (glob)
+ $ restore
+
+stripping an empty revset
+
+ $ hg strip "1 and not 1"
+ abort: empty revision set
+ [255]
+
+remove branchy history for qimport tests
+
+ $ hg strip 3
+ saved backup bundle to $TESTTMP/test/.hg/strip-backup/*-backup.hg (glob)
+
+
+strip of applied mq should cleanup status file
+
+ $ echo "mq=" >> $HGRCPATH
+ $ hg up -C 3
+ 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
+ $ echo fooagain >> bar
+ $ hg ci -mf
+ $ hg qimport -r tip:2
+
+applied patches before strip
+
+ $ hg qapplied
+ 2.diff
+ 3.diff
+ 4.diff
+
+stripping revision in queue
+
+ $ hg strip 3
+ 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
+ saved backup bundle to $TESTTMP/test/.hg/strip-backup/*-backup.hg (glob)
+
+applied patches after stripping rev in queue
+
+ $ hg qapplied
+ 2.diff
+
+stripping ancestor of queue
+
+ $ hg strip 1
+ 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
+ saved backup bundle to $TESTTMP/test/.hg/strip-backup/*-backup.hg (glob)
+
+applied patches after stripping ancestor of queue
+
+ $ hg qapplied
+
+Verify strip protects against stripping wc parent when there are uncommited mods
+
+ $ echo b > b
+ $ hg add b
+ $ hg ci -m 'b'
+ $ hg log --graph
+ @ changeset: 1:7519abd79d14
+ | tag: tip
+ | user: test
+ | date: Thu Jan 01 00:00:00 1970 +0000
+ | summary: b
+ |
+ o changeset: 0:9ab35a2d17cb
+ user: test
+ date: Thu Jan 01 00:00:00 1970 +0000
+ summary: a
+
+
+ $ echo c > b
+ $ echo c > bar
+ $ hg strip tip
+ abort: local changes found
+ [255]
+ $ hg strip tip --keep
+ saved backup bundle to $TESTTMP/test/.hg/strip-backup/*-backup.hg (glob)
+ $ hg log --graph
+ @ changeset: 0:9ab35a2d17cb
+ tag: tip
+ user: test
+ date: Thu Jan 01 00:00:00 1970 +0000
+ summary: a
+
+ $ hg status
+ M bar
+ ? b
+
+Strip adds, removes, modifies with --keep
+
+ $ touch b
+ $ hg add b
+ $ hg commit -mb
+ $ touch c
+
+... with a clean working dir
+
+ $ hg add c
+ $ hg rm bar
+ $ hg commit -mc
+ $ hg status
+ $ hg strip --keep tip
+ saved backup bundle to $TESTTMP/test/.hg/strip-backup/*-backup.hg (glob)
+ $ hg status
+ ! bar
+ ? c
+
+... with a dirty working dir
+
+ $ hg add c
+ $ hg rm bar
+ $ hg commit -mc
+ $ hg status
+ $ echo b > b
+ $ echo d > d
+ $ hg strip --keep tip
+ saved backup bundle to $TESTTMP/test/.hg/strip-backup/*-backup.hg (glob)
+ $ hg status
+ M b
+ ! bar
+ ? c
+ ? d
+ $ cd ..
+
+stripping many nodes on a complex graph (issue3299)
+
+ $ hg init issue3299
+ $ cd issue3299
+ $ hg debugbuilddag '@a.:a@b.:b.:x<a@a.:a<b@b.:b<a@a.:a'
+ $ hg strip 'not ancestors(x)'
+ saved backup bundle to $TESTTMP/issue3299/.hg/strip-backup/*-backup.hg (glob)
+
+test hg strip -B bookmark
+
+ $ cd ..
+ $ hg init bookmarks
+ $ cd bookmarks
+ $ hg debugbuilddag '..<2.*1/2:m<2+3:c<m+3:a<2.:b'
+ $ hg bookmark -r 'a' 'todelete'
+ $ hg bookmark -r 'b' 'B'
+ $ hg bookmark -r 'b' 'nostrip'
+ $ hg bookmark -r 'c' 'delete'
+ $ hg up -C todelete
+ 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
+ $ hg strip -B nostrip
+ bookmark 'nostrip' deleted
+ abort: empty revision set
+ [255]
+ $ hg strip -B todelete
+ bookmark 'todelete' deleted
+ 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
+ saved backup bundle to $TESTTMP/bookmarks/.hg/strip-backup/*-backup.hg (glob)
+ $ hg id -ir dcbb326fdec2
+ abort: unknown revision 'dcbb326fdec2'!
+ [255]
+ $ hg id -ir d62d843c9a01
+ d62d843c9a01
+ $ hg bookmarks
+ B 9:ff43616e5d0f
+ delete 6:2702dd0c91e7
+ $ hg strip -B delete
+ bookmark 'delete' deleted
+ saved backup bundle to $TESTTMP/bookmarks/.hg/strip-backup/*-backup.hg (glob)
+ $ hg id -ir 6:2702dd0c91e7
+ abort: unknown revision '2702dd0c91e7'!
+ [255]
+
+ $ cd ..
--- a/tests/test-subrepo-git.t Mon Oct 07 17:47:19 2013 -0400
+++ b/tests/test-subrepo-git.t Mon Oct 07 17:47:55 2013 -0400
@@ -155,6 +155,8 @@
added 1 changesets with 1 changes to 1 files (+1 heads)
(run 'hg heads' to see heads, 'hg merge' to merge)
$ hg merge 2>/dev/null
+ subrepository s diverged (local revision: 796959400868, remote revision: aa84837ccfbd)
+ (M)erge, keep (l)ocal or keep (r)emote? m
pulling subrepo s from $TESTTMP/gitroot
0 files updated, 0 files merged, 0 files removed, 0 files unresolved
(branch merge, don't forget to commit)
@@ -462,6 +464,8 @@
da5f5b1d8ffcf62fb8327bcd3c89a4367a6018e7
$ cd ..
$ hg update 4
+ subrepository s diverged (local revision: da5f5b1d8ffc, remote revision: aa84837ccfbd)
+ (M)erge, keep (l)ocal or keep (r)emote? m
subrepository sources for s differ
use (l)ocal source (da5f5b1) or (r)emote source (aa84837)?
l
@@ -487,6 +491,8 @@
HEAD is now at aa84837... f
$ cd ..
$ hg update 1
+ subrepository s diverged (local revision: 32a343883b74, remote revision: da5f5b1d8ffc)
+ (M)erge, keep (l)ocal or keep (r)emote? m
subrepository sources for s differ (in checked out version)
use (l)ocal source (32a3438) or (r)emote source (da5f5b1)?
l
@@ -508,6 +514,8 @@
$ hg id -n
1+
$ hg update 7
+ subrepository s diverged (local revision: 32a343883b74, remote revision: 32a343883b74)
+ (M)erge, keep (l)ocal or keep (r)emote? m
subrepository sources for s differ
use (l)ocal source (32a3438) or (r)emote source (32a3438)?
l
--- a/tests/test-subrepo-svn.t Mon Oct 07 17:47:19 2013 -0400
+++ b/tests/test-subrepo-svn.t Mon Oct 07 17:47:55 2013 -0400
@@ -319,6 +319,8 @@
2M
$ cd ..
$ hg update tip
+ subrepository s diverged (local revision: 2, remote revision: 3)
+ (M)erge, keep (l)ocal or keep (r)emote? m
subrepository sources for s differ
use (l)ocal source (2) or (r)emote source (3)?
l
@@ -349,6 +351,8 @@
$ svn update -qr 1
$ cd ..
$ hg update 1
+ subrepository s diverged (local revision: 3, remote revision: 2)
+ (M)erge, keep (l)ocal or keep (r)emote? m
subrepository sources for s differ (in checked out version)
use (l)ocal source (1) or (r)emote source (2)?
l
@@ -371,6 +375,8 @@
$ hg id -n
1+
$ hg update tip
+ subrepository s diverged (local revision: 3, remote revision: 3)
+ (M)erge, keep (l)ocal or keep (r)emote? m
subrepository sources for s differ
use (l)ocal source (1) or (r)emote source (3)?
l
@@ -404,6 +410,8 @@
$ svn update -qr 2
$ cd ..
$ hg update 1
+ subrepository s diverged (local revision: 3, remote revision: 2)
+ (M)erge, keep (l)ocal or keep (r)emote? m
1 files updated, 0 files merged, 0 files removed, 0 files unresolved
$ hg id -n
1+
@@ -477,7 +485,8 @@
This is surprising, but is also correct based on the current code:
$ echo "updating should (maybe) fail" > obstruct/other
$ hg co tip
- abort: crosses branches (merge branches or use --clean to discard changes)
+ abort: uncommitted changes
+ (commit or update --clean to discard changes)
[255]
Point to a Subversion branch which has since been deleted and recreated
--- a/tests/test-subrepo.t Mon Oct 07 17:47:19 2013 -0400
+++ b/tests/test-subrepo.t Mon Oct 07 17:47:55 2013 -0400
@@ -236,7 +236,9 @@
.hgsubstate: versions differ -> m
updating: .hgsubstate 1/1 files (100.00%)
subrepo merge e45c8b14af55+ f94576341bcf 1831e14459c4
- subrepo t: both sides changed, merge with t:7af322bc1198a32402fe903e0b7ebcfc5c9bf8f4:hg
+ subrepo t: both sides changed
+ subrepository t diverged (local revision: 20a0db6fbf6c, remote revision: 7af322bc1198)
+ (M)erge, keep (l)ocal or keep (r)emote? m
merging subrepo t
searching for copies back to rev 2
resolving manifests
@@ -252,6 +254,7 @@
merging t 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
+ subrepo t: merge with t:7af322bc1198a32402fe903e0b7ebcfc5c9bf8f4:hg
0 files updated, 0 files merged, 0 files removed, 0 files unresolved
(branch merge, don't forget to commit)
@@ -620,6 +623,8 @@
$ hg up 5
0 files updated, 0 files merged, 0 files removed, 0 files unresolved
$ hg merge 4 # try to merge default into br again
+ subrepository s diverged (local revision: f8f13b33206e, remote revision: a3f9062a4f88)
+ (M)erge, keep (l)ocal or keep (r)emote? m
1 files updated, 0 files merged, 0 files removed, 0 files unresolved
(branch merge, don't forget to commit)
$ cd ..
@@ -922,9 +927,13 @@
$ hg -R t id
e95bcfa18a35+
$ hg update tip
+ subrepository s diverged (local revision: fc627a69481f, remote revision: 12a213df6fa9)
+ (M)erge, keep (l)ocal or keep (r)emote? m
subrepository sources for s differ
use (l)ocal source (fc627a69481f) or (r)emote source (12a213df6fa9)?
l
+ subrepository t diverged (local revision: e95bcfa18a35, remote revision: 52c0adc0515a)
+ (M)erge, keep (l)ocal or keep (r)emote? m
subrepository sources for t differ
use (l)ocal source (e95bcfa18a35) or (r)emote source (52c0adc0515a)?
l
@@ -953,6 +962,10 @@
1 files updated, 0 files merged, 0 files removed, 0 files unresolved
$ cd ..
$ hg update 10
+ subrepository s diverged (local revision: 12a213df6fa9, remote revision: fc627a69481f)
+ (M)erge, keep (l)ocal or keep (r)emote? m
+ subrepository t diverged (local revision: 52c0adc0515a, remote revision: 20a0db6fbf6c)
+ (M)erge, keep (l)ocal or keep (r)emote? m
subrepository sources for t differ (in checked out version)
use (l)ocal source (7af322bc1198) or (r)emote source (20a0db6fbf6c)?
l
@@ -976,9 +989,13 @@
$ hg -R t id
7af322bc1198+
$ hg update tip
+ subrepository s diverged (local revision: 12a213df6fa9, remote revision: 12a213df6fa9)
+ (M)erge, keep (l)ocal or keep (r)emote? m
subrepository sources for s differ
use (l)ocal source (02dcf1d70411) or (r)emote source (12a213df6fa9)?
l
+ subrepository t diverged (local revision: 52c0adc0515a, remote revision: 52c0adc0515a)
+ (M)erge, keep (l)ocal or keep (r)emote? m
subrepository sources for t differ
use (l)ocal source (7af322bc1198) or (r)emote source (52c0adc0515a)?
l
@@ -1006,6 +1023,8 @@
1 files updated, 0 files merged, 0 files removed, 0 files unresolved
$ cd ..
$ hg update 11
+ subrepository s diverged (local revision: 12a213df6fa9, remote revision: fc627a69481f)
+ (M)erge, keep (l)ocal or keep (r)emote? m
0 files updated, 0 files merged, 0 files removed, 0 files unresolved
0 files updated, 0 files merged, 0 files removed, 0 files unresolved
$ hg id -n
--- a/tests/test-symlink-placeholder.t Mon Oct 07 17:47:19 2013 -0400
+++ b/tests/test-symlink-placeholder.t Mon Oct 07 17:47:55 2013 -0400
@@ -41,6 +41,13 @@
a (no-eol)
$ hg --config extensions.n=$TESTTMP/nolink.py st --debug
+Empty placeholder:
+
+ $ rm b
+ $ touch b
+ $ hg --config extensions.n=$TESTTMP/nolink.py st --debug
+ ignoring suspect symlink placeholder "b"
+
Write binary data to the placeholder:
>>> open('b', 'w').write('this is a binary\0')
--- a/tests/test-trusted.py Mon Oct 07 17:47:19 2013 -0400
+++ b/tests/test-trusted.py Mon Oct 07 17:47:55 2013 -0400
@@ -145,7 +145,7 @@
f.write('[foobar]\n')
f.write('baz = quux\n')
f.close()
-u.readconfig(filename, sections = ['foobar'])
+u.readconfig(filename, sections=['foobar'])
print u.config('foobar', 'baz')
print
--- a/tests/test-up-local-change.t Mon Oct 07 17:47:19 2013 -0400
+++ b/tests/test-up-local-change.t Mon Oct 07 17:47:55 2013 -0400
@@ -167,10 +167,11 @@
summary: 2
$ hg --debug up
- abort: crosses branches (merge branches or use --clean to discard changes)
+ abort: uncommitted changes
+ (commit and merge, or update --clean to discard changes)
[255]
$ hg --debug merge
- abort: outstanding uncommitted changes
+ abort: uncommitted changes
(use 'hg status' to list changes)
[255]
$ hg --debug merge -f
--- a/tests/test-update-branches.t Mon Oct 07 17:47:19 2013 -0400
+++ b/tests/test-update-branches.t Mon Oct 07 17:47:55 2013 -0400
@@ -94,7 +94,8 @@
parent=5
$ norevtest 'none clean same' clean 2
- abort: crosses branches (merge branches or update --check to force update)
+ abort: not a linear update
+ (merge or update --check to force update)
parent=2
@@ -122,22 +123,32 @@
M sub/suba
$ revtest 'none dirty same' dirty 2 3
- abort: crosses branches (merge branches or use --clean to discard changes)
+ abort: uncommitted changes
+ (commit or update --clean to discard changes)
parent=2
M foo
$ revtest 'none dirtysub same' dirtysub 2 3
- abort: crosses branches (merge branches or use --clean to discard changes)
+ abort: uncommitted changes
+ (commit or update --clean to discard changes)
parent=2
M sub/suba
$ revtest 'none dirty cross' dirty 3 4
- abort: crosses branches (merge branches or use --clean to discard changes)
+ abort: uncommitted changes
+ (commit or update --clean to discard changes)
parent=3
M foo
+ $ norevtest 'none dirty cross' dirty 2
+ abort: uncommitted changes
+ (commit and merge, or update --clean to discard changes)
+ parent=2
+ M foo
+
$ revtest 'none dirtysub cross' dirtysub 3 4
- abort: crosses branches (merge branches or use --clean to discard changes)
+ abort: uncommitted changes
+ (commit or update --clean to discard changes)
parent=3
M sub/suba
@@ -146,12 +157,12 @@
parent=2
$ revtest '-c dirty linear' dirty 1 2 -c
- abort: uncommitted local changes
+ abort: uncommitted changes
parent=1
M foo
$ revtest '-c dirtysub linear' dirtysub 1 2 -c
- abort: uncommitted local changes
+ abort: uncommitted changes
parent=1
M sub/suba
@@ -222,5 +233,6 @@
$ hg up --quiet 0
$ hg up --quiet 2
$ hg up 5
- abort: crosses branches (merge branches or use --clean to discard changes)
+ abort: uncommitted changes
+ (commit or update --clean to discard changes)
[255]
--- a/tests/test-update-issue1456.t Mon Oct 07 17:47:19 2013 -0400
+++ b/tests/test-update-issue1456.t Mon Oct 07 17:47:55 2013 -0400
@@ -18,7 +18,7 @@
$ echo dirty > foo
$ hg up -c
- abort: uncommitted local changes
+ abort: uncommitted changes
[255]
$ hg up -q
$ cat foo
--- a/tests/test-walk.t Mon Oct 07 17:47:19 2013 -0400
+++ b/tests/test-walk.t Mon Oct 07 17:47:55 2013 -0400
@@ -3,11 +3,11 @@
$ mkdir -p beans
$ for b in kidney navy turtle borlotti black pinto; do
> echo $b > beans/$b
- $ done
+ > done
$ mkdir -p mammals/Procyonidae
$ for m in cacomistle coatimundi raccoon; do
> echo $m > mammals/Procyonidae/$m
- $ done
+ > done
$ echo skunk > mammals/skunk
$ echo fennel > fennel
$ echo fenugreek > fenugreek