--- a/contrib/check-code.py Sun May 13 11:19:48 2012 +0200
+++ b/contrib/check-code.py Sun May 13 12:52:24 2012 +0200
@@ -45,12 +45,10 @@
[
(r'pushd|popd', "don't use 'pushd' or 'popd', use 'cd'"),
(r'\W\$?\(\([^\)\n]*\)\)', "don't use (()) or $(()), use 'expr'"),
- (r'^function', "don't use 'function', use old style"),
(r'grep.*-q', "don't use 'grep -q', redirect to /dev/null"),
(r'sed.*-i', "don't use 'sed -i', use a temporary file"),
(r'echo.*\\n', "don't use 'echo \\n', use printf"),
(r'echo -n', "don't use 'echo -n', use printf"),
- (r'^diff.*-\w*N', "don't use 'diff -N'"),
(r'(^| )wc[^|]*$\n(?!.*\(re\))', "filter wc output"),
(r'head -c', "don't use 'head -c', use 'dd'"),
(r'sha1sum', "don't use sha1sum, use $TESTDIR/md5sum.py"),
@@ -62,10 +60,8 @@
(r'(^|\|\s*)grep (-\w\s+)*[^|]*[(|]\w',
"use egrep for extended grep syntax"),
(r'/bin/', "don't use explicit paths for tools"),
- (r'\$PWD', "don't use $PWD, use `pwd`"),
(r'[^\n]\Z', "no trailing newline"),
(r'export.*=', "don't export and assign at once"),
- (r'^([^"\'\n]|("[^"\n]*")|(\'[^\'\n]*\'))*\^', "^ must be quoted"),
(r'^source\b', "don't use 'source', use '.'"),
(r'touch -d', "don't use 'touch -d', use 'touch -t' instead"),
(r'ls +[^|\n-]+ +-', "options to 'ls' must come before filenames"),
@@ -79,7 +75,12 @@
(r'^( *)\t', "don't use tabs to indent"),
],
# warnings
- []
+ [
+ (r'^function', "don't use 'function', use old style"),
+ (r'^diff.*-\w*N', "don't use 'diff -N'"),
+ (r'\$PWD', "don't use $PWD, use `pwd`"),
+ (r'^([^"\'\n]|("[^"\n]*")|(\'[^\'\n]*\'))*\^', "^ must be quoted"),
+ ]
]
testfilters = [
@@ -91,7 +92,8 @@
utestpats = [
[
(r'^(\S| $ ).*(\S[ \t]+|^[ \t]+)\n', "trailing whitespace on non-output"),
- (uprefix + r'.*\|\s*sed', "use regex test output patterns instead of sed"),
+ (uprefix + r'.*\|\s*sed[^|>\n]*\n',
+ "use regex test output patterns instead of sed"),
(uprefix + r'(true|exit 0)', "explicit zero exit unnecessary"),
(uprefix + r'.*(?<!\[)\$\?', "explicit exit code checks unnecessary"),
(uprefix + r'.*\|\| echo.*(fail|error)',
@@ -106,9 +108,9 @@
for i in [0, 1]:
for p, m in testpats[i]:
if p.startswith(r'^'):
- p = r"^ \$ (%s)" % p[1:]
+ p = r"^ [$>] (%s)" % p[1:]
else:
- p = r"^ \$ .*(%s)" % p
+ p = r"^ [$>] .*(%s)" % p
utestpats[i].append((p, m))
utestfilters = [
@@ -137,7 +139,8 @@
(r' x+[xo][\'"]\n\s+[\'"]x', 'string join across lines with no space'),
(r'[^\n]\Z', "no trailing newline"),
(r'(\S[ \t]+|^[ \t]+)\n', "trailing whitespace"),
-# (r'^\s+[^_ \n][^_. \n]+_[^_\n]+\s*=', "don't use underbars in identifiers"),
+# (r'^\s+[^_ \n][^_. \n]+_[^_\n]+\s*=',
+# "don't use underbars in identifiers"),
(r'^\s+(self\.)?[A-za-z][a-z0-9]+[A-Z]\w* = ',
"don't use camelcase in identifiers"),
(r'^\s*(if|while|def|class|except|try)\s[^[\n]*:\s*[^\\n]#\s]+',
@@ -199,6 +202,7 @@
"always assign an opened file to a variable, and close it afterwards"),
(r'(?i)descendent', "the proper spelling is descendAnt"),
(r'\.debug\(\_', "don't mark debug messages for translation"),
+ (r'\.strip\(\)\.split\(\)', "no need to strip before splitting"),
],
# warnings
[
--- a/contrib/debugcmdserver.py Sun May 13 11:19:48 2012 +0200
+++ b/contrib/debugcmdserver.py Sun May 13 12:52:24 2012 +0200
@@ -24,7 +24,7 @@
def read(size):
data = sys.stdin.read(size)
if not data:
- raise EOFError()
+ raise EOFError
sys.stdout.write(data)
sys.stdout.flush()
return data
--- a/contrib/perf.py Sun May 13 11:19:48 2012 +0200
+++ b/contrib/perf.py Sun May 13 12:52:24 2012 +0200
@@ -33,16 +33,17 @@
try:
m = scmutil.match(repo[None], pats, {})
timer(lambda: len(list(repo.dirstate.walk(m, [], True, False))))
- except:
+ except Exception:
try:
m = scmutil.match(repo[None], pats, {})
timer(lambda: len([b for a, b, c in repo.dirstate.statwalk([], m)]))
- except:
+ except Exception:
timer(lambda: len(list(cmdutil.walk(repo, pats, {}))))
def perfstatus(ui, repo, *pats):
#m = match.always(repo.root, repo.getcwd())
- #timer(lambda: sum(map(len, repo.dirstate.status(m, [], False, False, False))))
+ #timer(lambda: sum(map(len, repo.dirstate.status(m, [], False, False,
+ # False))))
timer(lambda: sum(map(len, repo.status())))
def perfheads(ui, repo):
--- a/contrib/setup3k.py Sun May 13 11:19:48 2012 +0200
+++ b/contrib/setup3k.py Sun May 13 12:52:24 2012 +0200
@@ -26,22 +26,22 @@
try:
import hashlib
sha = hashlib.sha1()
-except:
+except ImportError:
try:
import sha
- except:
+ except ImportError:
raise SystemExit(
"Couldn't import standard hashlib (incomplete Python install).")
try:
import zlib
-except:
+except ImportError:
raise SystemExit(
"Couldn't import standard zlib (incomplete Python install).")
try:
import bz2
-except:
+except ImportError:
raise SystemExit(
"Couldn't import standard bz2 (incomplete Python install).")
@@ -84,7 +84,7 @@
os.dup2(devnull.fileno(), sys.stderr.fileno())
objects = cc.compile([fname], output_dir=tmpdir)
cc.link_executable(objects, os.path.join(tmpdir, "a.out"))
- except:
+ except Exception:
return False
return True
finally:
--- a/doc/gendoc.py Sun May 13 11:19:48 2012 +0200
+++ b/doc/gendoc.py Sun May 13 12:52:24 2012 +0200
@@ -102,9 +102,9 @@
ui.write("\n")
section(ui, _("Extensions"))
- ui.write(_("This section contains help for extensions that are distributed "
- "together with Mercurial. Help for other extensions is available "
- "in the help system."))
+ ui.write(_("This section contains help for extensions that are "
+ "distributed together with Mercurial. Help for other "
+ "extensions is available in the help system."))
ui.write("\n\n"
".. contents::\n"
" :class: htmlonly\n"
--- a/doc/hgmanpage.py Sun May 13 11:19:48 2012 +0200
+++ b/doc/hgmanpage.py Sun May 13 12:52:24 2012 +0200
@@ -582,7 +582,7 @@
self._docinfo[name],
self.defs['indent'][1],
self.defs['indent'][1]))
- elif not name in skip:
+ elif name not in skip:
if name in self._docinfo_names:
label = self._docinfo_names[name]
else:
--- a/hgext/bugzilla.py Sun May 13 11:19:48 2012 +0200
+++ b/hgext/bugzilla.py Sun May 13 12:52:24 2012 +0200
@@ -416,7 +416,8 @@
for id in bugs.keys():
self.ui.status(_(' bug %s\n') % id)
cmdfmt = self.ui.config('bugzilla', 'notify', self.default_notify)
- bzdir = self.ui.config('bugzilla', 'bzdir', '/var/www/html/bugzilla')
+ bzdir = self.ui.config('bugzilla', 'bzdir',
+ '/var/www/html/bugzilla')
try:
# Backwards-compatible with old notify string, which
# took one string. This will throw with a new format
@@ -468,8 +469,8 @@
userid = self.get_user_id(defaultuser)
user = defaultuser
except KeyError:
- raise util.Abort(_('cannot find bugzilla user id for %s or %s') %
- (user, defaultuser))
+ raise util.Abort(_('cannot find bugzilla user id for %s or %s')
+ % (user, defaultuser))
return (user, userid)
def updatebug(self, bugid, newstate, text, committer):
--- a/hgext/children.py Sun May 13 11:19:48 2012 +0200
+++ b/hgext/children.py Sun May 13 12:52:24 2012 +0200
@@ -8,7 +8,11 @@
# This software may be used and distributed according to the terms of the
# GNU General Public License version 2 or any later version.
-'''command to display child changesets'''
+'''command to display child changesets (DEPRECATED)
+
+This extension is deprecated. You should use :hg:`log -r
+"children(REV)"` instead.
+'''
from mercurial import cmdutil
from mercurial.commands import templateopts
--- a/hgext/convert/__init__.py Sun May 13 11:19:48 2012 +0200
+++ b/hgext/convert/__init__.py Sun May 13 12:52:24 2012 +0200
@@ -328,7 +328,8 @@
('', 'root', '', _('specify cvsroot')),
# Options specific to builtin cvsps
('', 'parents', '', _('show parent changesets')),
- ('', 'ancestors', '', _('show current changeset in ancestor branches')),
+ ('', 'ancestors', '',
+ _('show current changeset in ancestor branches')),
# Options that are ignored for compatibility with cvsps-2.1
('A', 'cvs-direct', None, _('ignored for compatibility')),
],
--- a/hgext/convert/bzr.py Sun May 13 11:19:48 2012 +0200
+++ b/hgext/convert/bzr.py Sun May 13 12:52:24 2012 +0200
@@ -72,7 +72,7 @@
self.ui.warn(_('warning: lightweight checkouts may cause '
'conversion failures, try with a regular '
'branch instead.\n'))
- except:
+ except Exception:
self.ui.note(_('bzr source type could not be determined\n'))
def before(self):
--- a/hgext/convert/common.py Sun May 13 11:19:48 2012 +0200
+++ b/hgext/convert/common.py Sun May 13 12:52:24 2012 +0200
@@ -76,7 +76,7 @@
def getheads(self):
"""Return a list of this repository's heads"""
- raise NotImplementedError()
+ raise NotImplementedError
def getfile(self, name, rev):
"""Return a pair (data, mode) where data is the file content
@@ -84,7 +84,7 @@
identifier returned by a previous call to getchanges(). Raise
IOError to indicate that name was deleted in rev.
"""
- raise NotImplementedError()
+ raise NotImplementedError
def getchanges(self, version):
"""Returns a tuple of (files, copies).
@@ -95,18 +95,18 @@
copies is a dictionary of dest: source
"""
- raise NotImplementedError()
+ raise NotImplementedError
def getcommit(self, version):
"""Return the commit object for version"""
- raise NotImplementedError()
+ raise NotImplementedError
def gettags(self):
"""Return the tags as a dictionary of name: revision
Tag names must be UTF-8 strings.
"""
- raise NotImplementedError()
+ raise NotImplementedError
def recode(self, s, encoding=None):
if not encoding:
@@ -116,10 +116,10 @@
return s.encode("utf-8")
try:
return s.decode(encoding).encode("utf-8")
- except:
+ except UnicodeError:
try:
return s.decode("latin-1").encode("utf-8")
- except:
+ except UnicodeError:
return s.decode(encoding, "replace").encode("utf-8")
def getchangedfiles(self, rev, i):
@@ -133,7 +133,7 @@
This function is only needed to support --filemap
"""
- raise NotImplementedError()
+ raise NotImplementedError
def converted(self, rev, sinkrev):
'''Notify the source that a revision has been converted.'''
@@ -175,13 +175,13 @@
def getheads(self):
"""Return a list of this repository's heads"""
- raise NotImplementedError()
+ raise NotImplementedError
def revmapfile(self):
"""Path to a file that will contain lines
source_rev_id sink_rev_id
mapping equivalent revision identifiers for each system."""
- raise NotImplementedError()
+ raise NotImplementedError
def authorfile(self):
"""Path to a file that will contain lines
@@ -203,7 +203,7 @@
a particular revision (or even what that revision would be)
before it receives the file data.
"""
- raise NotImplementedError()
+ raise NotImplementedError
def puttags(self, tags):
"""Put tags into sink.
@@ -212,7 +212,7 @@
Return a pair (tag_revision, tag_parent_revision), or (None, None)
if nothing was changed.
"""
- raise NotImplementedError()
+ raise NotImplementedError
def setbranch(self, branch, pbranches):
"""Set the current branch name. Called before the first putcommit
@@ -247,7 +247,7 @@
def hascommit(self, rev):
"""Return True if the sink contains rev"""
- raise NotImplementedError()
+ raise NotImplementedError
class commandline(object):
def __init__(self, ui, command):
@@ -333,7 +333,7 @@
argmax = 4096
try:
argmax = os.sysconf("SC_ARG_MAX")
- except:
+ except (AttributeError, ValueError):
pass
# Windows shells impose their own limits on command line length,
--- a/hgext/convert/convcmd.py Sun May 13 11:19:48 2012 +0200
+++ b/hgext/convert/convcmd.py Sun May 13 12:52:24 2012 +0200
@@ -190,7 +190,7 @@
children.setdefault(n, [])
hasparent = False
for p in parents[n]:
- if not p in self.map:
+ if p not in self.map:
visit.append(p)
hasparent = True
children.setdefault(p, []).append(n)
@@ -462,7 +462,7 @@
if not revmapfile:
try:
revmapfile = destc.revmapfile()
- except:
+ except Exception:
revmapfile = os.path.join(destc, "map")
c = converter(ui, srcc, destc, revmapfile, opts)
--- a/hgext/convert/cvs.py Sun May 13 11:19:48 2012 +0200
+++ b/hgext/convert/cvs.py Sun May 13 12:52:24 2012 +0200
@@ -121,12 +121,13 @@
pf = open(cvspass)
for line in pf.read().splitlines():
part1, part2 = line.split(' ', 1)
+ # /1 :pserver:user@example.com:2401/cvsroot/foo
+ # Ah<Z
if part1 == '/1':
- # /1 :pserver:user@example.com:2401/cvsroot/foo Ah<Z
part1, part2 = part2.split(' ', 1)
format = format1
+ # :pserver:user@example.com:/cvsroot/foo Ah<Z
else:
- # :pserver:user@example.com:/cvsroot/foo Ah<Z
format = format0
if part1 == format:
passw = part2
--- a/hgext/convert/cvsps.py Sun May 13 11:19:48 2012 +0200
+++ b/hgext/convert/cvsps.py Sun May 13 12:52:24 2012 +0200
@@ -336,7 +336,8 @@
else:
myrev = '.'.join(myrev[:-2] + ['0', myrev[-2]])
branches = [b for b in branchmap if branchmap[b] == myrev]
- assert len(branches) == 1, 'unknown branch: %s' % e.mergepoint
+ assert len(branches) == 1, ('unknown branch: %s'
+ % e.mergepoint)
e.mergepoint = branches[0]
else:
e.mergepoint = None
@@ -705,11 +706,11 @@
if mergeto:
m = mergeto.search(c.comment)
if m:
- try:
+ if m.groups():
m = m.group(1)
if m == 'HEAD':
m = None
- except:
+ else:
m = None # if no group found then merge to HEAD
if m in branches and c.branch != m:
# insert empty changeset for merge
--- a/hgext/convert/git.py Sun May 13 11:19:48 2012 +0200
+++ b/hgext/convert/git.py Sun May 13 12:52:24 2012 +0200
@@ -69,7 +69,7 @@
def catfile(self, rev, type):
if rev == hex(nullid):
- raise IOError()
+ raise IOError
data, ret = self.gitread("git cat-file %s %s" % (type, rev))
if ret:
raise util.Abort(_('cannot read %r object at %s') % (type, rev))
@@ -181,8 +181,8 @@
m, f = l[:-1].split("\t")
changes.append(f)
else:
- fh = self.gitopen('git diff-tree --name-only --root -r %s "%s^%s" --'
- % (version, version, i + 1))
+ fh = self.gitopen('git diff-tree --name-only --root -r %s '
+ '"%s^%s" --' % (version, version, i + 1))
changes = [f.rstrip('\n') for f in fh]
if fh.close():
raise util.Abort(_('cannot read changes in %s') % version)
@@ -211,7 +211,7 @@
continue
name = '%s%s' % (reftype, name[prefixlen:])
bookmarks[name] = rev
- except:
+ except Exception:
pass
return bookmarks
--- a/hgext/convert/hg.py Sun May 13 11:19:48 2012 +0200
+++ b/hgext/convert/hg.py Sun May 13 12:52:24 2012 +0200
@@ -95,7 +95,7 @@
self.after()
try:
self.repo = hg.repository(self.ui, branchpath)
- except:
+ except Exception:
self.repo = hg.repository(self.ui, branchpath, create=True)
self.before()
@@ -105,7 +105,7 @@
for b in pbranches:
try:
self.repo.lookup(b[0])
- except:
+ except Exception:
missings.setdefault(b[1], []).append(b[0])
if missings:
@@ -192,7 +192,7 @@
try:
oldlines = sorted(parentctx['.hgtags'].data().splitlines(True))
- except:
+ except Exception:
oldlines = []
newlines = sorted([("%s %s\n" % (tags[tag], tag)) for tag in tags])
@@ -224,7 +224,7 @@
bookmarks.write(self.repo)
def hascommit(self, rev):
- if not rev in self.repo and self.clonebranches:
+ if rev not in self.repo and self.clonebranches:
raise util.Abort(_('revision %s not found in destination '
'repository (lookups with clonebranches=true '
'are not implemented)') % rev)
@@ -241,7 +241,7 @@
# try to provoke an exception if this isn't really a hg
# repo, but some other bogus compatible-looking url
if not self.repo.local():
- raise error.RepoError()
+ raise error.RepoError
except error.RepoError:
ui.traceback()
raise NoRepo(_("%s is not a local Mercurial repository") % path)
@@ -294,7 +294,8 @@
if not parents:
files = sorted(ctx.manifest())
# getcopies() is not needed for roots, but it is a simple way to
- # detect missing revlogs and abort on errors or populate self.ignored
+ # detect missing revlogs and abort on errors or populate
+ # self.ignored
self.getcopies(ctx, parents, files)
return [(f, rev) for f in files if f not in self.ignored], {}
if self._changescache and self._changescache[0] == rev:
--- a/hgext/convert/monotone.py Sun May 13 11:19:48 2012 +0200
+++ b/hgext/convert/monotone.py Sun May 13 12:52:24 2012 +0200
@@ -30,7 +30,7 @@
f = file(path, 'rb')
header = f.read(16)
f.close()
- except:
+ except IOError:
header = ''
if header != 'SQLite format 3\x00':
raise norepo
@@ -283,11 +283,11 @@
def getfile(self, name, rev):
if not self.mtnisfile(name, rev):
- raise IOError() # file was deleted or renamed
+ raise IOError # file was deleted or renamed
try:
data = self.mtnrun("get_file_of", name, r=rev)
- except:
- raise IOError() # file was deleted or renamed
+ except Exception:
+ raise IOError # file was deleted or renamed
self.mtnloadmanifest(rev)
node, attr = self.files.get(name, (None, ""))
return data, attr
@@ -317,7 +317,7 @@
def getchangedfiles(self, rev, i):
# This function is only needed to support --filemap
# ... and we don't support that
- raise NotImplementedError()
+ raise NotImplementedError
def before(self):
# Check if we have a new enough version to use automate stdio
--- a/hgext/convert/subversion.py Sun May 13 11:19:48 2012 +0200
+++ b/hgext/convert/subversion.py Sun May 13 12:52:24 2012 +0200
@@ -85,8 +85,8 @@
self.copyfrom_rev = p.copyfrom_rev
self.action = p.action
-def get_log_child(fp, url, paths, start, end, limit=0, discover_changed_paths=True,
- strict_node_history=False):
+def get_log_child(fp, url, paths, start, end, limit=0,
+ discover_changed_paths=True, strict_node_history=False):
protocol = -1
def receiver(orig_paths, revnum, author, date, message, pool):
if orig_paths is not None:
@@ -139,7 +139,7 @@
' hg executable is in PATH'))
try:
orig_paths, revnum, author, date, message = entry
- except:
+ except (TypeError, ValueError):
if entry is None:
break
raise util.Abort(_("log stream exception '%s'") % entry)
@@ -176,7 +176,7 @@
'know better.\n'))
return True
data = inst.fp.read()
- except:
+ except Exception:
# Could be urllib2.URLError if the URL is invalid or anything else.
return False
return '<m:human-readable errcode="160013">' in data
@@ -276,7 +276,8 @@
except ValueError:
raise util.Abort(_('svn: revision %s is not an integer') % rev)
- self.trunkname = self.ui.config('convert', 'svn.trunk', 'trunk').strip('/')
+ self.trunkname = self.ui.config('convert', 'svn.trunk',
+ 'trunk').strip('/')
self.startrev = self.ui.config('convert', 'svn.startrev', default=0)
try:
self.startrev = int(self.startrev)
@@ -862,13 +863,14 @@
pass
except SubversionException, (inst, num):
if num == svn.core.SVN_ERR_FS_NO_SUCH_REVISION:
- raise util.Abort(_('svn: branch has no revision %s') % to_revnum)
+ raise util.Abort(_('svn: branch has no revision %s')
+ % to_revnum)
raise
def getfile(self, file, rev):
# TODO: ra.get_file transmits the whole file instead of diffs.
if file in self.removed:
- raise IOError()
+ raise IOError
mode = ''
try:
new_module, revnum = revsplit(rev)[1:]
@@ -889,7 +891,7 @@
notfound = (svn.core.SVN_ERR_FS_NOT_FOUND,
svn.core.SVN_ERR_RA_DAV_PATH_NOT_FOUND)
if e.apr_err in notfound: # File not found
- raise IOError()
+ raise IOError
raise
if mode == 'l':
link_prefix = "link "
@@ -949,8 +951,8 @@
if not p.startswith('/'):
p = self.module + '/' + p
relpaths.append(p.strip('/'))
- args = [self.baseurl, relpaths, start, end, limit, discover_changed_paths,
- strict_node_history]
+ args = [self.baseurl, relpaths, start, end, limit,
+ discover_changed_paths, strict_node_history]
arg = encodeargs(args)
hgexe = util.hgexecutable()
cmd = '%s debugsvnlog' % util.shellquote(hgexe)
--- a/hgext/eol.py Sun May 13 11:19:48 2012 +0200
+++ b/hgext/eol.py Sun May 13 12:52:24 2012 +0200
@@ -111,7 +111,8 @@
return s
if ui.configbool('eol', 'only-consistent', True) and inconsistenteol(s):
return s
- if ui.configbool('eol', 'fix-trailing-newline', False) and s and s[-1] != '\n':
+ if (ui.configbool('eol', 'fix-trailing-newline', False)
+ and s and s[-1] != '\n'):
s = s + '\n'
return eolre.sub('\n', s)
@@ -121,7 +122,8 @@
return s
if ui.configbool('eol', 'only-consistent', True) and inconsistenteol(s):
return s
- if ui.configbool('eol', 'fix-trailing-newline', False) and s and s[-1] != '\n':
+ if (ui.configbool('eol', 'fix-trailing-newline', False)
+ and s and s[-1] != '\n'):
s = s + '\n'
return eolre.sub('\r\n', s)
--- a/hgext/extdiff.py Sun May 13 11:19:48 2012 +0200
+++ b/hgext/extdiff.py Sun May 13 12:52:24 2012 +0200
@@ -88,7 +88,7 @@
ctx = repo[node]
for fn in files:
wfn = util.pconvert(fn)
- if not wfn in ctx:
+ if wfn not in ctx:
# File doesn't exist; could be a bogus modify
continue
ui.note(' %s\n' % wfn)
--- a/hgext/fetch.py Sun May 13 11:19:48 2012 +0200
+++ b/hgext/fetch.py Sun May 13 12:52:24 2012 +0200
@@ -5,7 +5,7 @@
# This software may be used and distributed according to the terms of the
# GNU General Public License version 2 or any later version.
-'''pull, update and merge in one command'''
+'''pull, update and merge in one command (DEPRECATED)'''
from mercurial.i18n import _
from mercurial.node import nullid, short
--- a/hgext/gpg.py Sun May 13 11:19:48 2012 +0200
+++ b/hgext/gpg.py Sun May 13 12:52:24 2012 +0200
@@ -43,7 +43,7 @@
try:
if f:
os.unlink(f)
- except:
+ except OSError:
pass
keys = []
key, fingerprint = None, None
--- a/hgext/hgcia.py Sun May 13 11:19:48 2012 +0200
+++ b/hgext/hgcia.py Sun May 13 12:52:24 2012 +0200
@@ -46,17 +46,14 @@
from mercurial import cmdutil, patch, templater, util, mail
import email.Parser
-import xmlrpclib
+import socket, xmlrpclib
from xml.sax import saxutils
socket_timeout = 30 # seconds
-try:
+if util.safehasattr(socket, 'setdefaulttimeout'):
# set a timeout for the socket so you don't have to wait so looooong
# when cia.vc is having problems. requires python >= 2.3:
- import socket
socket.setdefaulttimeout(socket_timeout)
-except:
- pass
HGCIA_VERSION = '0.1'
HGCIA_URL = 'http://hg.kublai.com/mercurial/hgcia'
--- a/hgext/hgk.py Sun May 13 11:19:48 2012 +0200
+++ b/hgext/hgk.py Sun May 13 12:52:24 2012 +0200
@@ -95,7 +95,8 @@
nlprefix = '\n' + prefix
if ctx is None:
ctx = repo[n]
- ui.write("tree %s\n" % short(ctx.changeset()[0])) # use ctx.node() instead ??
+ # use ctx.node() instead ??
+ ui.write("tree %s\n" % short(ctx.changeset()[0]))
for p in ctx.parents():
ui.write("parent %s\n" % p)
@@ -113,7 +114,8 @@
ui.write("branch %s\n\n" % ctx.branch())
if prefix != "":
- ui.write("%s%s\n" % (prefix, description.replace('\n', nlprefix).strip()))
+ ui.write("%s%s\n" % (prefix,
+ description.replace('\n', nlprefix).strip()))
else:
ui.write(description + "\n")
if prefix:
--- a/hgext/highlight/__init__.py Sun May 13 11:19:48 2012 +0200
+++ b/hgext/highlight/__init__.py Sun May 13 12:52:24 2012 +0200
@@ -51,11 +51,13 @@
pg_style = web.config('web', 'pygments_style', 'colorful')
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('')]
+ return ['/* pygments_style = %s */\n\n' % pg_style,
+ fmter.get_style_defs('')]
def extsetup():
# monkeypatch in the new version
- extensions.wrapfunction(webcommands, '_filerevision', filerevision_highlight)
+ extensions.wrapfunction(webcommands, '_filerevision',
+ filerevision_highlight)
extensions.wrapfunction(webcommands, 'annotate', annotate_highlight)
webcommands.highlightcss = generate_css
webcommands.__all__.append('highlightcss')
--- a/hgext/inotify/__init__.py Sun May 13 11:19:48 2012 +0200
+++ b/hgext/inotify/__init__.py Sun May 13 12:52:24 2012 +0200
@@ -46,7 +46,8 @@
files = match.files()
if '.' in files:
files = []
- if self._inotifyon and not ignored and not subrepos and not self._dirty:
+ if (self._inotifyon and not ignored and not subrepos and
+ not self._dirty):
cli = client(ui, repo)
try:
result = cli.statusquery(files, match, False,
--- a/hgext/inotify/server.py Sun May 13 11:19:48 2012 +0200
+++ b/hgext/inotify/server.py Sun May 13 12:52:24 2012 +0200
@@ -355,7 +355,7 @@
except (OSError, socket.error), inst:
try:
os.unlink(self.realsockpath)
- except:
+ except OSError:
pass
os.rmdir(tempdir)
if inst.errno == errno.EEXIST:
@@ -416,7 +416,7 @@
# try to send back our version to the client
# this way, the client too is informed of the mismatch
sock.sendall(chr(common.version))
- except:
+ except socket.error:
pass
return
--- a/hgext/keyword.py Sun May 13 11:19:48 2012 +0200
+++ b/hgext/keyword.py Sun May 13 12:52:24 2012 +0200
@@ -238,7 +238,7 @@
def iskwfile(self, cand, ctx):
'''Returns subset of candidates which are configured for keyword
expansion but are not symbolic links.'''
- return [f for f in cand if self.match(f) and not 'l' in ctx.flags(f)]
+ return [f for f in cand if self.match(f) and 'l' not in ctx.flags(f)]
def overwrite(self, ctx, candidates, lookup, expand, rekw=False):
'''Overwrites selected files expanding/shrinking keywords.'''
@@ -651,7 +651,7 @@
return kwt.match(source)
candidates = [f for f in repo.dirstate.copies() if
- not 'l' in wctx.flags(f) and haskwsource(f)]
+ 'l' not in wctx.flags(f) and haskwsource(f)]
kwt.overwrite(wctx, candidates, False, False)
def kw_dorecord(orig, ui, repo, commitfunc, *pats, **opts):
@@ -680,7 +680,7 @@
# not make sense
if (fctx._filerev is None and
(self._repo._encodefilterpats or
- kwt.match(fctx.path()) and not 'l' in fctx.flags() or
+ kwt.match(fctx.path()) and 'l' not in fctx.flags() or
self.size() - 4 == fctx.size()) or
self.size() == fctx.size()):
return self._filelog.cmp(self._filenode, fctx.data())
--- a/hgext/largefiles/lfcommands.py Sun May 13 11:19:48 2012 +0200
+++ b/hgext/largefiles/lfcommands.py Sun May 13 12:52:24 2012 +0200
@@ -11,7 +11,8 @@
import os
import shutil
-from mercurial import util, match as match_, hg, node, context, error, cmdutil
+from mercurial import util, match as match_, hg, node, context, error, \
+ cmdutil, scmutil
from mercurial.i18n import _
import lfutil
@@ -129,7 +130,7 @@
try:
fctx = ctx.filectx(lfutil.standin(f))
except error.LookupError:
- raise IOError()
+ raise IOError
renamed = fctx.renamed()
if renamed:
renamed = lfutil.splitstandin(renamed[0])
@@ -229,7 +230,7 @@
try:
fctx = ctx.filectx(srcfname)
except error.LookupError:
- raise IOError()
+ raise IOError
renamed = fctx.renamed()
if renamed:
# standin is always a largefile because largefile-ness
@@ -278,7 +279,7 @@
try:
fctx = ctx.filectx(f)
except error.LookupError:
- raise IOError()
+ raise IOError
renamed = fctx.renamed()
if renamed:
renamed = renamed[0]
@@ -400,6 +401,23 @@
return ([], [])
+def downloadlfiles(ui, repo, rev=None):
+ matchfn = scmutil.match(repo[None],
+ [repo.wjoin(lfutil.shortname)], {})
+ def prepare(ctx, fns):
+ pass
+ totalsuccess = 0
+ totalmissing = 0
+ for ctx in cmdutil.walkchangerevs(repo, matchfn, {'rev' : rev},
+ prepare):
+ success, missing = cachelfiles(ui, repo, ctx.node())
+ totalsuccess += len(success)
+ totalmissing += len(missing)
+ ui.status(_("%d additional largefiles cached\n") % totalsuccess)
+ if totalmissing > 0:
+ ui.status(_("%d largefiles failed to download\n") % totalmissing)
+ return totalsuccess, totalmissing
+
def updatelfiles(ui, repo, filelist=None, printmessage=True):
wlock = repo.wlock()
try:
--- a/hgext/largefiles/overrides.py Sun May 13 11:19:48 2012 +0200
+++ b/hgext/largefiles/overrides.py Sun May 13 12:52:24 2012 +0200
@@ -651,6 +651,7 @@
# take some extra care so that the largefiles are correctly updated in the
# working copy
def overridepull(orig, ui, repo, source=None, **opts):
+ revsprepull = len(repo)
if opts.get('rebase', False):
repo._isrebasing = True
try:
@@ -660,7 +661,6 @@
'the update flag\n')
del opts['rebase']
cmdutil.bailifchanged(repo)
- revsprepull = len(repo)
origpostincoming = commands.postincoming
def _dummy(*args, **kwargs):
pass
@@ -695,8 +695,29 @@
(cached, missing) = lfcommands.cachelfiles(ui, repo, head)
numcached += len(cached)
ui.status(_("%d largefiles cached\n") % numcached)
+ if opts.get('all_largefiles'):
+ revspostpull = len(repo)
+ revs = []
+ for rev in xrange(revsprepull + 1, revspostpull):
+ revs.append(repo[rev].rev())
+ lfcommands.downloadlfiles(ui, repo, revs)
return result
+def overrideclone(orig, ui, source, dest=None, **opts):
+ result = hg.clone(ui, opts, source, dest,
+ pull=opts.get('pull'),
+ stream=opts.get('uncompressed'),
+ rev=opts.get('rev'),
+ update=True, # required for successful walkchangerevs
+ branch=opts.get('branch'))
+ if result is None:
+ return True
+ if opts.get('all_largefiles'):
+ sourcerepo, destrepo = result
+ success, missing = lfcommands.downloadlfiles(ui, destrepo, None)
+ return missing != 0
+ return result is None
+
def overriderebase(orig, ui, repo, **opts):
repo._isrebasing = True
try:
@@ -782,6 +803,47 @@
archiver.done()
+def hgsubrepoarchive(orig, repo, ui, archiver, prefix):
+ rev = repo._state[1]
+ ctx = repo._repo[rev]
+
+ lfcommands.cachelfiles(ui, repo._repo, ctx.node())
+
+ def write(name, mode, islink, getdata):
+ if lfutil.isstandin(name):
+ return
+ data = getdata()
+
+ archiver.addfile(prefix + repo._path + '/' + name, mode, islink, data)
+
+ for f in ctx:
+ ff = ctx.flags(f)
+ getdata = ctx[f].data
+ if lfutil.isstandin(f):
+ path = lfutil.findfile(repo._repo, getdata().strip())
+ if path is None:
+ raise util.Abort(
+ _('largefile %s not found in repo store or system cache')
+ % lfutil.splitstandin(f))
+ f = lfutil.splitstandin(f)
+
+ def getdatafn():
+ fd = None
+ try:
+ fd = open(os.path.join(prefix, path), 'rb')
+ return fd.read()
+ finally:
+ if fd:
+ fd.close()
+
+ getdata = getdatafn
+
+ write(f, 'x' in ff and 0755 or 0644, 'l' in ff, getdata)
+
+ for subpath in ctx.substate:
+ sub = ctx.sub(subpath)
+ sub.archive(repo.ui, archiver, prefix)
+
# If a largefile is modified, the change is not reflected in its
# standin until a commit. cmdutil.bailifchanged() raises an exception
# if the repo has uncommitted changes. Wrap it to also check if
--- a/hgext/largefiles/uisetup.py Sun May 13 11:19:48 2012 +0200
+++ b/hgext/largefiles/uisetup.py Sun May 13 12:52:24 2012 +0200
@@ -70,6 +70,15 @@
overrides.overrideupdate)
entry = extensions.wrapcommand(commands.table, 'pull',
overrides.overridepull)
+ pullopt = [('', 'all-largefiles', None,
+ _('download all pulled versions of largefiles'))]
+ entry[1].extend(pullopt)
+ entry = extensions.wrapcommand(commands.table, 'clone',
+ overrides.overrideclone)
+ cloneopt = [('', 'all-largefiles', None,
+ _('download all versions of all largefiles'))]
+
+ entry[1].extend(cloneopt)
entry = extensions.wrapcommand(commands.table, 'cat',
overrides.overridecat)
entry = extensions.wrapfunction(merge, '_checkunknownfile',
@@ -100,6 +109,7 @@
extensions.wrapfunction(hg, 'merge', overrides.hgmerge)
extensions.wrapfunction(archival, 'archive', overrides.overridearchive)
+ extensions.wrapfunction(hgsubrepo, 'archive', overrides.hgsubrepoarchive)
extensions.wrapfunction(cmdutil, 'bailifchanged',
overrides.overridebailifchanged)
--- a/hgext/largefiles/wirestore.py Sun May 13 11:19:48 2012 +0200
+++ b/hgext/largefiles/wirestore.py Sun May 13 12:52:24 2012 +0200
@@ -14,7 +14,7 @@
if not cap:
raise lfutil.storeprotonotcapable([])
storetypes = cap.split(',')
- if not 'serve' in storetypes:
+ if 'serve' not in storetypes:
raise lfutil.storeprotonotcapable(storetypes)
self.remote = remote
super(wirestore, self).__init__(ui, repo, remote.url())
--- a/hgext/mq.py Sun May 13 11:19:48 2012 +0200
+++ b/hgext/mq.py Sun May 13 12:52:24 2012 +0200
@@ -46,6 +46,17 @@
You will by default be managing a patch queue named "patches". You can
create other, independent patch queues with the :hg:`qqueue` command.
+
+If the working directory contains uncommitted files, qpush, qpop and
+qgoto abort immediately. If -f/--force is used, the changes are
+discarded. Setting:
+
+ [mq]
+ check = True
+
+make them behave as if -c/--check 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.
'''
from mercurial.i18n import _
@@ -280,6 +291,9 @@
if phase is not None:
repo.ui.restoreconfig(backup)
+class AbortNoCleanup(error.Abort):
+ pass
+
class queue(object):
def __init__(self, ui, path, patchdir=None):
self.basepath = path
@@ -308,7 +322,7 @@
try:
gitmode = ui.configbool('mq', 'git', None)
if gitmode is None:
- raise error.ConfigError()
+ raise error.ConfigError
self.gitmode = gitmode and 'yes' or 'no'
except error.ConfigError:
self.gitmode = ui.config('mq', 'git', 'auto').lower()
@@ -599,7 +613,7 @@
raise util.Abort(_("repo commit failed"))
try:
ph = patchheader(mergeq.join(patch), self.plainmode)
- except:
+ except Exception:
raise util.Abort(_("unable to read %s") % patch)
diffopts = self.patchopts(diffopts, patch)
@@ -681,7 +695,7 @@
def apply(self, repo, series, list=False, update_status=True,
strict=False, patchdir=None, merge=None, all_files=None,
- tobackup=None):
+ tobackup=None, check=False):
wlock = lock = tr = None
try:
wlock = repo.wlock()
@@ -690,10 +704,14 @@
try:
ret = self._apply(repo, series, list, update_status,
strict, patchdir, merge, all_files=all_files,
- tobackup=tobackup)
+ tobackup=tobackup, check=check)
tr.close()
self.savedirty()
return ret
+ except AbortNoCleanup:
+ tr.close()
+ self.savedirty()
+ return 2, repo.dirstate.p1()
except:
try:
tr.abort()
@@ -708,7 +726,7 @@
def _apply(self, repo, series, list=False, update_status=True,
strict=False, patchdir=None, merge=None, all_files=None,
- tobackup=None):
+ tobackup=None, check=False):
"""returns (error, hash)
error = 1 for unable to read, 2 for patch failed, 3 for patch
@@ -749,6 +767,9 @@
if tobackup:
touched = patchmod.changedfiles(self.ui, repo, pf)
touched = set(touched) & tobackup
+ if touched and check:
+ raise AbortNoCleanup(
+ _("local changes found, refresh first"))
self.backup(repo, touched, copy=True)
tobackup = tobackup - touched
(patcherr, files, fuzz) = self.patch(repo, pf)
@@ -862,7 +883,7 @@
def finish(self, repo, revs):
# Manually trigger phase computation to ensure phasedefaults is
# executed before we remove the patches.
- repo._phaserev
+ repo._phasecache
patches = self._revpatches(repo, sorted(revs))
qfinished = self._cleanup(patches, len(patches))
if qfinished and repo.ui.configbool('mq', 'secret', False):
@@ -959,6 +980,10 @@
else:
raise util.Abort(_('patch "%s" already exists') % name)
+ def checkforcecheck(self, check, force):
+ if force and check:
+ raise util.Abort(_('cannot use both --force and --check'))
+
def new(self, repo, patchfn, *pats, **opts):
"""options:
msg: a string or a no-argument function returning a string
@@ -1059,7 +1084,7 @@
patchpath = self.join(patchfn)
try:
os.unlink(patchpath)
- except:
+ except OSError:
self.ui.warn(_('error unlinking %s\n') % patchpath)
raise
self.removeundo(repo)
@@ -1156,8 +1181,9 @@
return self.series[i + off]
raise util.Abort(_("patch %s not in series") % patch)
- def push(self, repo, patch=None, force=False, list=False,
- mergeq=None, all=False, move=False, exact=False, nobackup=False):
+ def push(self, repo, patch=None, force=False, list=False, mergeq=None,
+ all=False, move=False, exact=False, nobackup=False, check=False):
+ self.checkforcecheck(check, force)
diffopts = self.diffopts()
wlock = repo.wlock()
try:
@@ -1212,14 +1238,19 @@
if start == len(self.series):
self.ui.warn(_('patch series already fully applied\n'))
return 1
- if not force:
+ if not force and not check:
self.checklocalchanges(repo, refresh=self.applied)
if exact:
+ if check:
+ raise util.Abort(
+ _("cannot use --exact and --check together"))
if move:
- raise util.Abort(_("cannot use --exact and --move together"))
+ raise util.Abort(_('cannot use --exact and --move '
+ 'together'))
if self.applied:
- raise util.Abort(_("cannot push --exact with applied patches"))
+ raise util.Abort(_('cannot push --exact with applied '
+ 'patches'))
root = self.series[start]
target = patchheader(self.join(root), self.plainmode).parent
if not target:
@@ -1257,9 +1288,12 @@
end = self.series.index(patch, start) + 1
tobackup = set()
- if not nobackup and force:
+ if (not nobackup and force) or check:
m, a, r, d = self.checklocalchanges(repo, force=True)
- tobackup.update(m + a)
+ if check:
+ tobackup.update(m + a + r + d)
+ else:
+ tobackup.update(m + a)
s = self.series[start:end]
all_files = set()
@@ -1268,7 +1302,7 @@
ret = self.mergepatch(repo, mergeq, s, diffopts)
else:
ret = self.apply(repo, s, list, all_files=all_files,
- tobackup=tobackup)
+ tobackup=tobackup, check=check)
except:
self.ui.warn(_('cleaning up working directory...'))
node = repo.dirstate.p1()
@@ -1299,7 +1333,8 @@
wlock.release()
def pop(self, repo, patch=None, force=False, update=True, all=False,
- nobackup=False):
+ nobackup=False, check=False):
+ self.checkforcecheck(check, force)
wlock = repo.wlock()
try:
if patch:
@@ -1346,9 +1381,12 @@
tobackup = set()
if update:
- m, a, r, d = self.checklocalchanges(repo, force=force)
- if not nobackup and force:
- tobackup.update(m + a)
+ m, a, r, d = self.checklocalchanges(repo, force=force or check)
+ if force:
+ if not nobackup:
+ tobackup.update(m + a)
+ elif check:
+ tobackup.update(m + a + r + d)
self.applieddirty = True
end = len(self.applied)
@@ -1379,8 +1417,10 @@
if d:
raise util.Abort(_("deletions found between repo revs"))
- # backup local changes in --force case
- self.backup(repo, set(a + m + r) & tobackup)
+ tobackup = set(a + m + r) & tobackup
+ if check and tobackup:
+ self.localchangesfound()
+ self.backup(repo, tobackup)
for f in a:
try:
@@ -1959,6 +1999,14 @@
self.removeundo(repo)
return imported
+def fixcheckopts(ui, opts):
+ if (not ui.configbool('mq', 'check') or opts.get('force')
+ or opts.get('exact')):
+ return opts
+ opts = dict(opts)
+ opts['check'] = True
+ return opts
+
@command("qdelete|qremove|qrm",
[('k', 'keep', None, _('keep patch file')),
('r', 'rev', [],
@@ -2140,7 +2188,8 @@
@command("qclone",
[('', 'pull', None, _('use pull protocol to copy metadata')),
- ('U', 'noupdate', None, _('do not update the new working directories')),
+ ('U', 'noupdate', None,
+ _('do not update the new working directories')),
('', 'uncompressed', None,
_('use uncompressed transfer (fast over LAN)')),
('p', 'patches', '',
@@ -2242,7 +2291,8 @@
"""print the entire series file
Returns 0 on success."""
- repo.mq.qseries(repo, missing=opts.get('missing'), summary=opts.get('summary'))
+ repo.mq.qseries(repo, missing=opts.get('missing'),
+ summary=opts.get('summary'))
return 0
@command("qtop", seriesopts, _('hg qtop [-s]'))
@@ -2463,7 +2513,8 @@
if p in patches or p == parent:
ui.warn(_('Skipping already folded patch %s\n') % p)
if q.isapplied(p):
- raise util.Abort(_('qfold cannot fold already applied patch %s') % p)
+ raise util.Abort(_('qfold cannot fold already applied patch %s')
+ % p)
patches.append(p)
for p in patches:
@@ -2497,20 +2548,25 @@
wlock.release()
@command("qgoto",
- [('f', 'force', None, _('overwrite any local changes')),
+ [('c', 'check', None, _('tolerate non-conflicting local changes')),
+ ('f', 'force', None, _('overwrite any local changes')),
('', 'no-backup', None, _('do not save backup copies of files'))],
_('hg qgoto [OPTION]... PATCH'))
def goto(ui, repo, patch, **opts):
'''push or pop patches until named patch is at top of stack
Returns 0 on success.'''
+ opts = fixcheckopts(ui, opts)
q = repo.mq
patch = q.lookup(patch)
nobackup = opts.get('no_backup')
+ check = opts.get('check')
if q.isapplied(patch):
- ret = q.pop(repo, patch, force=opts.get('force'), nobackup=nobackup)
+ ret = q.pop(repo, patch, force=opts.get('force'), nobackup=nobackup,
+ check=check)
else:
- ret = q.push(repo, patch, force=opts.get('force'), nobackup=nobackup)
+ ret = q.push(repo, patch, force=opts.get('force'), nobackup=nobackup,
+ check=check)
q.savedirty()
return ret
@@ -2566,7 +2622,8 @@
args = list(args)
if opts.get('list'):
if args or opts.get('none'):
- raise util.Abort(_('cannot mix -l/--list with options or arguments'))
+ raise util.Abort(_('cannot mix -l/--list with options or '
+ 'arguments'))
for i in xrange(len(q.series)):
status(i)
return
@@ -2630,8 +2687,10 @@
return newpath
@command("^qpush",
- [('f', 'force', None, _('apply on top of local changes')),
- ('e', 'exact', None, _('apply the target patch to its recorded parent')),
+ [('c', 'check', None, _('tolerate non-conflicting local changes')),
+ ('f', 'force', None, _('apply on top of local changes')),
+ ('e', 'exact', None,
+ _('apply the target patch to its recorded parent')),
('l', 'list', None, _('list patch name in commit text')),
('a', 'all', None, _('apply all patches')),
('m', 'merge', None, _('merge from another queue (DEPRECATED)')),
@@ -2644,14 +2703,17 @@
def push(ui, repo, patch=None, **opts):
"""push the next patch onto the stack
- When -f/--force is applied, all local changes in patched files
- will be lost.
+ By default, abort if the working directory contains uncommitted
+ changes. With -c/--check, abort only if the uncommitted files
+ overlap with patched files. With -f/--force, backup and patch over
+ uncommitted changes.
Return 0 on success.
"""
q = repo.mq
mergeq = None
+ opts = fixcheckopts(ui, opts)
if opts.get('merge'):
if opts.get('name'):
newpath = repo.join(opts.get('name'))
@@ -2664,25 +2726,33 @@
ui.warn(_("merging with queue at: %s\n") % mergeq.path)
ret = q.push(repo, patch, force=opts.get('force'), list=opts.get('list'),
mergeq=mergeq, all=opts.get('all'), move=opts.get('move'),
- exact=opts.get('exact'), nobackup=opts.get('no_backup'))
+ exact=opts.get('exact'), nobackup=opts.get('no_backup'),
+ check=opts.get('check'))
return ret
@command("^qpop",
[('a', 'all', None, _('pop all patches')),
('n', 'name', '',
_('queue name to pop (DEPRECATED)'), _('NAME')),
+ ('c', 'check', None, _('tolerate non-conflicting local changes')),
('f', 'force', None, _('forget any local changes to patched files')),
('', 'no-backup', None, _('do not save backup copies of files'))],
_('hg qpop [-a] [-f] [PATCH | INDEX]'))
def pop(ui, repo, patch=None, **opts):
"""pop the current patch off the stack
- By default, pops off the top of the patch stack. If given a patch
- name, keeps popping off patches until the named patch is at the
- top of the stack.
+ Without argument, pops off the top of the patch stack. If given a
+ patch name, keeps popping off patches until the named patch is at
+ the top of the stack.
+
+ By default, abort if the working directory contains uncommitted
+ changes. With -c/--check, abort only if the uncommitted files
+ overlap with patched files. With -f/--force, backup and discard
+ changes made to such files.
Return 0 on success.
"""
+ opts = fixcheckopts(ui, opts)
localupdate = True
if opts.get('name'):
q = queue(ui, repo.path, repo.join(opts.get('name')))
@@ -2691,7 +2761,8 @@
else:
q = repo.mq
ret = q.pop(repo, patch, force=opts.get('force'), update=localupdate,
- all=opts.get('all'), nobackup=opts.get('no_backup'))
+ all=opts.get('all'), nobackup=opts.get('no_backup'),
+ check=opts.get('check'))
q.savedirty()
return ret
@@ -3309,8 +3380,8 @@
tags = result[0]
for patch in mqtags:
if patch[1] in tags:
- self.ui.warn(_('Tag %s overrides mq patch of the same name\n')
- % patch[1])
+ self.ui.warn(_('Tag %s overrides mq patch of the same '
+ 'name\n') % patch[1])
else:
tags[patch[1]] = patch[0]
--- a/hgext/notify.py Sun May 13 11:19:48 2012 +0200
+++ b/hgext/notify.py Sun May 13 12:52:24 2012 +0200
@@ -353,8 +353,8 @@
author = repo[rev].user()
else:
data += ui.popbuffer()
- ui.note(_('notify: suppressing notification for merge %d:%s\n') %
- (rev, repo[rev].hex()[:12]))
+ ui.note(_('notify: suppressing notification for merge %d:%s\n')
+ % (rev, repo[rev].hex()[:12]))
ui.pushbuffer()
if count:
n.diff(ctx, repo['tip'])
--- a/hgext/patchbomb.py Sun May 13 11:19:48 2012 +0200
+++ b/hgext/patchbomb.py Sun May 13 12:52:24 2012 +0200
@@ -109,7 +109,8 @@
msg = email.MIMEMultipart.MIMEMultipart()
if body:
msg.attach(mail.mimeencode(ui, body, _charsets, opts.get('test')))
- p = mail.mimetextpatch('\n'.join(patchlines), 'x-patch', opts.get('test'))
+ p = mail.mimetextpatch('\n'.join(patchlines), 'x-patch',
+ opts.get('test'))
binnode = bin(node)
# if node is mq patch, it will have the patch file's name as a tag
if not patchname:
@@ -119,7 +120,8 @@
patchname = patchtags[0]
elif total > 1:
patchname = cmdutil.makefilename(repo, '%b-%n.patch',
- binnode, seqno=idx, total=total)
+ binnode, seqno=idx,
+ total=total)
else:
patchname = cmdutil.makefilename(repo, '%b.patch', binnode)
disposition = 'inline'
@@ -302,7 +304,7 @@
finally:
try:
os.unlink(tmpfn)
- except:
+ except OSError:
pass
os.rmdir(tmpdir)
--- a/hgext/progress.py Sun May 13 11:19:48 2012 +0200
+++ b/hgext/progress.py Sun May 13 12:52:24 2012 +0200
@@ -237,7 +237,7 @@
# truncate the list of topics assuming all topics within
# this one are also closed
if topic in self.topics:
- self.topics = self.topics[:self.topics.index(topic)]
+ self.topics = self.topics[:self.topics.index(topic)]
else:
if topic not in self.topics:
self.starttimes[topic] = now
--- a/hgext/rebase.py Sun May 13 11:19:48 2012 +0200
+++ b/hgext/rebase.py Sun May 13 12:52:24 2012 +0200
@@ -182,7 +182,7 @@
branch = repo[None].branch()
dest = repo[branch]
else:
- dest = repo[destf]
+ dest = scmutil.revsingle(repo, destf)
if revf:
rebaseset = repo.revs('%lr', revf)
@@ -201,7 +201,7 @@
root = None
if not rebaseset:
- repo.ui.debug('base is ancestor of destination')
+ repo.ui.debug('base is ancestor of destination\n')
result = None
elif not keepf and list(repo.revs('first(children(%ld) - %ld)',
rebaseset, rebaseset)):
@@ -214,7 +214,7 @@
% repo[root],
hint=_('see hg help phases for details'))
else:
- result = buildstate(repo, dest, rebaseset, detachf)
+ result = buildstate(repo, dest, rebaseset, detachf, collapsef)
if not result:
# Empty state built, nothing to rebase
@@ -265,7 +265,7 @@
else:
try:
ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
- stats = rebasenode(repo, rev, p1, state)
+ stats = rebasenode(repo, rev, p1, state, collapsef)
if stats and stats[3] > 0:
raise util.Abort(_('unresolved conflicts (see hg '
'resolve, then hg rebase --continue)'))
@@ -383,7 +383,7 @@
repo.dirstate.invalidate()
raise
-def rebasenode(repo, rev, p1, state):
+def rebasenode(repo, rev, p1, state, collapse):
'Rebase a single revision'
# Merge phase
# Update to target and merge it with local
@@ -397,7 +397,9 @@
base = None
if repo[rev].rev() != repo[min(state)].rev():
base = repo[rev].p1().node()
- return merge.update(repo, rev, True, True, False, base)
+ # When collapsing in-place, the parent is the common ancestor, we
+ # have to allow merging with it.
+ return merge.update(repo, rev, True, True, False, base, collapse)
def defineparents(repo, rev, target, state, targetancestors):
'Return the new parent relationship of the revision that will be rebased'
@@ -589,7 +591,7 @@
repo.ui.warn(_('rebase aborted\n'))
return 0
-def buildstate(repo, dest, rebaseset, detach):
+def buildstate(repo, dest, rebaseset, detach, collapse):
'''Define which revisions are going to be rebased and where
repo: repo
@@ -617,9 +619,9 @@
raise util.Abort(_('source is ancestor of destination'))
if commonbase == dest:
samebranch = root.branch() == dest.branch()
- if samebranch and root in dest.children():
- repo.ui.debug('source is a child of destination')
- return None
+ if not collapse and samebranch and root in dest.children():
+ repo.ui.debug('source is a child of destination\n')
+ return None
# rebase on ancestor, force detach
detach = True
if detach:
--- a/hgext/record.py Sun May 13 11:19:48 2012 +0200
+++ b/hgext/record.py Sun May 13 12:52:24 2012 +0200
@@ -516,10 +516,11 @@
'(use "hg commit" instead)'))
changes = repo.status(match=match)[:3]
- diffopts = mdiff.diffopts(git=True, nodates=True,
- ignorews=opts.get('ignore_all_space'),
- ignorewsamount=opts.get('ignore_space_change'),
- ignoreblanklines=opts.get('ignore_blank_lines'))
+ diffopts = mdiff.diffopts(
+ git=True, nodates=True,
+ ignorews=opts.get('ignore_all_space'),
+ ignorewsamount=opts.get('ignore_space_change'),
+ ignoreblanklines=opts.get('ignore_blank_lines'))
chunks = patch.diff(repo, changes=changes, opts=diffopts)
fp = cStringIO.StringIO()
fp.write(''.join(chunks))
--- a/hgext/relink.py Sun May 13 11:19:48 2012 +0200
+++ b/hgext/relink.py Sun May 13 12:52:24 2012 +0200
@@ -79,7 +79,7 @@
dirnames.sort()
relpath = dirpath[len(src) + seplen:]
for filename in sorted(filenames):
- if not filename[-2:] in ('.d', '.i'):
+ if filename[-2:] not in ('.d', '.i'):
continue
st = os.stat(os.path.join(dirpath, filename))
if not stat.S_ISREG(st.st_mode):
--- a/hgext/transplant.py Sun May 13 11:19:48 2012 +0200
+++ b/hgext/transplant.py Sun May 13 12:52:24 2012 +0200
@@ -124,7 +124,7 @@
continue
parents = source.changelog.parents(node)
- if not opts.get('filter'):
+ if not (opts.get('filter') or opts.get('log')):
# If the changeset parent is the same as the
# wdir's parent, just pull it.
if parents[0] == p1:
--- a/hgext/zeroconf/__init__.py Sun May 13 11:19:48 2012 +0200
+++ b/hgext/zeroconf/__init__.py Sun May 13 12:52:24 2012 +0200
@@ -44,7 +44,7 @@
s.connect(('1.0.0.1', 0))
ip = s.getsockname()[0]
return ip
- except:
+ except socket.error:
pass
# Generic method, sometimes gives useless results
@@ -61,7 +61,7 @@
s.connect(('1.0.0.1', 1))
ip = s.getsockname()[0]
return ip
- except:
+ except socket.error:
pass
return dumbip
@@ -119,7 +119,8 @@
name = os.path.basename(repo)
path = (prefix + repo).strip('/')
desc = u.config('web', 'description', name)
- publish(name, desc, path, util.getport(u.config("web", "port", 8000)))
+ publish(name, desc, path,
+ util.getport(u.config("web", "port", 8000)))
# listen
--- a/mercurial/bookmarks.py Sun May 13 11:19:48 2012 +0200
+++ b/mercurial/bookmarks.py Sun May 13 12:52:24 2012 +0200
@@ -221,6 +221,11 @@
repo._bookmarks[n] = cr.node()
changed = True
ui.warn(_("divergent bookmark %s stored as %s\n") % (k, n))
+ elif rb[k] in repo:
+ # add remote bookmarks for changes we already have
+ repo._bookmarks[k] = repo[rb[k]].node()
+ changed = True
+ ui.status(_("adding remote bookmark %s\n") % k)
if changed:
write(repo)
--- a/mercurial/bundlerepo.py Sun May 13 11:19:48 2012 +0200
+++ b/mercurial/bundlerepo.py Sun May 13 12:52:24 2012 +0200
@@ -54,7 +54,7 @@
continue
for p in (p1, p2):
- if not p in self.nodemap:
+ if p not in self.nodemap:
raise error.LookupError(p, self.indexfile,
_("unknown parent"))
# start, size, full unc. size, base (unused), link, p1, p2, node
@@ -323,13 +323,16 @@
Returns a tuple (local, csets, cleanupfn):
- "local" is a local repo from which to obtain the actual incoming changesets; it
- is a bundlerepo for the obtained bundle when the original "other" is remote.
+ "local" is a local repo from which to obtain the actual incoming
+ changesets; it is a bundlerepo for the obtained bundle when the
+ original "other" is remote.
"csets" lists the incoming changeset node ids.
- "cleanupfn" must be called without arguments when you're done processing the
- changes; it closes both the original "other" and the one returned here.
+ "cleanupfn" must be called without arguments when you're done processing
+ the changes; it closes both the original "other" and the one returned
+ here.
'''
- tmp = discovery.findcommonincoming(repo, other, heads=onlyheads, force=force)
+ tmp = discovery.findcommonincoming(repo, other, heads=onlyheads,
+ force=force)
common, incoming, rheads = tmp
if not incoming:
try:
--- a/mercurial/cmdutil.py Sun May 13 11:19:48 2012 +0200
+++ b/mercurial/cmdutil.py Sun May 13 12:52:24 2012 +0200
@@ -1363,7 +1363,7 @@
copied=copied.get(path))
return mctx
except KeyError:
- raise IOError()
+ raise IOError
else:
ui.note(_('copying changeset %s to %s\n') % (old, base))
@@ -1372,7 +1372,7 @@
try:
return old.filectx(path)
except KeyError:
- raise IOError()
+ raise IOError
# See if we got a message from -m or -l, if not, open the editor
# with the message of the changeset to amend
@@ -1489,7 +1489,7 @@
def badfn(path, msg):
if path in names:
return
- if path in repo[node].substate:
+ if path in ctx.substate:
return
path_ = path + '/'
for f in names:
@@ -1497,14 +1497,14 @@
return
ui.warn("%s: %s\n" % (m.rel(path), msg))
- m = scmutil.match(repo[node], pats, opts)
+ m = scmutil.match(ctx, pats, opts)
m.bad = badfn
- for abs in repo[node].walk(m):
+ for abs in ctx.walk(m):
if abs not in names:
names[abs] = m.rel(abs), m.exact(abs)
# get the list of subrepos that must be reverted
- targetsubs = [s for s in repo[node].substate if m(s)]
+ targetsubs = [s for s in ctx.substate if m(s)]
m = scmutil.matchfiles(repo, names)
changes = repo.status(match=m)[:4]
modified, added, removed, deleted = map(set, changes)
--- a/mercurial/commands.py Sun May 13 11:19:48 2012 +0200
+++ b/mercurial/commands.py Sun May 13 12:52:24 2012 +0200
@@ -520,10 +520,12 @@
revision as good or bad without checking it out first.
If you supply a command, it will be used for automatic bisection.
- Its exit status will be used to mark revisions as good or bad:
- status 0 means good, 125 means to skip the revision, 127
- (command not found) will abort the bisection, and any other
- non-zero exit status means the revision is bad.
+ The environment variable HG_NODE will contain the ID of the
+ changeset being tested. The exit status of the command will be
+ used to mark revisions as good or bad: status 0 means good, 125
+ means to skip the revision, 127 (command not found) will abort the
+ bisection, and any other non-zero exit status means the revision
+ is bad.
.. container:: verbose
@@ -563,6 +565,11 @@
hg log -r "bisect(pruned)"
+ - see the changeset currently being bisected (especially useful
+ if running with -U/--noupdate)::
+
+ hg log -r "bisect(current)"
+
- see all changesets that took part in the current bisection::
hg log -r "bisect(range)"
@@ -647,10 +654,22 @@
if command:
changesets = 1
try:
+ node = state['current'][0]
+ except LookupError:
+ if noupdate:
+ raise util.Abort(_('current bisect revision is unknown - '
+ 'start a new bisect to fix'))
+ node, p2 = repo.dirstate.parents()
+ if p2 != nullid:
+ raise util.Abort(_('current bisect revision is a merge'))
+ try:
while changesets:
# update state
+ state['current'] = [node]
hbisect.save_state(repo, state)
- status = util.system(command, out=ui.fout)
+ status = util.system(command,
+ environ={'HG_NODE': hex(node)},
+ out=ui.fout)
if status == 125:
transition = "skip"
elif status == 0:
@@ -662,7 +681,7 @@
raise util.Abort(_("%s killed") % command)
else:
transition = "bad"
- ctx = scmutil.revsingle(repo, rev)
+ ctx = scmutil.revsingle(repo, rev, node)
rev = None # clear for future iterations
state[transition].append(ctx.node())
ui.status(_('Changeset %d:%s: %s\n') % (ctx, ctx, transition))
@@ -670,9 +689,12 @@
# bisect
nodes, changesets, good = hbisect.bisect(repo.changelog, state)
# update to next check
- cmdutil.bailifchanged(repo)
- hg.clean(repo, nodes[0], show_stats=False)
+ node = nodes[0]
+ if not noupdate:
+ cmdutil.bailifchanged(repo)
+ hg.clean(repo, node, show_stats=False)
finally:
+ state['current'] = [node]
hbisect.save_state(repo, state)
print_result(nodes, good)
return
@@ -704,6 +726,8 @@
if extendnode is not None:
ui.write(_("Extending search to changeset %d:%s\n"
% (extendnode.rev(), extendnode)))
+ state['current'] = [extendnode.node()]
+ hbisect.save_state(repo, state)
if noupdate:
return
cmdutil.bailifchanged(repo)
@@ -723,6 +747,8 @@
ui.write(_("Testing changeset %d:%s "
"(%d changesets remaining, ~%d tests)\n")
% (rev, short(node), changesets, tests))
+ state['current'] = [node]
+ hbisect.save_state(repo, state)
if not noupdate:
cmdutil.bailifchanged(repo)
return hg.clean(repo, node)
@@ -921,26 +947,26 @@
for isactive, node, tag in branches:
if (not active) or isactive:
+ hn = repo.lookup(node)
+ if isactive:
+ label = 'branches.active'
+ notice = ''
+ elif hn not in repo.branchheads(tag, closed=False):
+ if not closed:
+ continue
+ label = 'branches.closed'
+ notice = _(' (closed)')
+ else:
+ label = 'branches.inactive'
+ notice = _(' (inactive)')
+ if tag == repo.dirstate.branch():
+ label = 'branches.current'
+ rev = str(node).rjust(31 - encoding.colwidth(tag))
+ rev = ui.label('%s:%s' % (rev, hexfunc(hn)), 'log.changeset')
+ tag = ui.label(tag, label)
if ui.quiet:
ui.write("%s\n" % tag)
else:
- hn = repo.lookup(node)
- if isactive:
- label = 'branches.active'
- notice = ''
- elif hn not in repo.branchheads(tag, closed=False):
- if not closed:
- continue
- label = 'branches.closed'
- notice = _(' (closed)')
- else:
- label = 'branches.inactive'
- notice = _(' (inactive)')
- if tag == repo.dirstate.branch():
- label = 'branches.current'
- rev = str(node).rjust(31 - encoding.colwidth(tag))
- rev = ui.label('%s:%s' % (rev, hexfunc(hn)), 'log.changeset')
- tag = ui.label(tag, label)
ui.write("%s %s%s\n" % (tag, rev, notice))
@command('bundle',
@@ -1661,7 +1687,8 @@
revs = set((int(r) for r in revs))
def events():
for r in rlog:
- yield 'n', (r, list(set(p for p in rlog.parentrevs(r) if p != -1)))
+ yield 'n', (r, list(set(p for p in rlog.parentrevs(r)
+ if p != -1)))
if r in revs:
yield 'l', (r, "r%i" % r)
elif repo:
@@ -1680,7 +1707,8 @@
if newb != b:
yield 'a', newb
b = newb
- yield 'n', (r, list(set(p for p in cl.parentrevs(r) if p != -1)))
+ yield 'n', (r, list(set(p for p in cl.parentrevs(r)
+ if p != -1)))
if tags:
ls = labels.get(r)
if ls:
@@ -1738,7 +1766,8 @@
_('[-l REV] [-r REV] [-b BRANCH]... [OTHER]'))
def debugdiscovery(ui, repo, remoteurl="default", **opts):
"""runs the changeset discovery protocol in isolation"""
- remoteurl, branches = hg.parseurl(ui.expandpath(remoteurl), opts.get('branch'))
+ remoteurl, branches = hg.parseurl(ui.expandpath(remoteurl),
+ opts.get('branch'))
remote = hg.peer(repo, opts, remoteurl)
ui.status(_('comparing with %s\n') % util.hidepassword(remoteurl))
@@ -1748,7 +1777,8 @@
def doit(localheads, remoteheads):
if opts.get('old'):
if localheads:
- raise util.Abort('cannot use localheads with old style discovery')
+ raise util.Abort('cannot use localheads with old style '
+ 'discovery')
common, _in, hds = treediscovery.findcommonincoming(repo, remote,
force=True)
common = set(common)
@@ -1875,7 +1905,8 @@
" nodeid p1 p2\n")
elif format == 1:
ui.write(" rev flag offset length"
- " size " + basehdr + " link p1 p2 nodeid\n")
+ " size " + basehdr + " link p1 p2"
+ " nodeid\n")
for i in r:
node = r.node(i)
@@ -1886,7 +1917,7 @@
if format == 0:
try:
pp = r.parents(node)
- except:
+ except Exception:
pp = [nullid, nullid]
ui.write("% 6d % 9d % 7d % 6d % 7d %s %s %s\n" % (
i, r.start(i), r.length(i), base, r.linkrev(i),
@@ -2000,8 +2031,8 @@
def debugknown(ui, repopath, *ids, **opts):
"""test whether node ids are known to a repo
- Every ID must be a full-length hex node id string. Returns a list of 0s and 1s
- indicating unknown/known.
+ Every ID must be a full-length hex node id string. Returns a list of 0s
+ and 1s indicating unknown/known.
"""
repo = hg.peer(ui, opts, repopath)
if not repo.capable('known'):
@@ -2233,13 +2264,17 @@
fmt2 = pcfmtstr(numdeltas, 4)
ui.write('deltas against prev : ' + fmt % pcfmt(numprev, numdeltas))
if numprev > 0:
- ui.write(' where prev = p1 : ' + fmt2 % pcfmt(nump1prev, numprev))
- ui.write(' where prev = p2 : ' + fmt2 % pcfmt(nump2prev, numprev))
- ui.write(' other : ' + fmt2 % pcfmt(numoprev, numprev))
+ ui.write(' where prev = p1 : ' + fmt2 % pcfmt(nump1prev,
+ numprev))
+ ui.write(' where prev = p2 : ' + fmt2 % pcfmt(nump2prev,
+ numprev))
+ ui.write(' other : ' + fmt2 % pcfmt(numoprev,
+ numprev))
if gdelta:
ui.write('deltas against p1 : ' + fmt % pcfmt(nump1, numdeltas))
ui.write('deltas against p2 : ' + fmt % pcfmt(nump2, numdeltas))
- ui.write('deltas against other : ' + fmt % pcfmt(numother, numdeltas))
+ ui.write('deltas against other : ' + fmt % pcfmt(numother,
+ numdeltas))
@command('debugrevspec', [], ('REVSPEC'))
def debugrevspec(ui, repo, expr):
@@ -2555,6 +2590,7 @@
'graft',
[('c', 'continue', False, _('resume interrupted graft')),
('e', 'edit', False, _('invoke editor on commit messages')),
+ ('', 'log', None, _('append graft info to log message')),
('D', 'currentdate', False,
_('record the current date as commit date')),
('U', 'currentuser', False,
@@ -2573,6 +2609,11 @@
Changesets that are ancestors of the current revision, that have
already been grafted, or that are merges will be skipped.
+ If --log is specified, log messages will have a comment appended
+ of the form::
+
+ (grafted from CHANGESETHASH)
+
If a graft merge results in conflicts, the graft process is
interrupted so that the current merge can be manually resolved.
Once all conflicts are addressed, the graft process can be
@@ -2722,8 +2763,13 @@
date = ctx.date()
if opts.get('date'):
date = opts['date']
- repo.commit(text=ctx.description(), user=user,
+ message = ctx.description()
+ if opts.get('log'):
+ message += '\n(grafted from %s)' % ctx.hex()
+ node = repo.commit(text=message, user=user,
date=date, extra=extra, editor=editor)
+ if node is None:
+ ui.status(_('graft for revision %s is empty\n') % ctx.rev())
finally:
wlock.release()
@@ -4347,10 +4393,10 @@
lock = repo.lock()
try:
# set phase
- nodes = [ctx.node() for ctx in repo.set('%ld', revs)]
- if not nodes:
- raise util.Abort(_('empty revision set'))
- olddata = repo._phaserev[:]
+ if not revs:
+ raise util.Abort(_('empty revision set'))
+ nodes = [repo[r].node() for r in revs]
+ olddata = repo._phasecache.getphaserevs(repo)[:]
phases.advanceboundary(repo, targetphase, nodes)
if opts['force']:
phases.retractboundary(repo, targetphase, nodes)
@@ -4358,7 +4404,7 @@
lock.release()
if olddata is not None:
changes = 0
- newdata = repo._phaserev
+ newdata = repo._phasecache.getphaserevs(repo)
changes = sum(o != newdata[i] for i, o in enumerate(olddata))
rejected = [n for n in nodes
if newdata[repo[n].rev()] < targetphase]
@@ -4396,7 +4442,8 @@
if currentbranchheads == modheads:
ui.status(_("(run 'hg heads' to see heads, 'hg merge' to merge)\n"))
elif currentbranchheads > 1:
- ui.status(_("(run 'hg heads .' to see heads, 'hg merge' to merge)\n"))
+ ui.status(_("(run 'hg heads .' to see heads, 'hg merge' to "
+ "merge)\n"))
else:
ui.status(_("(run 'hg heads' to see heads)\n"))
else:
@@ -5368,7 +5415,8 @@
t = []
source, branches = hg.parseurl(ui.expandpath('default'))
other = hg.peer(repo, {}, source)
- revs, checkout = hg.addbranchrevs(repo, other, branches, opts.get('rev'))
+ revs, checkout = hg.addbranchrevs(repo, other, branches,
+ opts.get('rev'))
ui.debug('comparing with %s\n' % util.hidepassword(source))
repo.ui.pushbuffer()
commoninc = discovery.findcommonincoming(repo, other)
@@ -5586,9 +5634,9 @@
f = url.open(ui, fname)
gen = changegroup.readbundle(f, fname)
modheads = repo.addchangegroup(gen, 'unbundle', 'bundle:' + fname)
- bookmarks.updatecurrentbookmark(repo, wc.node(), wc.branch())
finally:
lock.release()
+ bookmarks.updatecurrentbookmark(repo, wc.node(), wc.branch())
return postincoming(ui, repo, modheads, opts.get('update'), None)
@command('^update|up|checkout|co',
--- a/mercurial/commandserver.py Sun May 13 11:19:48 2012 +0200
+++ b/mercurial/commandserver.py Sun May 13 12:52:24 2012 +0200
@@ -142,8 +142,8 @@
else:
logfile = open(logpath, 'a')
- # the ui here is really the repo ui so take its baseui so we don't end up
- # with its local configuration
+ # the ui here is really the repo ui so take its baseui so we don't end
+ # up with its local configuration
self.ui = repo.baseui
self.repo = repo
self.repoui = repo.ui
@@ -166,7 +166,7 @@
# is the other end closed?
if not data:
- raise EOFError()
+ raise EOFError
return data
--- a/mercurial/context.py Sun May 13 11:19:48 2012 +0200
+++ b/mercurial/context.py Sun May 13 12:52:24 2012 +0200
@@ -8,6 +8,7 @@
from node import nullid, nullrev, short, hex, bin
from i18n import _
import ancestor, mdiff, error, util, scmutil, subrepo, patch, encoding, phases
+import copies
import match as matchmod
import os, errno, stat
@@ -190,12 +191,7 @@
def bookmarks(self):
return self._repo.nodebookmarks(self._node)
def phase(self):
- if self._rev == -1:
- return phases.public
- if self._rev >= len(self._repo._phaserev):
- # outdated cache
- del self._repo._phaserev
- return self._repo._phaserev[self._rev]
+ return self._repo._phasecache.phase(self._repo, self._rev)
def phasestr(self):
return phases.phasenames[self.phase()]
def mutable(self):
@@ -237,7 +233,8 @@
_('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)
+ return (self._manifestdelta[path],
+ self._manifestdelta.flags(path))
node, flag = self._repo.manifest.find(self._changeset[0], path)
if not node:
raise error.LookupError(self._node, path,
@@ -634,27 +631,27 @@
return zip(hist[base][0], hist[base][1].splitlines(True))
- def ancestor(self, fc2, actx=None):
+ def ancestor(self, fc2, actx):
"""
find the common ancestor file context, if any, of self, and fc2
- If actx is given, it must be the changectx of the common ancestor
+ actx must be the changectx of the common ancestor
of self's and fc2's respective changesets.
"""
- if actx is None:
- actx = self.changectx().ancestor(fc2.changectx())
-
- # the trivial case: changesets are unrelated, files must be too
- if not actx:
- return None
-
# the easy case: no (relevant) renames
if fc2.path() == self.path() and self.path() in actx:
return actx[self.path()]
- acache = {}
+
+ # the next easiest cases: unambiguous predecessor (name trumps
+ # history)
+ if self.path() in actx and fc2.path() not in actx:
+ return actx[self.path()]
+ if fc2.path() in actx and self.path() not in actx:
+ return actx[fc2.path()]
# prime the ancestor cache for the working directory
+ acache = {}
for c in (self, fc2):
if c._filerev is None:
pl = [(n.path(), n.filenode()) for n in c.parents()]
@@ -695,6 +692,14 @@
c = visit.pop(max(visit))
yield c
+ def copies(self, c2):
+ if not util.safehasattr(self, "_copycache"):
+ self._copycache = {}
+ sc2 = str(c2)
+ if sc2 not in self._copycache:
+ 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.
--- a/mercurial/dagparser.py Sun May 13 11:19:48 2012 +0200
+++ b/mercurial/dagparser.py Sun May 13 12:52:24 2012 +0200
@@ -268,7 +268,8 @@
s += c
i += 1
c = nextch()
- raise util.Abort(_("invalid character in dag description: %s...") % s)
+ raise util.Abort(_('invalid character in dag description: '
+ '%s...') % s)
def dagtextlines(events,
addspaces=True,
@@ -436,7 +437,9 @@
>>> dagtext([('n', (0, [-1])), ('a', 'ann'), ('n', (1, [0]))])
'+1 @ann +1'
- >>> dagtext([('n', (0, [-1])), ('a', 'my annotation'), ('n', (1, [0]))])
+ >>> dagtext([('n', (0, [-1])),
+ ... ('a', 'my annotation'),
+ ... ('n', (1, [0]))])
'+1 @"my annotation" +1'
Commands:
@@ -447,7 +450,9 @@
>>> dagtext([('n', (0, [-1])), ('c', 'my command'), ('n', (1, [0]))])
'+1 !"my command" +1'
- >>> dagtext([('n', (0, [-1])), ('C', 'my command line'), ('n', (1, [0]))])
+ >>> dagtext([('n', (0, [-1])),
+ ... ('C', 'my command line'),
+ ... ('n', (1, [0]))])
'+1 !!my command line\\n+1'
Comments:
--- a/mercurial/dagutil.py Sun May 13 11:19:48 2012 +0200
+++ b/mercurial/dagutil.py Sun May 13 12:52:24 2012 +0200
@@ -26,25 +26,25 @@
def nodeset(self):
'''set of all node idxs'''
- raise NotImplementedError()
+ raise NotImplementedError
def heads(self):
'''list of head ixs'''
- raise NotImplementedError()
+ raise NotImplementedError
def parents(self, ix):
'''list of parents ixs of ix'''
- raise NotImplementedError()
+ raise NotImplementedError
def inverse(self):
'''inverse DAG, where parents becomes children, etc.'''
- raise NotImplementedError()
+ raise NotImplementedError
def ancestorset(self, starts, stops=None):
'''
set of all ancestors of starts (incl), but stop walk at stops (excl)
'''
- raise NotImplementedError()
+ raise NotImplementedError
def descendantset(self, starts, stops=None):
'''
@@ -59,7 +59,7 @@
By "connected list" we mean that if an ancestor and a descendant are in
the list, then so is at least one path connecting them.
'''
- raise NotImplementedError()
+ raise NotImplementedError
def externalize(self, ix):
'''return a list of (or set if given a set) of node ids'''
--- a/mercurial/diffhelpers.c Sun May 13 11:19:48 2012 +0200
+++ b/mercurial/diffhelpers.c Sun May 13 12:52:24 2012 +0200
@@ -20,14 +20,14 @@
/* fixup the last lines of a and b when the patch has no newline at eof */
static void _fix_newline(PyObject *hunk, PyObject *a, PyObject *b)
{
- int hunksz = PyList_Size(hunk);
+ Py_ssize_t hunksz = PyList_Size(hunk);
PyObject *s = PyList_GET_ITEM(hunk, hunksz-1);
char *l = PyBytes_AsString(s);
- int alen = PyList_Size(a);
- int blen = PyList_Size(b);
+ Py_ssize_t alen = PyList_Size(a);
+ Py_ssize_t blen = PyList_Size(b);
char c = l[0];
PyObject *hline;
- int sz = PyBytes_GET_SIZE(s);
+ Py_ssize_t sz = PyBytes_GET_SIZE(s);
if (sz > 1 && l[sz-2] == '\r')
/* tolerate CRLF in last line */
@@ -57,6 +57,12 @@
return Py_BuildValue("l", 0);
}
+#if (PY_VERSION_HEX < 0x02050000)
+static const char *addlines_format = "OOiiOO";
+#else
+static const char *addlines_format = "OOnnOO";
+#endif
+
/*
* read lines from fp into the hunk. The hunk is parsed into two arrays
* a and b. a gets the old state of the text, b gets the new state
@@ -68,13 +74,14 @@
{
PyObject *fp, *hunk, *a, *b, *x;
- int i;
- int lena, lenb;
- int num;
- int todoa, todob;
+ Py_ssize_t i;
+ Py_ssize_t lena, lenb;
+ Py_ssize_t num;
+ Py_ssize_t todoa, todob;
char *s, c;
PyObject *l;
- if (!PyArg_ParseTuple(args, "OOiiOO", &fp, &hunk, &lena, &lenb, &a, &b))
+ if (!PyArg_ParseTuple(args, addlines_format,
+ &fp, &hunk, &lena, &lenb, &a, &b))
return NULL;
while (1) {
@@ -127,8 +134,8 @@
PyObject *a, *b;
long bstart;
- int alen, blen;
- int i;
+ Py_ssize_t alen, blen;
+ Py_ssize_t i;
char *sa, *sb;
if (!PyArg_ParseTuple(args, "OOl", &a, &b, &bstart))
--- a/mercurial/dirstate.py Sun May 13 11:19:48 2012 +0200
+++ b/mercurial/dirstate.py Sun May 13 12:52:24 2012 +0200
@@ -695,7 +695,8 @@
if not skipstep3 and not exact:
visit = sorted([f for f in dmap if f not in results and matchfn(f)])
for nf, st in zip(visit, util.statfiles([join(i) for i in visit])):
- if not st is None and not getkind(st.st_mode) in (regkind, lnkkind):
+ if (not st is None and
+ getkind(st.st_mode) not in (regkind, lnkkind)):
st = None
results[nf] = st
for s in subrepos:
--- a/mercurial/discovery.py Sun May 13 11:19:48 2012 +0200
+++ b/mercurial/discovery.py Sun May 13 12:52:24 2012 +0200
@@ -86,13 +86,14 @@
self._computecommonmissing()
return self._missing
-def findcommonoutgoing(repo, other, onlyheads=None, force=False, commoninc=None):
+def findcommonoutgoing(repo, other, onlyheads=None, force=False,
+ commoninc=None):
'''Return an outgoing instance to identify the nodes present in repo but
not in other.
- If onlyheads is given, only nodes ancestral to nodes in onlyheads (inclusive)
- are included. If you already know the local repo's heads, passing them in
- onlyheads is faster than letting them be recomputed here.
+ If onlyheads is given, only nodes ancestral to nodes in onlyheads
+ (inclusive) are included. If you already know the local repo's heads,
+ passing them in onlyheads is faster than letting them be recomputed here.
If commoninc is given, it must the the result of a prior call to
findcommonincoming(repo, other, force) to avoid recomputing it here.'''
@@ -105,7 +106,7 @@
og.commonheads, _any, _hds = commoninc
# compute outgoing
- if not repo._phaseroots[phases.secret]:
+ if not repo._phasecache.phaseroots[phases.secret]:
og.missingheads = onlyheads or repo.heads()
elif onlyheads is None:
# use visible heads as it should be cached
--- a/mercurial/dispatch.py Sun May 13 11:19:48 2012 +0200
+++ b/mercurial/dispatch.py Sun May 13 12:52:24 2012 +0200
@@ -12,7 +12,8 @@
import ui as uimod
class request(object):
- def __init__(self, args, ui=None, repo=None, fin=None, fout=None, ferr=None):
+ def __init__(self, args, ui=None, repo=None, fin=None, fout=None,
+ ferr=None):
self.args = args
self.ui = ui
self.repo = repo
@@ -532,7 +533,8 @@
if cmd and util.safehasattr(fn, 'shell'):
d = lambda: fn(ui, *args[1:])
- return lambda: runcommand(lui, None, cmd, args[:1], ui, options, d, [], {})
+ return lambda: runcommand(lui, None, cmd, args[:1], ui, options, d,
+ [], {})
restorecommands()
@@ -680,7 +682,8 @@
return _dispatch(req)
if not path:
raise error.RepoError(_("no repository found in '%s'"
- " (.hg not found)") % os.getcwd())
+ " (.hg not found)")
+ % os.getcwd())
raise
if repo:
ui = repo.ui
@@ -703,7 +706,7 @@
field = ui.config('profiling', 'sort', default='inlinetime')
climit = ui.configint('profiling', 'nested', default=5)
- if not format in ['text', 'kcachegrind']:
+ if format not in ['text', 'kcachegrind']:
ui.warn(_("unrecognized profiling format '%s'"
" - Ignored\n") % format)
format = 'text'
--- a/mercurial/extensions.py Sun May 13 11:19:48 2012 +0200
+++ b/mercurial/extensions.py Sun May 13 12:52:24 2012 +0200
@@ -301,7 +301,7 @@
def disabledcmd(ui, cmd, strict=False):
'''import disabled extensions until cmd is found.
- returns (cmdname, extname, doc)'''
+ returns (cmdname, extname, module)'''
paths = _disabledpaths(strip_init=True)
if not paths:
@@ -329,18 +329,19 @@
cmd = aliases[0]
return (cmd, name, mod)
+ ext = None
# first, search for an extension with the same name as the command
path = paths.pop(cmd, None)
if path:
ext = findcmd(cmd, cmd, path)
- if ext:
- return ext
-
- # otherwise, interrogate each extension until there's a match
- for name, path in paths.iteritems():
- ext = findcmd(cmd, name, path)
- if ext:
- return ext
+ if not ext:
+ # otherwise, interrogate each extension until there's a match
+ for name, path in paths.iteritems():
+ ext = findcmd(cmd, name, path)
+ if ext:
+ break
+ if ext and 'DEPRECATED' not in ext.__doc__:
+ return ext
raise error.UnknownCommand(cmd)
--- a/mercurial/hbisect.py Sun May 13 11:19:48 2012 +0200
+++ b/mercurial/hbisect.py Sun May 13 12:52:24 2012 +0200
@@ -132,7 +132,7 @@
def load_state(repo):
- state = {'good': [], 'bad': [], 'skip': []}
+ state = {'current': [], 'good': [], 'bad': [], 'skip': []}
if os.path.exists(repo.join("bisect.state")):
for l in repo.opener("bisect.state"):
kind, node = l[:-1].split()
@@ -164,10 +164,11 @@
- ``pruned`` : csets that are goods, bads or skipped
- ``untested`` : csets whose fate is yet unknown
- ``ignored`` : csets ignored due to DAG topology
+ - ``current`` : the cset currently being bisected
"""
state = load_state(repo)
- if status in ('good', 'bad', 'skip'):
- return [repo.changelog.rev(n) for n in state[status]]
+ if status in ('good', 'bad', 'skip', 'current'):
+ return map(repo.changelog.rev, state[status])
else:
# In the floowing sets, we do *not* call 'bisect()' with more
# than one level of recusrsion, because that can be very, very
@@ -233,7 +234,7 @@
if rev in get(repo, 'skip'):
# i18n: bisect changeset status
return _('skipped')
- if rev in get(repo, 'untested'):
+ if rev in get(repo, 'untested') or rev in get(repo, 'current'):
# i18n: bisect changeset status
return _('untested')
if rev in get(repo, 'ignored'):
--- a/mercurial/hgweb/common.py Sun May 13 11:19:48 2012 +0200
+++ b/mercurial/hgweb/common.py Sun May 13 12:52:24 2012 +0200
@@ -95,7 +95,7 @@
def __getattr__(self, attr):
if attr in ('close', 'readline', 'readlines', '__iter__'):
return getattr(self.f, attr)
- raise AttributeError()
+ raise AttributeError
def _statusmessage(code):
from BaseHTTPServer import BaseHTTPRequestHandler
--- a/mercurial/hgweb/hgweb_mod.py Sun May 13 11:19:48 2012 +0200
+++ b/mercurial/hgweb/hgweb_mod.py Sun May 13 12:52:24 2012 +0200
@@ -73,7 +73,8 @@
self.repo = hg.repository(self.repo.ui, self.repo.root)
self.maxchanges = int(self.config("web", "maxchanges", 10))
self.stripecount = int(self.config("web", "stripes", 1))
- self.maxshortchanges = int(self.config("web", "maxshortchanges", 60))
+ self.maxshortchanges = int(self.config("web", "maxshortchanges",
+ 60))
self.maxfiles = int(self.config("web", "maxfiles", 10))
self.allowpull = self.configbool("web", "allowpull", True)
encoding.encoding = self.config("web", "encoding",
--- a/mercurial/httpclient/__init__.py Sun May 13 11:19:48 2012 +0200
+++ b/mercurial/httpclient/__init__.py Sun May 13 12:52:24 2012 +0200
@@ -45,6 +45,7 @@
import select
import socket
+import _readers
import socketutil
logger = logging.getLogger(__name__)
@@ -54,8 +55,6 @@
HTTP_VER_1_0 = 'HTTP/1.0'
HTTP_VER_1_1 = 'HTTP/1.1'
-_LEN_CLOSE_IS_END = -1
-
OUTGOING_BUFFER_SIZE = 1 << 15
INCOMING_BUFFER_SIZE = 1 << 20
@@ -83,23 +82,19 @@
The response will continue to load as available. If you need the
complete response before continuing, check the .complete() method.
"""
- def __init__(self, sock, timeout):
+ def __init__(self, sock, timeout, method):
self.sock = sock
+ self.method = method
self.raw_response = ''
- self._body = None
self._headers_len = 0
- self._content_len = 0
self.headers = None
self.will_close = False
self.status_line = ''
self.status = None
+ self.continued = False
self.http_version = None
self.reason = None
- self._chunked = False
- self._chunked_done = False
- self._chunked_until_next = 0
- self._chunked_skip_bytes = 0
- self._chunked_preloaded_block = None
+ self._reader = None
self._read_location = 0
self._eol = EOL
@@ -117,11 +112,12 @@
socket is closed, this will nearly always return False, even
in cases where all the data has actually been loaded.
"""
- if self._chunked:
- return self._chunked_done
- if self._content_len == _LEN_CLOSE_IS_END:
- return False
- return self._body is not None and len(self._body) >= self._content_len
+ if self._reader:
+ return self._reader.done()
+
+ def _close(self):
+ if self._reader is not None:
+ self._reader._close()
def readline(self):
"""Read a single line from the response body.
@@ -129,30 +125,34 @@
This may block until either a line ending is found or the
response is complete.
"""
- eol = self._body.find('\n', self._read_location)
- while eol == -1 and not self.complete():
+ # TODO: move this into the reader interface where it can be
+ # smarter (and probably avoid copies)
+ bytes = []
+ while not bytes:
+ try:
+ bytes = [self._reader.read(1)]
+ except _readers.ReadNotReady:
+ self._select()
+ while bytes[-1] != '\n' and not self.complete():
self._select()
- eol = self._body.find('\n', self._read_location)
- if eol != -1:
- eol += 1
- else:
- eol = len(self._body)
- data = self._body[self._read_location:eol]
- self._read_location = eol
- return data
+ bytes.append(self._reader.read(1))
+ if bytes[-1] != '\n':
+ next = self._reader.read(1)
+ while next and next != '\n':
+ bytes.append(next)
+ next = self._reader.read(1)
+ bytes.append(next)
+ return ''.join(bytes)
def read(self, length=None):
# if length is None, unbounded read
while (not self.complete() # never select on a finished read
and (not length # unbounded, so we wait for complete()
- or (self._read_location + length) > len(self._body))):
+ or length > self._reader.available_data)):
self._select()
if not length:
- length = len(self._body) - self._read_location
- elif len(self._body) < (self._read_location + length):
- length = len(self._body) - self._read_location
- r = self._body[self._read_location:self._read_location + length]
- self._read_location += len(r)
+ length = self._reader.available_data
+ r = self._reader.read(length)
if self.complete() and self.will_close:
self.sock.close()
return r
@@ -160,93 +160,35 @@
def _select(self):
r, _, _ = select.select([self.sock], [], [], self._timeout)
if not r:
- # socket was not readable. If the response is not complete
- # and we're not a _LEN_CLOSE_IS_END response, raise a timeout.
- # If we are a _LEN_CLOSE_IS_END response and we have no data,
- # raise a timeout.
- if not (self.complete() or
- (self._content_len == _LEN_CLOSE_IS_END and self._body)):
+ # socket was not readable. If the response is not
+ # complete, raise a timeout.
+ if not self.complete():
logger.info('timed out with timeout of %s', self._timeout)
raise HTTPTimeoutException('timeout reading data')
- logger.info('cl: %r body: %r', self._content_len, self._body)
try:
data = self.sock.recv(INCOMING_BUFFER_SIZE)
- # If the socket was readable and no data was read, that
- # means the socket was closed. If this isn't a
- # _CLOSE_IS_END socket, then something is wrong if we're
- # here (we shouldn't enter _select() if the response is
- # complete), so abort.
- if not data and self._content_len != _LEN_CLOSE_IS_END:
- raise HTTPRemoteClosedError(
- 'server appears to have closed the socket mid-response')
except socket.sslerror, e:
if e.args[0] != socket.SSL_ERROR_WANT_READ:
raise
logger.debug('SSL_WANT_READ in _select, should retry later')
return True
logger.debug('response read %d data during _select', len(data))
+ # If the socket was readable and no data was read, that means
+ # the socket was closed. Inform the reader (if any) so it can
+ # raise an exception if this is an invalid situation.
if not data:
- if self.headers and self._content_len == _LEN_CLOSE_IS_END:
- self._content_len = len(self._body)
+ if self._reader:
+ self._reader._close()
return False
else:
self._load_response(data)
return True
- def _chunked_parsedata(self, data):
- if self._chunked_preloaded_block:
- data = self._chunked_preloaded_block + data
- self._chunked_preloaded_block = None
- while data:
- logger.debug('looping with %d data remaining', len(data))
- # Slice out anything we should skip
- if self._chunked_skip_bytes:
- if len(data) <= self._chunked_skip_bytes:
- self._chunked_skip_bytes -= len(data)
- data = ''
- break
- else:
- data = data[self._chunked_skip_bytes:]
- self._chunked_skip_bytes = 0
-
- # determine how much is until the next chunk
- if self._chunked_until_next:
- amt = self._chunked_until_next
- logger.debug('reading remaining %d of existing chunk', amt)
- self._chunked_until_next = 0
- body = data
- else:
- try:
- amt, body = data.split(self._eol, 1)
- except ValueError:
- self._chunked_preloaded_block = data
- logger.debug('saving %r as a preloaded block for chunked',
- self._chunked_preloaded_block)
- return
- amt = int(amt, base=16)
- logger.debug('reading chunk of length %d', amt)
- if amt == 0:
- self._chunked_done = True
-
- # read through end of what we have or the chunk
- self._body += body[:amt]
- if len(body) >= amt:
- data = body[amt:]
- self._chunked_skip_bytes = len(self._eol)
- else:
- self._chunked_until_next = amt - len(body)
- self._chunked_skip_bytes = 0
- data = ''
-
def _load_response(self, data):
- if self._chunked:
- self._chunked_parsedata(data)
- return
- elif self._body is not None:
- self._body += data
- return
-
- # We haven't seen end of headers yet
+ # Being here implies we're not at the end of the headers yet,
+ # since at the end of this method if headers were completely
+ # loaded we replace this method with the load() method of the
+ # reader we created.
self.raw_response += data
# This is a bogus server with bad line endings
if self._eol not in self.raw_response:
@@ -270,6 +212,7 @@
http_ver, status = hdrs.split(' ', 1)
if status.startswith('100'):
self.raw_response = body
+ self.continued = True
logger.debug('continue seen, setting body to %r', body)
return
@@ -289,23 +232,46 @@
if self._eol != EOL:
hdrs = hdrs.replace(self._eol, '\r\n')
headers = rfc822.Message(cStringIO.StringIO(hdrs))
+ content_len = None
if HDR_CONTENT_LENGTH in headers:
- self._content_len = int(headers[HDR_CONTENT_LENGTH])
+ content_len = int(headers[HDR_CONTENT_LENGTH])
if self.http_version == HTTP_VER_1_0:
self.will_close = True
elif HDR_CONNECTION_CTRL in headers:
self.will_close = (
headers[HDR_CONNECTION_CTRL].lower() == CONNECTION_CLOSE)
- if self._content_len == 0:
- self._content_len = _LEN_CLOSE_IS_END
if (HDR_XFER_ENCODING in headers
and headers[HDR_XFER_ENCODING].lower() == XFER_ENCODING_CHUNKED):
- self._body = ''
- self._chunked_parsedata(body)
- self._chunked = True
- if self._body is None:
- self._body = body
+ self._reader = _readers.ChunkedReader(self._eol)
+ logger.debug('using a chunked reader')
+ else:
+ # HEAD responses are forbidden from returning a body, and
+ # it's implausible for a CONNECT response to use
+ # close-is-end logic for an OK response.
+ if (self.method == 'HEAD' or
+ (self.method == 'CONNECT' and content_len is None)):
+ content_len = 0
+ if content_len is not None:
+ logger.debug('using a content-length reader with length %d',
+ content_len)
+ self._reader = _readers.ContentLengthReader(content_len)
+ else:
+ # Response body had no length specified and is not
+ # chunked, so the end of the body will only be
+ # identifiable by the termination of the socket by the
+ # server. My interpretation of the spec means that we
+ # are correct in hitting this case if
+ # transfer-encoding, content-length, and
+ # connection-control were left unspecified.
+ self._reader = _readers.CloseIsEndReader()
+ logger.debug('using a close-is-end reader')
+ self.will_close = True
+
+ if body:
+ self._reader._load(body)
+ logger.debug('headers complete')
self.headers = headers
+ self._load_response = self._reader._load
class HTTPConnection(object):
@@ -382,13 +348,14 @@
{}, HTTP_VER_1_0)
sock.send(data)
sock.setblocking(0)
- r = self.response_class(sock, self.timeout)
+ r = self.response_class(sock, self.timeout, 'CONNECT')
timeout_exc = HTTPTimeoutException(
'Timed out waiting for CONNECT response from proxy')
while not r.complete():
try:
if not r._select():
- raise timeout_exc
+ if not r.complete():
+ raise timeout_exc
except HTTPTimeoutException:
# This raise/except pattern looks goofy, but
# _select can raise the timeout as well as the
@@ -527,7 +494,7 @@
out = outgoing_headers or body
blocking_on_continue = False
if expect_continue and not outgoing_headers and not (
- response and response.headers):
+ response and (response.headers or response.continued)):
logger.info(
'waiting up to %s seconds for'
' continue response from server',
@@ -550,11 +517,6 @@
'server, optimistically sending request body')
else:
raise HTTPTimeoutException('timeout sending data')
- # TODO exceptional conditions with select? (what are those be?)
- # TODO if the response is loading, must we finish sending at all?
- #
- # Certainly not if it's going to close the connection and/or
- # the response is already done...I think.
was_first = first
# incoming data
@@ -572,11 +534,11 @@
logger.info('socket appears closed in read')
self.sock = None
self._current_response = None
+ if response is not None:
+ response._close()
# This if/elif ladder is a bit subtle,
# comments in each branch should help.
- if response is not None and (
- response.complete() or
- response._content_len == _LEN_CLOSE_IS_END):
+ if response is not None and response.complete():
# Server responded completely and then
# closed the socket. We should just shut
# things down and let the caller get their
@@ -605,7 +567,7 @@
'response was missing or incomplete!')
logger.debug('read %d bytes in request()', len(data))
if response is None:
- response = self.response_class(r[0], self.timeout)
+ response = self.response_class(r[0], self.timeout, method)
response._load_response(data)
# Jump to the next select() call so we load more
# data if the server is still sending us content.
@@ -613,10 +575,6 @@
except socket.error, e:
if e[0] != errno.EPIPE and not was_first:
raise
- if (response._content_len
- and response._content_len != _LEN_CLOSE_IS_END):
- outgoing_headers = sent_data + outgoing_headers
- reconnect('read')
# outgoing data
if w and out:
@@ -661,7 +619,7 @@
# close if the server response said to or responded before eating
# the whole request
if response is None:
- response = self.response_class(self.sock, self.timeout)
+ response = self.response_class(self.sock, self.timeout, method)
complete = response.complete()
data_left = bool(outgoing_headers or body)
if data_left:
@@ -679,7 +637,8 @@
raise httplib.ResponseNotReady()
r = self._current_response
while r.headers is None:
- r._select()
+ if not r._select() and not r.complete():
+ raise _readers.HTTPRemoteClosedError()
if r.will_close:
self.sock = None
self._current_response = None
@@ -705,7 +664,7 @@
class HTTPStateError(httplib.HTTPException):
"""Invalid internal state encountered."""
-
-class HTTPRemoteClosedError(httplib.HTTPException):
- """The server closed the remote socket in the middle of a response."""
+# Forward this exception type from _readers since it needs to be part
+# of the public API.
+HTTPRemoteClosedError = _readers.HTTPRemoteClosedError
# no-check-code
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/mercurial/httpclient/_readers.py Sun May 13 12:52:24 2012 +0200
@@ -0,0 +1,195 @@
+# Copyright 2011, Google Inc.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+"""Reader objects to abstract out different body response types.
+
+This module is package-private. It is not expected that these will
+have any clients outside of httpplus.
+"""
+
+import httplib
+import itertools
+import logging
+
+logger = logging.getLogger(__name__)
+
+
+class ReadNotReady(Exception):
+ """Raised when read() is attempted but not enough data is loaded."""
+
+
+class HTTPRemoteClosedError(httplib.HTTPException):
+ """The server closed the remote socket in the middle of a response."""
+
+
+class AbstractReader(object):
+ """Abstract base class for response readers.
+
+ Subclasses must implement _load, and should implement _close if
+ it's not an error for the server to close their socket without
+ some termination condition being detected during _load.
+ """
+ def __init__(self):
+ self._finished = False
+ self._done_chunks = []
+
+ @property
+ def available_data(self):
+ return sum(map(len, self._done_chunks))
+
+ def done(self):
+ return self._finished
+
+ def read(self, amt):
+ if self.available_data < amt and not self._finished:
+ raise ReadNotReady()
+ need = [amt]
+ def pred(s):
+ needed = need[0] > 0
+ need[0] -= len(s)
+ return needed
+ blocks = list(itertools.takewhile(pred, self._done_chunks))
+ self._done_chunks = self._done_chunks[len(blocks):]
+ over_read = sum(map(len, blocks)) - amt
+ if over_read > 0 and blocks:
+ logger.debug('need to reinsert %d data into done chunks', over_read)
+ last = blocks[-1]
+ blocks[-1], reinsert = last[:-over_read], last[-over_read:]
+ self._done_chunks.insert(0, reinsert)
+ result = ''.join(blocks)
+ assert len(result) == amt or (self._finished and len(result) < amt)
+ return result
+
+ def _load(self, data): # pragma: no cover
+ """Subclasses must implement this.
+
+ As data is available to be read out of this object, it should
+ be placed into the _done_chunks list. Subclasses should not
+ rely on data remaining in _done_chunks forever, as it may be
+ reaped if the client is parsing data as it comes in.
+ """
+ raise NotImplementedError
+
+ def _close(self):
+ """Default implementation of close.
+
+ The default implementation assumes that the reader will mark
+ the response as finished on the _finished attribute once the
+ entire response body has been read. In the event that this is
+ not true, the subclass should override the implementation of
+ close (for example, close-is-end responses have to set
+ self._finished in the close handler.)
+ """
+ if not self._finished:
+ raise HTTPRemoteClosedError(
+ 'server appears to have closed the socket mid-response')
+
+
+class AbstractSimpleReader(AbstractReader):
+ """Abstract base class for simple readers that require no response decoding.
+
+ Examples of such responses are Connection: Close (close-is-end)
+ and responses that specify a content length.
+ """
+ def _load(self, data):
+ if data:
+ assert not self._finished, (
+ 'tried to add data (%r) to a closed reader!' % data)
+ logger.debug('%s read an addtional %d data', self.name, len(data))
+ self._done_chunks.append(data)
+
+
+class CloseIsEndReader(AbstractSimpleReader):
+ """Reader for responses that specify Connection: Close for length."""
+ name = 'close-is-end'
+
+ def _close(self):
+ logger.info('Marking close-is-end reader as closed.')
+ self._finished = True
+
+
+class ContentLengthReader(AbstractSimpleReader):
+ """Reader for responses that specify an exact content length."""
+ name = 'content-length'
+
+ def __init__(self, amount):
+ AbstractReader.__init__(self)
+ self._amount = amount
+ if amount == 0:
+ self._finished = True
+ self._amount_seen = 0
+
+ def _load(self, data):
+ AbstractSimpleReader._load(self, data)
+ self._amount_seen += len(data)
+ if self._amount_seen >= self._amount:
+ self._finished = True
+ logger.debug('content-length read complete')
+
+
+class ChunkedReader(AbstractReader):
+ """Reader for chunked transfer encoding responses."""
+ def __init__(self, eol):
+ AbstractReader.__init__(self)
+ self._eol = eol
+ self._leftover_skip_amt = 0
+ self._leftover_data = ''
+
+ def _load(self, data):
+ assert not self._finished, 'tried to add data to a closed reader!'
+ logger.debug('chunked read an addtional %d data', len(data))
+ position = 0
+ if self._leftover_data:
+ logger.debug('chunked reader trying to finish block from leftover data')
+ # TODO: avoid this string concatenation if possible
+ data = self._leftover_data + data
+ position = self._leftover_skip_amt
+ self._leftover_data = ''
+ self._leftover_skip_amt = 0
+ datalen = len(data)
+ while position < datalen:
+ split = data.find(self._eol, position)
+ if split == -1:
+ self._leftover_data = data
+ self._leftover_skip_amt = position
+ return
+ amt = int(data[position:split], base=16)
+ block_start = split + len(self._eol)
+ # If the whole data chunk plus the eol trailer hasn't
+ # loaded, we'll wait for the next load.
+ if block_start + amt + len(self._eol) > len(data):
+ self._leftover_data = data
+ self._leftover_skip_amt = position
+ return
+ if amt == 0:
+ self._finished = True
+ logger.debug('closing chunked redaer due to chunk of length 0')
+ return
+ self._done_chunks.append(data[block_start:block_start + amt])
+ position = block_start + amt + len(self._eol)
+# no-check-code
--- a/mercurial/httpclient/tests/simple_http_test.py Sun May 13 11:19:48 2012 +0200
+++ b/mercurial/httpclient/tests/simple_http_test.py Sun May 13 12:52:24 2012 +0200
@@ -29,7 +29,7 @@
import socket
import unittest
-import http
+import httpplus
# relative import to ease embedding the library
import util
@@ -38,7 +38,7 @@
class SimpleHttpTest(util.HttpTestBase, unittest.TestCase):
def _run_simple_test(self, host, server_data, expected_req, expected_data):
- con = http.HTTPConnection(host)
+ con = httpplus.HTTPConnection(host)
con._connect()
con.sock.data = server_data
con.request('GET', '/')
@@ -47,9 +47,9 @@
self.assertEqual(expected_data, con.getresponse().read())
def test_broken_data_obj(self):
- con = http.HTTPConnection('1.2.3.4:80')
+ con = httpplus.HTTPConnection('1.2.3.4:80')
con._connect()
- self.assertRaises(http.BadRequestData,
+ self.assertRaises(httpplus.BadRequestData,
con.request, 'POST', '/', body=1)
def test_no_keepalive_http_1_0(self):
@@ -74,7 +74,7 @@
fncache
dotencode
"""
- con = http.HTTPConnection('localhost:9999')
+ con = httpplus.HTTPConnection('localhost:9999')
con._connect()
con.sock.data = [expected_response_headers, expected_response_body]
con.request('GET', '/remote/.hg/requires',
@@ -95,7 +95,7 @@
self.assert_(resp.sock.closed)
def test_multiline_header(self):
- con = http.HTTPConnection('1.2.3.4:80')
+ con = httpplus.HTTPConnection('1.2.3.4:80')
con._connect()
con.sock.data = ['HTTP/1.1 200 OK\r\n',
'Server: BogusServer 1.0\r\n',
@@ -122,7 +122,7 @@
self.assertEqual(con.sock.closed, False)
def testSimpleRequest(self):
- con = http.HTTPConnection('1.2.3.4:80')
+ con = httpplus.HTTPConnection('1.2.3.4:80')
con._connect()
con.sock.data = ['HTTP/1.1 200 OK\r\n',
'Server: BogusServer 1.0\r\n',
@@ -149,12 +149,13 @@
resp.headers.getheaders('server'))
def testHeaderlessResponse(self):
- con = http.HTTPConnection('1.2.3.4', use_ssl=False)
+ con = httpplus.HTTPConnection('1.2.3.4', use_ssl=False)
con._connect()
con.sock.data = ['HTTP/1.1 200 OK\r\n',
'\r\n'
'1234567890'
]
+ con.sock.close_on_empty = True
con.request('GET', '/')
expected_req = ('GET / HTTP/1.1\r\n'
@@ -169,7 +170,30 @@
self.assertEqual(resp.status, 200)
def testReadline(self):
- con = http.HTTPConnection('1.2.3.4')
+ con = httpplus.HTTPConnection('1.2.3.4')
+ con._connect()
+ con.sock.data = ['HTTP/1.1 200 OK\r\n',
+ 'Server: BogusServer 1.0\r\n',
+ 'Connection: Close\r\n',
+ '\r\n'
+ '1\n2\nabcdefg\n4\n5']
+ con.sock.close_on_empty = True
+
+ expected_req = ('GET / HTTP/1.1\r\n'
+ 'Host: 1.2.3.4\r\n'
+ 'accept-encoding: identity\r\n\r\n')
+
+ con.request('GET', '/')
+ self.assertEqual(('1.2.3.4', 80), con.sock.sa)
+ self.assertEqual(expected_req, con.sock.sent)
+ r = con.getresponse()
+ for expected in ['1\n', '2\n', 'abcdefg\n', '4\n', '5']:
+ actual = r.readline()
+ self.assertEqual(expected, actual,
+ 'Expected %r, got %r' % (expected, actual))
+
+ def testReadlineTrickle(self):
+ con = httpplus.HTTPConnection('1.2.3.4')
con._connect()
# make sure it trickles in one byte at a time
# so that we touch all the cases in readline
@@ -179,6 +203,7 @@
'Connection: Close\r\n',
'\r\n'
'1\n2\nabcdefg\n4\n5']))
+ con.sock.close_on_empty = True
expected_req = ('GET / HTTP/1.1\r\n'
'Host: 1.2.3.4\r\n'
@@ -193,6 +218,59 @@
self.assertEqual(expected, actual,
'Expected %r, got %r' % (expected, actual))
+ def testVariousReads(self):
+ con = httpplus.HTTPConnection('1.2.3.4')
+ con._connect()
+ # make sure it trickles in one byte at a time
+ # so that we touch all the cases in readline
+ con.sock.data = list(''.join(
+ ['HTTP/1.1 200 OK\r\n',
+ 'Server: BogusServer 1.0\r\n',
+ 'Connection: Close\r\n',
+ '\r\n'
+ '1\n2',
+ '\na', 'bc',
+ 'defg\n4\n5']))
+ con.sock.close_on_empty = True
+
+ expected_req = ('GET / HTTP/1.1\r\n'
+ 'Host: 1.2.3.4\r\n'
+ 'accept-encoding: identity\r\n\r\n')
+
+ con.request('GET', '/')
+ self.assertEqual(('1.2.3.4', 80), con.sock.sa)
+ self.assertEqual(expected_req, con.sock.sent)
+ r = con.getresponse()
+ for read_amt, expect in [(1, '1'), (1, '\n'),
+ (4, '2\nab'),
+ ('line', 'cdefg\n'),
+ (None, '4\n5')]:
+ if read_amt == 'line':
+ self.assertEqual(expect, r.readline())
+ else:
+ self.assertEqual(expect, r.read(read_amt))
+
+ def testZeroLengthBody(self):
+ con = httpplus.HTTPConnection('1.2.3.4')
+ con._connect()
+ # make sure it trickles in one byte at a time
+ # so that we touch all the cases in readline
+ con.sock.data = list(''.join(
+ ['HTTP/1.1 200 OK\r\n',
+ 'Server: BogusServer 1.0\r\n',
+ 'Content-length: 0\r\n',
+ '\r\n']))
+
+ expected_req = ('GET / HTTP/1.1\r\n'
+ 'Host: 1.2.3.4\r\n'
+ 'accept-encoding: identity\r\n\r\n')
+
+ con.request('GET', '/')
+ self.assertEqual(('1.2.3.4', 80), con.sock.sa)
+ self.assertEqual(expected_req, con.sock.sent)
+ r = con.getresponse()
+ self.assertEqual('', r.read())
+
def testIPv6(self):
self._run_simple_test('[::1]:8221',
['HTTP/1.1 200 OK\r\n',
@@ -226,7 +304,7 @@
'1234567890')
def testEarlyContinueResponse(self):
- con = http.HTTPConnection('1.2.3.4:80')
+ con = httpplus.HTTPConnection('1.2.3.4:80')
con._connect()
sock = con.sock
sock.data = ['HTTP/1.1 403 Forbidden\r\n',
@@ -240,8 +318,23 @@
self.assertEqual("You can't do that.", con.getresponse().read())
self.assertEqual(sock.closed, True)
+ def testEarlyContinueResponseNoContentLength(self):
+ con = httpplus.HTTPConnection('1.2.3.4:80')
+ con._connect()
+ sock = con.sock
+ sock.data = ['HTTP/1.1 403 Forbidden\r\n',
+ 'Server: BogusServer 1.0\r\n',
+ '\r\n'
+ "You can't do that."]
+ sock.close_on_empty = True
+ expected_req = self.doPost(con, expect_body=False)
+ self.assertEqual(('1.2.3.4', 80), sock.sa)
+ self.assertStringEqual(expected_req, sock.sent)
+ self.assertEqual("You can't do that.", con.getresponse().read())
+ self.assertEqual(sock.closed, True)
+
def testDeniedAfterContinueTimeoutExpires(self):
- con = http.HTTPConnection('1.2.3.4:80')
+ con = httpplus.HTTPConnection('1.2.3.4:80')
con._connect()
sock = con.sock
sock.data = ['HTTP/1.1 403 Forbidden\r\n',
@@ -269,7 +362,7 @@
self.assertEqual(sock.closed, True)
def testPostData(self):
- con = http.HTTPConnection('1.2.3.4:80')
+ con = httpplus.HTTPConnection('1.2.3.4:80')
con._connect()
sock = con.sock
sock.read_wait_sentinel = 'POST data'
@@ -286,7 +379,7 @@
self.assertEqual(sock.closed, False)
def testServerWithoutContinue(self):
- con = http.HTTPConnection('1.2.3.4:80')
+ con = httpplus.HTTPConnection('1.2.3.4:80')
con._connect()
sock = con.sock
sock.read_wait_sentinel = 'POST data'
@@ -302,7 +395,7 @@
self.assertEqual(sock.closed, False)
def testServerWithSlowContinue(self):
- con = http.HTTPConnection('1.2.3.4:80')
+ con = httpplus.HTTPConnection('1.2.3.4:80')
con._connect()
sock = con.sock
sock.read_wait_sentinel = 'POST data'
@@ -321,7 +414,7 @@
self.assertEqual(sock.closed, False)
def testSlowConnection(self):
- con = http.HTTPConnection('1.2.3.4:80')
+ con = httpplus.HTTPConnection('1.2.3.4:80')
con._connect()
# simulate one byte arriving at a time, to check for various
# corner cases
@@ -340,12 +433,26 @@
self.assertEqual(expected_req, con.sock.sent)
self.assertEqual('1234567890', con.getresponse().read())
+ def testCloseAfterNotAllOfHeaders(self):
+ con = httpplus.HTTPConnection('1.2.3.4:80')
+ con._connect()
+ con.sock.data = ['HTTP/1.1 200 OK\r\n',
+ 'Server: NO CARRIER']
+ con.sock.close_on_empty = True
+ con.request('GET', '/')
+ self.assertRaises(httpplus.HTTPRemoteClosedError,
+ con.getresponse)
+
+ expected_req = ('GET / HTTP/1.1\r\n'
+ 'Host: 1.2.3.4\r\n'
+ 'accept-encoding: identity\r\n\r\n')
+
def testTimeout(self):
- con = http.HTTPConnection('1.2.3.4:80')
+ con = httpplus.HTTPConnection('1.2.3.4:80')
con._connect()
con.sock.data = []
con.request('GET', '/')
- self.assertRaises(http.HTTPTimeoutException,
+ self.assertRaises(httpplus.HTTPTimeoutException,
con.getresponse)
expected_req = ('GET / HTTP/1.1\r\n'
@@ -370,7 +477,7 @@
return s
socket.socket = closingsocket
- con = http.HTTPConnection('1.2.3.4:80')
+ con = httpplus.HTTPConnection('1.2.3.4:80')
con._connect()
con.request('GET', '/')
r1 = con.getresponse()
@@ -381,7 +488,7 @@
self.assertEqual(2, len(sockets))
def test_server_closes_before_end_of_body(self):
- con = http.HTTPConnection('1.2.3.4:80')
+ con = httpplus.HTTPConnection('1.2.3.4:80')
con._connect()
s = con.sock
s.data = ['HTTP/1.1 200 OK\r\n',
@@ -393,9 +500,9 @@
s.close_on_empty = True
con.request('GET', '/')
r1 = con.getresponse()
- self.assertRaises(http.HTTPRemoteClosedError, r1.read)
+ self.assertRaises(httpplus.HTTPRemoteClosedError, r1.read)
def test_no_response_raises_response_not_ready(self):
- con = http.HTTPConnection('foo')
- self.assertRaises(http.httplib.ResponseNotReady, con.getresponse)
+ con = httpplus.HTTPConnection('foo')
+ self.assertRaises(httpplus.httplib.ResponseNotReady, con.getresponse)
# no-check-code
--- a/mercurial/httpclient/tests/test_bogus_responses.py Sun May 13 11:19:48 2012 +0200
+++ b/mercurial/httpclient/tests/test_bogus_responses.py Sun May 13 12:52:24 2012 +0200
@@ -34,7 +34,7 @@
"""
import unittest
-import http
+import httpplus
# relative import to ease embedding the library
import util
@@ -43,7 +43,7 @@
class SimpleHttpTest(util.HttpTestBase, unittest.TestCase):
def bogusEOL(self, eol):
- con = http.HTTPConnection('1.2.3.4:80')
+ con = httpplus.HTTPConnection('1.2.3.4:80')
con._connect()
con.sock.data = ['HTTP/1.1 200 OK%s' % eol,
'Server: BogusServer 1.0%s' % eol,
--- a/mercurial/httpclient/tests/test_chunked_transfer.py Sun May 13 11:19:48 2012 +0200
+++ b/mercurial/httpclient/tests/test_chunked_transfer.py Sun May 13 12:52:24 2012 +0200
@@ -29,7 +29,7 @@
import cStringIO
import unittest
-import http
+import httpplus
# relative import to ease embedding the library
import util
@@ -50,7 +50,7 @@
class ChunkedTransferTest(util.HttpTestBase, unittest.TestCase):
def testChunkedUpload(self):
- con = http.HTTPConnection('1.2.3.4:80')
+ con = httpplus.HTTPConnection('1.2.3.4:80')
con._connect()
sock = con.sock
sock.read_wait_sentinel = '0\r\n\r\n'
@@ -77,7 +77,7 @@
self.assertEqual(sock.closed, False)
def testChunkedDownload(self):
- con = http.HTTPConnection('1.2.3.4:80')
+ con = httpplus.HTTPConnection('1.2.3.4:80')
con._connect()
sock = con.sock
sock.data = ['HTTP/1.1 200 OK\r\n',
@@ -85,14 +85,31 @@
'transfer-encoding: chunked',
'\r\n\r\n',
chunkedblock('hi '),
- chunkedblock('there'),
+ ] + list(chunkedblock('there')) + [
chunkedblock(''),
]
con.request('GET', '/')
self.assertStringEqual('hi there', con.getresponse().read())
+ def testChunkedDownloadOddReadBoundaries(self):
+ con = httpplus.HTTPConnection('1.2.3.4:80')
+ con._connect()
+ sock = con.sock
+ sock.data = ['HTTP/1.1 200 OK\r\n',
+ 'Server: BogusServer 1.0\r\n',
+ 'transfer-encoding: chunked',
+ '\r\n\r\n',
+ chunkedblock('hi '),
+ ] + list(chunkedblock('there')) + [
+ chunkedblock(''),
+ ]
+ con.request('GET', '/')
+ resp = con.getresponse()
+ for amt, expect in [(1, 'h'), (5, 'i the'), (100, 're')]:
+ self.assertEqual(expect, resp.read(amt))
+
def testChunkedDownloadBadEOL(self):
- con = http.HTTPConnection('1.2.3.4:80')
+ con = httpplus.HTTPConnection('1.2.3.4:80')
con._connect()
sock = con.sock
sock.data = ['HTTP/1.1 200 OK\n',
@@ -107,7 +124,7 @@
self.assertStringEqual('hi there', con.getresponse().read())
def testChunkedDownloadPartialChunkBadEOL(self):
- con = http.HTTPConnection('1.2.3.4:80')
+ con = httpplus.HTTPConnection('1.2.3.4:80')
con._connect()
sock = con.sock
sock.data = ['HTTP/1.1 200 OK\n',
@@ -122,7 +139,7 @@
con.getresponse().read())
def testChunkedDownloadPartialChunk(self):
- con = http.HTTPConnection('1.2.3.4:80')
+ con = httpplus.HTTPConnection('1.2.3.4:80')
con._connect()
sock = con.sock
sock.data = ['HTTP/1.1 200 OK\r\n',
@@ -136,7 +153,7 @@
con.getresponse().read())
def testChunkedDownloadEarlyHangup(self):
- con = http.HTTPConnection('1.2.3.4:80')
+ con = httpplus.HTTPConnection('1.2.3.4:80')
con._connect()
sock = con.sock
broken = chunkedblock('hi'*20)[:-1]
@@ -149,5 +166,5 @@
sock.close_on_empty = True
con.request('GET', '/')
resp = con.getresponse()
- self.assertRaises(http.HTTPRemoteClosedError, resp.read)
+ self.assertRaises(httpplus.HTTPRemoteClosedError, resp.read)
# no-check-code
--- a/mercurial/httpclient/tests/test_proxy_support.py Sun May 13 11:19:48 2012 +0200
+++ b/mercurial/httpclient/tests/test_proxy_support.py Sun May 13 12:52:24 2012 +0200
@@ -29,13 +29,13 @@
import unittest
import socket
-import http
+import httpplus
# relative import to ease embedding the library
import util
-def make_preloaded_socket(data):
+def make_preloaded_socket(data, close=False):
"""Make a socket pre-loaded with data so it can be read during connect.
Useful for https proxy tests because we have to read from the
@@ -44,6 +44,7 @@
def s(*args, **kwargs):
sock = util.MockSocket(*args, **kwargs)
sock.early_data = data[:]
+ sock.close_on_empty = close
return sock
return s
@@ -51,7 +52,7 @@
class ProxyHttpTest(util.HttpTestBase, unittest.TestCase):
def _run_simple_test(self, host, server_data, expected_req, expected_data):
- con = http.HTTPConnection(host)
+ con = httpplus.HTTPConnection(host)
con._connect()
con.sock.data = server_data
con.request('GET', '/')
@@ -60,7 +61,7 @@
self.assertEqual(expected_data, con.getresponse().read())
def testSimpleRequest(self):
- con = http.HTTPConnection('1.2.3.4:80',
+ con = httpplus.HTTPConnection('1.2.3.4:80',
proxy_hostport=('magicproxy', 4242))
con._connect()
con.sock.data = ['HTTP/1.1 200 OK\r\n',
@@ -88,7 +89,7 @@
resp.headers.getheaders('server'))
def testSSLRequest(self):
- con = http.HTTPConnection('1.2.3.4:443',
+ con = httpplus.HTTPConnection('1.2.3.4:443',
proxy_hostport=('magicproxy', 4242))
socket.socket = make_preloaded_socket(
['HTTP/1.1 200 OK\r\n',
@@ -124,12 +125,47 @@
self.assertEqual(['BogusServer 1.0'],
resp.headers.getheaders('server'))
- def testSSLProxyFailure(self):
- con = http.HTTPConnection('1.2.3.4:443',
+ def testSSLRequestNoConnectBody(self):
+ con = httpplus.HTTPConnection('1.2.3.4:443',
proxy_hostport=('magicproxy', 4242))
socket.socket = make_preloaded_socket(
- ['HTTP/1.1 407 Proxy Authentication Required\r\n\r\n'])
- self.assertRaises(http.HTTPProxyConnectFailedException, con._connect)
- self.assertRaises(http.HTTPProxyConnectFailedException,
+ ['HTTP/1.1 200 OK\r\n',
+ 'Server: BogusServer 1.0\r\n',
+ '\r\n'])
+ con._connect()
+ con.sock.data = ['HTTP/1.1 200 OK\r\n',
+ 'Server: BogusServer 1.0\r\n',
+ 'Content-Length: 10\r\n',
+ '\r\n'
+ '1234567890'
+ ]
+ connect_sent = con.sock.sent
+ con.sock.sent = ''
+ con.request('GET', '/')
+
+ expected_connect = ('CONNECT 1.2.3.4:443 HTTP/1.0\r\n'
+ 'Host: 1.2.3.4\r\n'
+ 'accept-encoding: identity\r\n'
+ '\r\n')
+ expected_request = ('GET / HTTP/1.1\r\n'
+ 'Host: 1.2.3.4\r\n'
+ 'accept-encoding: identity\r\n\r\n')
+
+ self.assertEqual(('127.0.0.42', 4242), con.sock.sa)
+ self.assertStringEqual(expected_connect, connect_sent)
+ self.assertStringEqual(expected_request, con.sock.sent)
+ resp = con.getresponse()
+ self.assertEqual(resp.status, 200)
+ self.assertEqual('1234567890', resp.read())
+ self.assertEqual(['BogusServer 1.0'],
+ resp.headers.getheaders('server'))
+
+ def testSSLProxyFailure(self):
+ con = httpplus.HTTPConnection('1.2.3.4:443',
+ proxy_hostport=('magicproxy', 4242))
+ socket.socket = make_preloaded_socket(
+ ['HTTP/1.1 407 Proxy Authentication Required\r\n\r\n'], close=True)
+ self.assertRaises(httpplus.HTTPProxyConnectFailedException, con._connect)
+ self.assertRaises(httpplus.HTTPProxyConnectFailedException,
con.request, 'GET', '/')
# no-check-code
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/mercurial/httpclient/tests/test_readers.py Sun May 13 12:52:24 2012 +0200
@@ -0,0 +1,70 @@
+# Copyright 2010, Google Inc.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+import unittest
+
+from httpplus import _readers
+
+def chunkedblock(x, eol='\r\n'):
+ r"""Make a chunked transfer-encoding block.
+
+ >>> chunkedblock('hi')
+ '2\r\nhi\r\n'
+ >>> chunkedblock('hi' * 10)
+ '14\r\nhihihihihihihihihihi\r\n'
+ >>> chunkedblock('hi', eol='\n')
+ '2\nhi\n'
+ """
+ return ''.join((hex(len(x))[2:], eol, x, eol))
+
+corpus = 'foo\r\nbar\r\nbaz\r\n'
+
+
+class ChunkedReaderTest(unittest.TestCase):
+ def test_many_block_boundaries(self):
+ for step in xrange(1, len(corpus)):
+ data = ''.join(chunkedblock(corpus[start:start+step]) for
+ start in xrange(0, len(corpus), step))
+ for istep in xrange(1, len(data)):
+ rdr = _readers.ChunkedReader('\r\n')
+ print 'step', step, 'load', istep
+ for start in xrange(0, len(data), istep):
+ rdr._load(data[start:start+istep])
+ rdr._load(chunkedblock(''))
+ self.assertEqual(corpus, rdr.read(len(corpus) + 1))
+
+ def test_small_chunk_blocks_large_wire_blocks(self):
+ data = ''.join(map(chunkedblock, corpus)) + chunkedblock('')
+ rdr = _readers.ChunkedReader('\r\n')
+ for start in xrange(0, len(data), 4):
+ d = data[start:start + 4]
+ if d:
+ rdr._load(d)
+ self.assertEqual(corpus, rdr.read(len(corpus)+100))
+# no-check-code
--- a/mercurial/httpclient/tests/test_ssl.py Sun May 13 11:19:48 2012 +0200
+++ b/mercurial/httpclient/tests/test_ssl.py Sun May 13 12:52:24 2012 +0200
@@ -28,7 +28,7 @@
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
import unittest
-import http
+import httpplus
# relative import to ease embedding the library
import util
@@ -37,7 +37,7 @@
class HttpSslTest(util.HttpTestBase, unittest.TestCase):
def testSslRereadRequired(self):
- con = http.HTTPConnection('1.2.3.4:443')
+ con = httpplus.HTTPConnection('1.2.3.4:443')
con._connect()
# extend the list instead of assign because of how
# MockSSLSocket works.
@@ -66,7 +66,7 @@
resp.headers.getheaders('server'))
def testSslRereadInEarlyResponse(self):
- con = http.HTTPConnection('1.2.3.4:443')
+ con = httpplus.HTTPConnection('1.2.3.4:443')
con._connect()
con.sock.early_data = ['HTTP/1.1 200 OK\r\n',
'Server: BogusServer 1.0\r\n',
--- a/mercurial/httpclient/tests/util.py Sun May 13 11:19:48 2012 +0200
+++ b/mercurial/httpclient/tests/util.py Sun May 13 12:52:24 2012 +0200
@@ -29,7 +29,7 @@
import difflib
import socket
-import http
+import httpplus
class MockSocket(object):
@@ -57,7 +57,7 @@
self.remote_closed = self.closed = False
self.close_on_empty = False
self.sent = ''
- self.read_wait_sentinel = http._END_HEADERS
+ self.read_wait_sentinel = httpplus._END_HEADERS
def close(self):
self.closed = True
@@ -86,7 +86,7 @@
@property
def ready_for_read(self):
- return ((self.early_data and http._END_HEADERS in self.sent)
+ return ((self.early_data and httpplus._END_HEADERS in self.sent)
or (self.read_wait_sentinel in self.sent and self.data)
or self.closed or self.remote_closed)
@@ -132,7 +132,7 @@
def mocksslwrap(sock, keyfile=None, certfile=None,
- server_side=False, cert_reqs=http.socketutil.CERT_NONE,
+ server_side=False, cert_reqs=httpplus.socketutil.CERT_NONE,
ssl_version=None, ca_certs=None,
do_handshake_on_connect=True,
suppress_ragged_eofs=True):
@@ -156,16 +156,16 @@
self.orig_getaddrinfo = socket.getaddrinfo
socket.getaddrinfo = mockgetaddrinfo
- self.orig_select = http.select.select
- http.select.select = mockselect
+ self.orig_select = httpplus.select.select
+ httpplus.select.select = mockselect
- self.orig_sslwrap = http.socketutil.wrap_socket
- http.socketutil.wrap_socket = mocksslwrap
+ self.orig_sslwrap = httpplus.socketutil.wrap_socket
+ httpplus.socketutil.wrap_socket = mocksslwrap
def tearDown(self):
socket.socket = self.orig_socket
- http.select.select = self.orig_select
- http.socketutil.wrap_socket = self.orig_sslwrap
+ httpplus.select.select = self.orig_select
+ httpplus.socketutil.wrap_socket = self.orig_sslwrap
socket.getaddrinfo = self.orig_getaddrinfo
def assertStringEqual(self, l, r):
--- a/mercurial/keepalive.py Sun May 13 11:19:48 2012 +0200
+++ b/mercurial/keepalive.py Sun May 13 12:52:24 2012 +0200
@@ -136,7 +136,7 @@
def add(self, host, connection, ready):
self._lock.acquire()
try:
- if not host in self._hostmap:
+ if host not in self._hostmap:
self._hostmap[host] = []
self._hostmap[host].append(connection)
self._connmap[connection] = host
@@ -534,7 +534,7 @@
if self.auto_open:
self.connect()
else:
- raise httplib.NotConnected()
+ raise httplib.NotConnected
# send the data to the server. if we get a broken pipe, then close
# the socket. we want to reconnect when somebody tries to send again.
@@ -758,7 +758,7 @@
try:
N = int(sys.argv[1])
url = sys.argv[2]
- except:
+ except (IndexError, ValueError):
print "%s <integer> <url>" % sys.argv[0]
else:
test(url, N)
--- a/mercurial/localrepo.py Sun May 13 11:19:48 2012 +0200
+++ b/mercurial/localrepo.py Sun May 13 12:52:24 2012 +0200
@@ -41,7 +41,6 @@
self.wopener = scmutil.opener(self.root)
self.baseui = baseui
self.ui = baseui.copy()
- self._dirtyphases = False
# A list of callback to shape the phase if no data were found.
# Callback are in the form: func(repo, roots) --> processed root.
# This list it to be filled by extension during repo setup
@@ -182,23 +181,8 @@
bookmarks.write(self)
@storecache('phaseroots')
- def _phaseroots(self):
- self._dirtyphases = False
- phaseroots = phases.readroots(self)
- phases.filterunknown(self, phaseroots)
- return phaseroots
-
- @propertycache
- def _phaserev(self):
- cache = [phases.public] * len(self)
- for phase in phases.trackedphases:
- roots = map(self.changelog.rev, self._phaseroots[phase])
- if roots:
- for rev in roots:
- cache[rev] = phase
- for rev in self.changelog.descendants(*roots):
- cache[rev] = phase
- return cache
+ def _phasecache(self):
+ return phases.phasecache(self, self._phasedefaults)
@storecache('00changelog.i')
def changelog(self):
@@ -296,7 +280,8 @@
fp.write('\n')
for name in names:
m = munge and munge(name) or name
- if self._tagscache.tagtypes and name in self._tagscache.tagtypes:
+ if (self._tagscache.tagtypes and
+ name in self._tagscache.tagtypes):
old = self.tags().get(name, nullid)
fp.write('%s %s\n' % (hex(old), m))
fp.write('%s %s\n' % (hex(node), m))
@@ -376,7 +361,8 @@
@propertycache
def _tagscache(self):
- '''Returns a tagscache object that contains various tags related caches.'''
+ '''Returns a tagscache object that contains various tags related
+ caches.'''
# This simplifies its cache management by having one decorated
# function (this one) and the rest simply fetch things from it.
@@ -505,7 +491,7 @@
partial = self._branchcache
self._branchtags(partial, lrev)
- # this private cache holds all heads (not just tips)
+ # this private cache holds all heads (not just the branch tips)
self._branchcache = partial
def branchmap(self):
@@ -585,8 +571,8 @@
latest = newnodes.pop()
if latest not in bheads:
continue
- minbhrev = self[bheads[0]].node()
- reachable = self.changelog.reachable(latest, minbhrev)
+ minbhnode = self[bheads[0]].node()
+ reachable = self.changelog.reachable(latest, minbhnode)
reachable.remove(latest)
if reachable:
bheads = [b for b in bheads if b not in reachable]
@@ -605,10 +591,11 @@
def known(self, nodes):
nm = self.changelog.nodemap
+ pc = self._phasecache
result = []
for n in nodes:
r = nm.get(n)
- resp = not (r is None or self._phaserev[r] >= phases.secret)
+ resp = not (r is None or pc.phase(self, r) >= phases.secret)
result.append(resp)
return result
@@ -864,7 +851,6 @@
pass
delcache('_tagscache')
- delcache('_phaserev')
self._branchcache = None # in UTF-8
self._branchcachetip = None
@@ -934,9 +920,8 @@
def unlock():
self.store.write()
- if self._dirtyphases:
- phases.writeroots(self)
- self._dirtyphases = False
+ if '_phasecache' in vars(self):
+ self._phasecache.write()
for k, ce in self._filecache.items():
if k == 'dirstate':
continue
@@ -1192,7 +1177,8 @@
p1, p2 = self.dirstate.parents()
hookp1, hookp2 = hex(p1), (p2 != nullid and hex(p2) or '')
try:
- self.hook("precommit", throw=True, parent1=hookp1, parent2=hookp2)
+ self.hook("precommit", throw=True, parent1=hookp1,
+ parent2=hookp2)
ret = self.commitctx(cctx, True)
except:
if edited:
@@ -1330,7 +1316,8 @@
def status(self, node1='.', node2=None, match=None,
ignored=False, clean=False, unknown=False,
listsubrepos=False):
- """return status of files between two nodes or node and working directory
+ """return status of files between two nodes or node and working
+ directory.
If node1 is None, use the first dirstate parent instead.
If node2 is None, compare node1 with working directory.
@@ -1338,6 +1325,8 @@
def mfmatches(ctx):
mf = ctx.manifest().copy()
+ if match.always():
+ return mf
for fn in mf.keys():
if not match(fn):
del mf[fn]
@@ -1423,10 +1412,11 @@
mf2 = mfmatches(ctx2)
modified, added, clean = [], [], []
+ withflags = mf1.withflags() | mf2.withflags()
for fn in mf2:
if fn in mf1:
if (fn not in deleted and
- (mf1.flags(fn) != mf2.flags(fn) or
+ ((fn in withflags and mf1.flags(fn) != mf2.flags(fn)) or
(mf1[fn] != mf2[fn] and
(mf2[fn] or ctx1[fn].cmp(ctx2[fn]))))):
modified.append(fn)
@@ -1672,7 +1662,8 @@
# http: return remote's addchangegroup() or 0 for error
ret = remote.unbundle(cg, remoteheads, 'push')
else:
- # we return an integer indicating remote head count change
+ # we return an integer indicating remote head count
+ # change
ret = remote.addchangegroup(cg, 'push', self.url())
if ret:
@@ -1698,7 +1689,7 @@
# * missingheads part of comon (::commonheads)
common = set(outgoing.common)
cheads = [node for node in revs if node in common]
- # and
+ # and
# * commonheads parents on missing
revset = self.set('%ln and parents(roots(%ln))',
outgoing.commonheads,
@@ -1904,7 +1895,8 @@
for fname in sorted(changedfiles):
filerevlog = self.file(fname)
if not len(filerevlog):
- raise util.Abort(_("empty or missing revlog for %s") % fname)
+ raise util.Abort(_("empty or missing revlog for %s")
+ % fname)
fstate[0] = fname
fstate[1] = fnodes.pop(fname, {})
@@ -2004,7 +1996,8 @@
for fname in sorted(changedfiles):
filerevlog = self.file(fname)
if not len(filerevlog):
- raise util.Abort(_("empty or missing revlog for %s") % fname)
+ raise util.Abort(_("empty or missing revlog for %s")
+ % fname)
fstate[0] = fname
nodelist = gennodelst(filerevlog)
if nodelist:
@@ -2261,7 +2254,8 @@
(util.bytecount(total_bytes), elapsed,
util.bytecount(total_bytes / elapsed)))
- # new requirements = old non-format requirements + new format-related
+ # new requirements = old non-format requirements +
+ # new format-related
# requirements from the streamed-in repository
requirements.update(set(self.requirements) - self.supportedformats)
self._applyrequirements(requirements)
--- a/mercurial/manifest.py Sun May 13 11:19:48 2012 +0200
+++ b/mercurial/manifest.py Sun May 13 12:52:24 2012 +0200
@@ -19,6 +19,8 @@
self._flags = flags
def flags(self, f):
return self._flags.get(f, "")
+ def withflags(self):
+ return set(self._flags.keys())
def set(self, f, flags):
self._flags[f] = flags
def copy(self):
@@ -124,8 +126,8 @@
addlist[start:end] = array.array('c', content)
else:
del addlist[start:end]
- return "".join(struct.pack(">lll", start, end, len(content)) + content
- for start, end, content in x)
+ return "".join(struct.pack(">lll", start, end, len(content))
+ + content for start, end, content in x)
def checkforbidden(l):
for f in l:
--- a/mercurial/match.py Sun May 13 11:19:48 2012 +0200
+++ b/mercurial/match.py Sun May 13 12:52:24 2012 +0200
@@ -118,6 +118,8 @@
return self._files
def anypats(self):
return self._anypats
+ def always(self):
+ return False
class exact(match):
def __init__(self, root, cwd, files):
@@ -126,6 +128,8 @@
class always(match):
def __init__(self, root, cwd):
match.__init__(self, root, cwd, [])
+ def always(self):
+ return True
class narrowmatcher(match):
"""Adapt a matcher to work on a subdirectory only.
@@ -272,7 +276,7 @@
try:
pat = '(?:%s)' % '|'.join([_regex(k, p, tail) for (k, p) in pats])
if len(pat) > 20000:
- raise OverflowError()
+ raise OverflowError
return pat, re.compile(pat).match
except OverflowError:
# We're using a Python with a tiny regex engine and we
--- a/mercurial/merge.py Sun May 13 11:19:48 2012 +0200
+++ b/mercurial/merge.py Sun May 13 12:52:24 2012 +0200
@@ -363,7 +363,8 @@
removed += 1
elif m == "m": # merge
if f == '.hgsubstate': # subrepo states need updating
- subrepo.submerge(repo, wctx, mctx, wctx.ancestor(mctx), overwrite)
+ subrepo.submerge(repo, wctx, mctx, wctx.ancestor(mctx),
+ overwrite)
continue
f2, fd, flags, move = a[2:]
repo.wopener.audit(fd)
@@ -479,7 +480,8 @@
if f:
repo.dirstate.drop(f)
-def update(repo, node, branchmerge, force, partial, ancestor=None):
+def update(repo, node, branchmerge, force, partial, ancestor=None,
+ mergeancestor=False):
"""
Perform a merge between the working directory and the given node
@@ -487,6 +489,10 @@
branchmerge = whether to merge between branches
force = whether to force branch merging or file overwriting
partial = a function to filter file lists (dirstate not updated)
+ mergeancestor = if false, merging with an ancestor (fast-forward)
+ is only allowed between different named branches. This flag
+ is used by rebase extension as a temporary fix and should be
+ avoided in general.
The table below shows all the behaviors of the update command
given the -c and -C or no options, whether the working directory
@@ -547,7 +553,7 @@
raise util.Abort(_("merging with a working directory ancestor"
" has no effect"))
elif pa == p1:
- if p1.branch() == p2.branch():
+ if not mergeancestor and p1.branch() == p2.branch():
raise util.Abort(_("nothing to merge"),
hint=_("use 'hg update' "
"or check 'hg heads'"))
--- a/mercurial/parsers.c Sun May 13 11:19:48 2012 +0200
+++ b/mercurial/parsers.c Sun May 13 12:52:24 2012 +0200
@@ -13,8 +13,10 @@
#include "util.h"
-static int hexdigit(char c)
+static inline int hexdigit(const char *p, Py_ssize_t off)
{
+ char c = p[off];
+
if (c >= '0' && c <= '9')
return c - '0';
if (c >= 'a' && c <= 'f')
@@ -32,8 +34,8 @@
static PyObject *unhexlify(const char *str, int len)
{
PyObject *ret;
- const char *c;
char *d;
+ int i;
ret = PyBytes_FromStringAndSize(NULL, len / 2);
@@ -42,9 +44,9 @@
d = PyBytes_AsString(ret);
- for (c = str; c < str + len;) {
- int hi = hexdigit(*c++);
- int lo = hexdigit(*c++);
+ for (i = 0; i < len;) {
+ int hi = hexdigit(str, i++);
+ int lo = hexdigit(str, i++);
*d++ = (hi << 4) | lo;
}
@@ -385,7 +387,7 @@
Py_ssize_t length = index_length(self);
const char *data;
- if (pos == length - 1)
+ if (pos == length - 1 || pos == INT_MAX)
return nullid;
if (pos >= length)
@@ -506,13 +508,13 @@
return NULL;
#define istat(__n, __d) \
- if (PyDict_SetItemString(obj, __d, PyInt_FromLong(self->__n)) == -1) \
+ if (PyDict_SetItemString(obj, __d, PyInt_FromSsize_t(self->__n)) == -1) \
goto bail;
if (self->added) {
Py_ssize_t len = PyList_GET_SIZE(self->added);
if (PyDict_SetItemString(obj, "index entries added",
- PyInt_FromLong(len)) == -1)
+ PyInt_FromSsize_t(len)) == -1)
goto bail;
}
@@ -536,7 +538,7 @@
return NULL;
}
-static inline int nt_level(const char *node, int level)
+static inline int nt_level(const char *node, Py_ssize_t level)
{
int v = node[level>>1];
if (!(level & 1))
@@ -544,8 +546,17 @@
return v & 0xf;
}
-static int nt_find(indexObject *self, const char *node, Py_ssize_t nodelen)
+/*
+ * Return values:
+ *
+ * -4: match is ambiguous (multiple candidates)
+ * -2: not found
+ * rest: valid rev
+ */
+static int nt_find(indexObject *self, const char *node, Py_ssize_t nodelen,
+ int hex)
{
+ int (*getnybble)(const char *, Py_ssize_t) = hex ? hexdigit : nt_level;
int level, maxlevel, off;
if (nodelen == 20 && node[0] == '\0' && memcmp(node, nullid, 20) == 0)
@@ -554,27 +565,35 @@
if (self->nt == NULL)
return -2;
- maxlevel = nodelen > 20 ? 40 : ((int)nodelen * 2);
+ if (hex)
+ maxlevel = nodelen > 40 ? 40 : (int)nodelen;
+ else
+ maxlevel = nodelen > 20 ? 40 : ((int)nodelen * 2);
for (level = off = 0; level < maxlevel; level++) {
- int k = nt_level(node, level);
+ int k = getnybble(node, level);
nodetree *n = &self->nt[off];
int v = n->children[k];
if (v < 0) {
const char *n;
+ Py_ssize_t i;
+
v = -v - 1;
n = index_node(self, v);
if (n == NULL)
return -2;
- return memcmp(node, n, nodelen > 20 ? 20 : nodelen)
- ? -2 : v;
+ for (i = level; i < maxlevel; i++)
+ if (getnybble(node, i) != nt_level(n, i))
+ return -2;
+ return v;
}
if (v == 0)
return -2;
off = v;
}
- return -2;
+ /* multiple matches against an ambiguous prefix */
+ return -4;
}
static int nt_new(indexObject *self)
@@ -638,6 +657,26 @@
return -1;
}
+static int nt_init(indexObject *self)
+{
+ if (self->nt == NULL) {
+ self->ntcapacity = self->raw_length < 4
+ ? 4 : self->raw_length / 2;
+ self->nt = calloc(self->ntcapacity, sizeof(nodetree));
+ if (self->nt == NULL) {
+ PyErr_NoMemory();
+ return -1;
+ }
+ self->ntlength = 1;
+ self->ntrev = (int)index_length(self) - 1;
+ self->ntlookups = 1;
+ self->ntmisses = 0;
+ if (nt_insert(self, nullid, INT_MAX) == -1)
+ return -1;
+ }
+ return 0;
+}
+
/*
* Return values:
*
@@ -651,23 +690,12 @@
int rev;
self->ntlookups++;
- rev = nt_find(self, node, nodelen);
+ rev = nt_find(self, node, nodelen, 0);
if (rev >= -1)
return rev;
- if (self->nt == NULL) {
- self->ntcapacity = self->raw_length < 4
- ? 4 : self->raw_length / 2;
- self->nt = calloc(self->ntcapacity, sizeof(nodetree));
- if (self->nt == NULL) {
- PyErr_SetString(PyExc_MemoryError, "out of memory");
- return -3;
- }
- self->ntlength = 1;
- self->ntrev = (int)index_length(self) - 1;
- self->ntlookups = 1;
- self->ntmisses = 0;
- }
+ if (nt_init(self) == -1)
+ return -3;
/*
* For the first handful of lookups, we scan the entire index,
@@ -692,10 +720,14 @@
} else {
for (rev = self->ntrev - 1; rev >= 0; rev--) {
const char *n = index_node(self, rev);
- if (n == NULL)
+ if (n == NULL) {
+ self->ntrev = rev + 1;
return -2;
- if (nt_insert(self, n, rev) == -1)
+ }
+ if (nt_insert(self, n, rev) == -1) {
+ self->ntrev = rev + 1;
return -3;
+ }
if (memcmp(node, n, nodelen > 20 ? 20 : nodelen) == 0) {
break;
}
@@ -763,6 +795,77 @@
return NULL;
}
+static int nt_partialmatch(indexObject *self, const char *node,
+ Py_ssize_t nodelen)
+{
+ int rev;
+
+ if (nt_init(self) == -1)
+ return -3;
+
+ if (self->ntrev > 0) {
+ /* ensure that the radix tree is fully populated */
+ for (rev = self->ntrev - 1; rev >= 0; rev--) {
+ const char *n = index_node(self, rev);
+ if (n == NULL)
+ return -2;
+ if (nt_insert(self, n, rev) == -1)
+ return -3;
+ }
+ self->ntrev = rev;
+ }
+
+ return nt_find(self, node, nodelen, 1);
+}
+
+static PyObject *index_partialmatch(indexObject *self, PyObject *args)
+{
+ const char *fullnode;
+ int nodelen;
+ char *node;
+ int rev, i;
+
+ if (!PyArg_ParseTuple(args, "s#", &node, &nodelen))
+ return NULL;
+
+ if (nodelen < 4) {
+ PyErr_SetString(PyExc_ValueError, "key too short");
+ return NULL;
+ }
+
+ if (nodelen > 40)
+ nodelen = 40;
+
+ for (i = 0; i < nodelen; i++)
+ hexdigit(node, i);
+ if (PyErr_Occurred()) {
+ /* input contains non-hex characters */
+ PyErr_Clear();
+ Py_RETURN_NONE;
+ }
+
+ rev = nt_partialmatch(self, node, nodelen);
+
+ switch (rev) {
+ case -4:
+ raise_revlog_error();
+ case -3:
+ return NULL;
+ case -2:
+ Py_RETURN_NONE;
+ case -1:
+ return PyString_FromStringAndSize(nullid, 20);
+ }
+
+ fullnode = index_node(self, rev);
+ if (fullnode == NULL) {
+ PyErr_Format(PyExc_IndexError,
+ "could not access rev %d", rev);
+ return NULL;
+ }
+ return PyString_FromStringAndSize(fullnode, 20);
+}
+
static PyObject *index_m_get(indexObject *self, PyObject *args)
{
Py_ssize_t nodelen;
@@ -1045,6 +1148,8 @@
"get an index entry"},
{"insert", (PyCFunction)index_insert, METH_VARARGS,
"insert an index entry"},
+ {"partialmatch", (PyCFunction)index_partialmatch, METH_VARARGS,
+ "match a potentially ambiguous node ID"},
{"stats", (PyCFunction)index_stats, METH_NOARGS,
"stats for the index"},
{NULL} /* Sentinel */
--- a/mercurial/patch.py Sun May 13 11:19:48 2012 +0200
+++ b/mercurial/patch.py Sun May 13 12:52:24 2012 +0200
@@ -534,7 +534,7 @@
if fname in self.data:
return self.data[fname]
if not self.opener or fname not in self.files:
- raise IOError()
+ raise IOError
fn, mode, copied = self.files[fname]
return self.opener.read(fn), mode, copied
@@ -560,7 +560,7 @@
try:
fctx = self.ctx[fname]
except error.LookupError:
- raise IOError()
+ raise IOError
flags = fctx.flags()
return fctx.data(), ('l' in flags, 'x' in flags)
@@ -858,7 +858,8 @@
self.lenb = int(self.lenb)
self.starta = int(self.starta)
self.startb = int(self.startb)
- diffhelpers.addlines(lr, self.hunk, self.lena, self.lenb, self.a, self.b)
+ diffhelpers.addlines(lr, self.hunk, self.lena, self.lenb, self.a,
+ self.b)
# if we hit eof before finishing out the hunk, the last line will
# be zero length. Lets try to fix it up.
while len(self.hunk[-1]) == 0:
@@ -1040,12 +1041,13 @@
hunk.append(l)
return l.rstrip('\r\n')
- line = getline(lr, self.hunk)
- while line and not line.startswith('literal '):
+ while True:
line = getline(lr, self.hunk)
- if not line:
- raise PatchError(_('could not extract "%s" binary data')
- % self._fname)
+ if not line:
+ raise PatchError(_('could not extract "%s" binary data')
+ % self._fname)
+ if line.startswith('literal '):
+ break
size = int(line[8:].rstrip())
dec = []
line = getline(lr, self.hunk)
@@ -1619,13 +1621,14 @@
if opts.git or opts.upgrade:
copy = copies.pathcopies(ctx1, ctx2)
- difffn = lambda opts, losedata: trydiff(repo, revs, ctx1, ctx2,
- modified, added, removed, copy, getfilectx, opts, losedata, prefix)
+ difffn = (lambda opts, losedata:
+ trydiff(repo, revs, ctx1, ctx2, modified, added, removed,
+ copy, getfilectx, opts, losedata, prefix))
if opts.upgrade and not opts.git:
try:
def losedata(fn):
if not losedatafn or not losedatafn(fn=fn):
- raise GitDiffRequired()
+ raise GitDiffRequired
# Buffer the whole output until we are sure it can be generated
return list(difffn(opts.copy(git=False), losedata))
except GitDiffRequired:
@@ -1656,7 +1659,7 @@
if line.startswith('@'):
head = False
else:
- if line and not line[0] in ' +-@\\':
+ if line and line[0] not in ' +-@\\':
head = True
stripline = line
if not head and line and line[0] in '+-':
@@ -1861,7 +1864,8 @@
countwidth, count, pluses, minuses))
if stats:
- output.append(_(' %d files changed, %d insertions(+), %d deletions(-)\n')
+ output.append(_(' %d files changed, %d insertions(+), '
+ '%d deletions(-)\n')
% (len(stats), totaladds, totalremoves))
return ''.join(output)
--- a/mercurial/phases.py Sun May 13 11:19:48 2012 +0200
+++ b/mercurial/phases.py Sun May 13 12:52:24 2012 +0200
@@ -99,60 +99,165 @@
"""
import errno
-from node import nullid, bin, hex, short
+from node import nullid, nullrev, bin, hex, short
from i18n import _
+import util
allphases = public, draft, secret = range(3)
trackedphases = allphases[1:]
phasenames = ['public', 'draft', 'secret']
-def readroots(repo):
- """Read phase roots from disk"""
+def _filterunknown(ui, changelog, phaseroots):
+ """remove unknown nodes from the phase boundary
+
+ Nothing is lost as unknown nodes only hold data for their descendants
+ """
+ updated = False
+ nodemap = changelog.nodemap # to filter unknown nodes
+ for phase, nodes in enumerate(phaseroots):
+ missing = [node for node in nodes if node not in nodemap]
+ if missing:
+ for mnode in missing:
+ ui.debug(
+ 'removing unknown node %s from %i-phase boundary\n'
+ % (short(mnode), phase))
+ nodes.symmetric_difference_update(missing)
+ updated = True
+ return updated
+
+def _readroots(repo, phasedefaults=None):
+ """Read phase roots from disk
+
+ phasedefaults is a list of fn(repo, roots) callable, which are
+ executed if the phase roots file does not exist. When phases are
+ being initialized on an existing repository, this could be used to
+ set selected changesets phase to something else than public.
+
+ Return (roots, dirty) where dirty is true if roots differ from
+ what is being stored.
+ """
+ dirty = False
roots = [set() for i in allphases]
try:
f = repo.sopener('phaseroots')
try:
for line in f:
- phase, nh = line.strip().split()
+ phase, nh = line.split()
roots[int(phase)].add(bin(nh))
finally:
f.close()
except IOError, inst:
if inst.errno != errno.ENOENT:
raise
- for f in repo._phasedefaults:
- roots = f(repo, roots)
- repo._dirtyphases = True
- return roots
+ if phasedefaults:
+ for f in phasedefaults:
+ roots = f(repo, roots)
+ dirty = True
+ if _filterunknown(repo.ui, repo.changelog, roots):
+ dirty = True
+ return roots, dirty
+
+class phasecache(object):
+ def __init__(self, repo, phasedefaults, _load=True):
+ if _load:
+ # Cheap trick to allow shallow-copy without copy module
+ self.phaseroots, self.dirty = _readroots(repo, phasedefaults)
+ self.opener = repo.sopener
+ self._phaserevs = None
+
+ def copy(self):
+ # Shallow copy meant to ensure isolation in
+ # advance/retractboundary(), nothing more.
+ ph = phasecache(None, None, _load=False)
+ ph.phaseroots = self.phaseroots[:]
+ ph.dirty = self.dirty
+ ph.opener = self.opener
+ ph._phaserevs = self._phaserevs
+ return ph
-def writeroots(repo):
- """Write phase roots from disk"""
- f = repo.sopener('phaseroots', 'w', atomictemp=True)
- try:
- for phase, roots in enumerate(repo._phaseroots):
- for h in roots:
- f.write('%i %s\n' % (phase, hex(h)))
- repo._dirtyphases = False
- finally:
- f.close()
+ def replace(self, phcache):
+ for a in 'phaseroots dirty opener _phaserevs'.split():
+ setattr(self, a, getattr(phcache, a))
+
+ def getphaserevs(self, repo, rebuild=False):
+ if rebuild or self._phaserevs is None:
+ revs = [public] * len(repo.changelog)
+ for phase in trackedphases:
+ roots = map(repo.changelog.rev, self.phaseroots[phase])
+ if roots:
+ for rev in roots:
+ revs[rev] = phase
+ for rev in repo.changelog.descendants(*roots):
+ revs[rev] = phase
+ self._phaserevs = revs
+ return self._phaserevs
+
+ def phase(self, repo, rev):
+ # We need a repo argument here to be able to build _phaserev
+ # if necessary. The repository instance is not stored in
+ # phasecache to avoid reference cycles. The changelog instance
+ # is not stored because it is a filecache() property and can
+ # be replaced without us being notified.
+ if rev == nullrev:
+ return public
+ if self._phaserevs is None or rev >= len(self._phaserevs):
+ self._phaserevs = self.getphaserevs(repo, rebuild=True)
+ return self._phaserevs[rev]
-def filterunknown(repo, phaseroots=None):
- """remove unknown nodes from the phase boundary
+ def write(self):
+ if not self.dirty:
+ return
+ f = self.opener('phaseroots', 'w', atomictemp=True)
+ try:
+ for phase, roots in enumerate(self.phaseroots):
+ for h in roots:
+ f.write('%i %s\n' % (phase, hex(h)))
+ finally:
+ f.close()
+ self.dirty = False
+
+ def _updateroots(self, phase, newroots):
+ self.phaseroots[phase] = newroots
+ self._phaserevs = None
+ self.dirty = True
+
+ def advanceboundary(self, repo, targetphase, nodes):
+ # Be careful to preserve shallow-copied values: do not update
+ # phaseroots values, replace them.
- no data is lost as unknown node only old data for their descentants
- """
- if phaseroots is None:
- phaseroots = repo._phaseroots
- nodemap = repo.changelog.nodemap # to filter unknown nodes
- for phase, nodes in enumerate(phaseroots):
- missing = [node for node in nodes if node not in nodemap]
- if missing:
- for mnode in missing:
- repo.ui.debug(
- 'removing unknown node %s from %i-phase boundary\n'
- % (short(mnode), phase))
- nodes.symmetric_difference_update(missing)
- repo._dirtyphases = True
+ delroots = [] # set of root deleted by this path
+ for phase in xrange(targetphase + 1, len(allphases)):
+ # filter nodes that are not in a compatible phase already
+ nodes = [n for n in nodes
+ if self.phase(repo, repo[n].rev()) >= phase]
+ if not nodes:
+ break # no roots to move anymore
+ olds = self.phaseroots[phase]
+ roots = set(ctx.node() for ctx in repo.set(
+ 'roots((%ln::) - (%ln::%ln))', olds, olds, nodes))
+ if olds != roots:
+ self._updateroots(phase, roots)
+ # some roots may need to be declared for lower phases
+ delroots.extend(olds - roots)
+ # declare deleted root in the target phase
+ if targetphase != 0:
+ self.retractboundary(repo, targetphase, delroots)
+
+ def retractboundary(self, repo, targetphase, nodes):
+ # Be careful to preserve shallow-copied values: do not update
+ # phaseroots values, replace them.
+
+ currentroots = self.phaseroots[targetphase]
+ newroots = [n for n in nodes
+ if self.phase(repo, repo[n].rev()) < targetphase]
+ if newroots:
+ if nullid in newroots:
+ raise util.Abort(_('cannot change null revision phase'))
+ currentroots = currentroots.copy()
+ currentroots.update(newroots)
+ ctxs = repo.set('roots(%ln::)', currentroots)
+ currentroots.intersection_update(ctx.node() for ctx in ctxs)
+ self._updateroots(targetphase, currentroots)
def advanceboundary(repo, targetphase, nodes):
"""Add nodes to a phase changing other nodes phases if necessary.
@@ -161,30 +266,9 @@
in the target phase or kept in a *lower* phase.
Simplify boundary to contains phase roots only."""
- delroots = [] # set of root deleted by this path
- for phase in xrange(targetphase + 1, len(allphases)):
- # filter nodes that are not in a compatible phase already
- # XXX rev phase cache might have been invalidated by a previous loop
- # XXX we need to be smarter here
- nodes = [n for n in nodes if repo[n].phase() >= phase]
- if not nodes:
- break # no roots to move anymore
- roots = repo._phaseroots[phase]
- olds = roots.copy()
- ctxs = list(repo.set('roots((%ln::) - (%ln::%ln))', olds, olds, nodes))
- roots.clear()
- roots.update(ctx.node() for ctx in ctxs)
- if olds != roots:
- # invalidate cache (we probably could be smarter here
- if '_phaserev' in vars(repo):
- del repo._phaserev
- repo._dirtyphases = True
- # some roots may need to be declared for lower phases
- delroots.extend(olds - roots)
- # declare deleted root in the target phase
- if targetphase != 0:
- retractboundary(repo, targetphase, delroots)
-
+ phcache = repo._phasecache.copy()
+ phcache.advanceboundary(repo, targetphase, nodes)
+ repo._phasecache.replace(phcache)
def retractboundary(repo, targetphase, nodes):
"""Set nodes back to a phase changing other nodes phases if necessary.
@@ -193,22 +277,15 @@
in the target phase or kept in a *higher* phase.
Simplify boundary to contains phase roots only."""
- currentroots = repo._phaseroots[targetphase]
- newroots = [n for n in nodes if repo[n].phase() < targetphase]
- if newroots:
- currentroots.update(newroots)
- ctxs = repo.set('roots(%ln::)', currentroots)
- currentroots.intersection_update(ctx.node() for ctx in ctxs)
- if '_phaserev' in vars(repo):
- del repo._phaserev
- repo._dirtyphases = True
-
+ phcache = repo._phasecache.copy()
+ phcache.retractboundary(repo, targetphase, nodes)
+ repo._phasecache.replace(phcache)
def listphases(repo):
"""List phases root for serialisation over pushkey"""
keys = {}
value = '%i' % draft
- for root in repo._phaseroots[draft]:
+ for root in repo._phasecache.phaseroots[draft]:
keys[hex(root)] = value
if repo.ui.configbool('phases', 'publish', True):
@@ -251,7 +328,7 @@
def visibleheads(repo):
"""return the set of visible head of this repo"""
# XXX we want a cache on this
- sroots = repo._phaseroots[secret]
+ sroots = repo._phasecache.phaseroots[secret]
if sroots:
# XXX very slow revset. storing heads or secret "boundary" would help.
revset = repo.set('heads(not (%ln::))', sroots)
@@ -267,7 +344,7 @@
"""return a branchmap for the visible set"""
# XXX Recomputing this data on the fly is very slow. We should build a
# XXX cached version while computin the standard branchmap version.
- sroots = repo._phaseroots[secret]
+ sroots = repo._phasecache.phaseroots[secret]
if sroots:
vbranchmap = {}
for branch, nodes in repo.branchmap().iteritems():
--- a/mercurial/pure/mpatch.py Sun May 13 11:19:48 2012 +0200
+++ b/mercurial/pure/mpatch.py Sun May 13 12:52:24 2012 +0200
@@ -85,10 +85,10 @@
p1, p2, l = struct.unpack(">lll", m.read(12))
pull(new, frags, p1 - last) # what didn't change
pull([], frags, p2 - p1) # what got deleted
- new.append((l, pos + 12)) # what got added
+ new.append((l, pos + 12)) # what got added
pos += l + 12
last = p2
- frags.extend(reversed(new)) # what was left at the end
+ frags.extend(reversed(new)) # what was left at the end
t = collect(b2, frags)
--- a/mercurial/pure/osutil.py Sun May 13 11:19:48 2012 +0200
+++ b/mercurial/pure/osutil.py Sun May 13 12:52:24 2012 +0200
@@ -119,7 +119,7 @@
flags = _O_TEXT
m0 = mode[0]
- if m0 == 'r' and not '+' in mode:
+ if m0 == 'r' and '+' not in mode:
flags |= _O_RDONLY
access = _GENERIC_READ
else:
--- a/mercurial/repair.py Sun May 13 11:19:48 2012 +0200
+++ b/mercurial/repair.py Sun May 13 12:52:24 2012 +0200
@@ -6,7 +6,7 @@
# This software may be used and distributed according to the terms of the
# GNU General Public License version 2 or any later version.
-from mercurial import changegroup, bookmarks, phases
+from mercurial import changegroup, bookmarks
from mercurial.node import short
from mercurial.i18n import _
import os
@@ -38,14 +38,14 @@
"""return the changesets which will be broken by the truncation"""
s = set()
def collectone(revlog):
- links = (revlog.linkrev(i) for i in revlog)
+ linkgen = (revlog.linkrev(i) for i in revlog)
# find the truncation point of the revlog
- for lrev in links:
+ for lrev in linkgen:
if lrev >= striprev:
break
# see if any revision after this point has a linkrev
# less than striprev (those will be broken by strip)
- for lrev in links:
+ for lrev in linkgen:
if lrev < striprev:
s.add(lrev)
@@ -170,7 +170,3 @@
raise
repo.destroyed()
-
- # remove potential unknown phase
- # XXX using to_strip data would be faster
- phases.filterunknown(repo)
--- a/mercurial/revlog.py Sun May 13 11:19:48 2012 +0200
+++ b/mercurial/revlog.py Sun May 13 12:52:24 2012 +0200
@@ -756,6 +756,15 @@
pass
def _partialmatch(self, id):
+ try:
+ return self.index.partialmatch(id)
+ except RevlogError:
+ # parsers.c radix tree lookup gave multiple matches
+ raise LookupError(id, self.indexfile, _("ambiguous identifier"))
+ except (AttributeError, ValueError):
+ # we are pure python, or key was too short to search radix tree
+ pass
+
if id in self._pcache:
return self._pcache[id]
@@ -1199,7 +1208,7 @@
continue
for p in (p1, p2):
- if not p in self.nodemap:
+ if p not in self.nodemap:
raise LookupError(p, self.indexfile,
_('unknown parent'))
--- a/mercurial/revset.py Sun May 13 11:19:48 2012 +0200
+++ b/mercurial/revset.py Sun May 13 12:52:24 2012 +0200
@@ -108,7 +108,8 @@
pos += 1
else:
raise error.ParseError(_("unterminated string"), s)
- elif c.isalnum() or c in '._' or ord(c) > 127: # gather up a symbol/keyword
+ # gather up a symbol/keyword
+ elif c.isalnum() or c in '._' or ord(c) > 127:
s = pos
pos += 1
while pos < l: # find end of symbol
@@ -257,7 +258,8 @@
def ancestorspec(repo, subset, x, n):
"""``set~n``
- Changesets that are the Nth ancestor (first parents only) of a changeset in set.
+ Changesets that are the Nth ancestor (first parents only) of a changeset
+ in set.
"""
try:
n = int(n[1])
@@ -289,6 +291,7 @@
- ``pruned`` : csets that are goods, bads or skipped
- ``untested`` : csets whose fate is yet unknown
- ``ignored`` : csets ignored due to DAG topology
+ - ``current`` : the cset currently being bisected
"""
status = getstring(x, _("bisect requires a string")).lower()
state = set(hbisect.get(repo, status))
@@ -462,7 +465,26 @@
"""``draft()``
Changeset in draft phase."""
getargs(x, 0, 0, _("draft takes no arguments"))
- return [r for r in subset if repo._phaserev[r] == phases.draft]
+ pc = repo._phasecache
+ return [r for r in subset if pc.phase(repo, r) == phases.draft]
+
+def extra(repo, subset, x):
+ """``extra(label, [value])``
+ Changesets with the given label in the extra metadata, with the given
+ optional value."""
+
+ l = getargs(x, 1, 2, _('extra takes at least 1 and at most 2 arguments'))
+ label = getstring(l[0], _('first argument to extra must be a string'))
+ value = None
+
+ if len(l) > 1:
+ value = getstring(l[1], _('second argument to extra must be a string'))
+
+ def _matchvalue(r):
+ extra = repo[r].extra()
+ return label in extra and (value is None or value == extra[label])
+
+ return [r for r in subset if _matchvalue(r)]
def filelog(repo, subset, x):
"""``filelog(pattern)``
@@ -851,7 +873,8 @@
"""``public()``
Changeset in public phase."""
getargs(x, 0, 0, _("public takes no arguments"))
- return [r for r in subset if repo._phaserev[r] == phases.public]
+ pc = repo._phasecache
+ return [r for r in subset if pc.phase(repo, r) == phases.public]
def remote(repo, subset, x):
"""``remote([id [,path]])``
@@ -1030,7 +1053,8 @@
"""``secret()``
Changeset in secret phase."""
getargs(x, 0, 0, _("secret takes no arguments"))
- return [r for r in subset if repo._phaserev[r] == phases.secret]
+ pc = repo._phasecache
+ return [r for r in subset if pc.phase(repo, r) == phases.secret]
def sort(repo, subset, x):
"""``sort(set[, [-]key...])``
@@ -1143,6 +1167,7 @@
"descendants": descendants,
"_firstdescendants": _firstdescendants,
"draft": draft,
+ "extra": extra,
"file": hasfile,
"filelog": filelog,
"first": first,
--- a/mercurial/scmutil.py Sun May 13 11:19:48 2012 +0200
+++ b/mercurial/scmutil.py Sun May 13 12:52:24 2012 +0200
@@ -141,8 +141,9 @@
elif (stat.S_ISDIR(st.st_mode) and
os.path.isdir(os.path.join(curpath, '.hg'))):
if not self.callback or not self.callback(curpath):
- raise util.Abort(_("path '%s' is inside nested repo %r") %
- (path, prefix))
+ raise util.Abort(_("path '%s' is inside nested "
+ "repo %r")
+ % (path, prefix))
prefixes.append(normprefix)
parts.pop()
normparts.pop()
@@ -654,8 +655,9 @@
unknown.append(abs)
if repo.ui.verbose or not exact:
repo.ui.status(_('adding %s\n') % ((pats and rel) or abs))
- elif repo.dirstate[abs] != 'r' and (not good or not os.path.lexists(target)
- or (os.path.isdir(target) and not os.path.islink(target))):
+ elif (repo.dirstate[abs] != 'r' and
+ (not good or not os.path.lexists(target) or
+ (os.path.isdir(target) and not os.path.islink(target)))):
deleted.append(abs)
if repo.ui.verbose or not exact:
repo.ui.status(_('removing %s\n') % ((pats and rel) or abs))
@@ -764,8 +766,9 @@
missings.append(r)
missings.sort()
if missings:
- raise error.RequirementError(_("unknown repository format: "
- "requires features '%s' (upgrade Mercurial)") % "', '".join(missings))
+ raise error.RequirementError(
+ _("unknown repository format: requires features '%s' (upgrade "
+ "Mercurial)") % "', '".join(missings))
return requirements
class filecacheentry(object):
--- a/mercurial/setdiscovery.py Sun May 13 11:19:48 2012 +0200
+++ b/mercurial/setdiscovery.py Sun May 13 12:52:24 2012 +0200
@@ -134,11 +134,16 @@
return (ownheadhashes, True, srvheadhashes,)
# full blown discovery
- undecided = dag.nodeset() # own nodes where I don't know if remote knows them
- common = set() # own nodes I know we both know
- missing = set() # own nodes I know remote lacks
- # treat remote heads (and maybe own heads) as a first implicit sample response
+ # own nodes where I don't know if remote knows them
+ undecided = dag.nodeset()
+ # own nodes I know we both know
+ common = set()
+ # own nodes I know remote lacks
+ missing = set()
+
+ # treat remote heads (and maybe own heads) as a first implicit sample
+ # response
common.update(dag.ancestorset(srvheads))
undecided.difference_update(common)
--- a/mercurial/similar.py Sun May 13 11:19:48 2012 +0200
+++ b/mercurial/similar.py Sun May 13 12:52:24 2012 +0200
@@ -44,7 +44,8 @@
'''
copies = {}
for i, r in enumerate(removed):
- repo.ui.progress(_('searching for similar files'), i, total=len(removed))
+ repo.ui.progress(_('searching for similar files'), i,
+ total=len(removed))
# lazily load text
@util.cachefunc
--- a/mercurial/simplemerge.py Sun May 13 11:19:48 2012 +0200
+++ b/mercurial/simplemerge.py Sun May 13 12:52:24 2012 +0200
@@ -94,7 +94,7 @@
elif self.a[0].endswith('\r'):
newline = '\r'
if base_marker and reprocess:
- raise CantReprocessAndShowBase()
+ raise CantReprocessAndShowBase
if name_a:
start_marker = start_marker + ' ' + name_a
if name_b:
@@ -222,7 +222,8 @@
# section a[0:ia] has been disposed of, etc
iz = ia = ib = 0
- for zmatch, zend, amatch, aend, bmatch, bend in self.find_sync_regions():
+ for region in self.find_sync_regions():
+ zmatch, zend, amatch, aend, bmatch, bend = region
#print 'match base [%d:%d]' % (zmatch, zend)
matchlen = zend - zmatch
--- a/mercurial/sshrepo.py Sun May 13 11:19:48 2012 +0200
+++ b/mercurial/sshrepo.py Sun May 13 12:52:24 2012 +0200
@@ -29,6 +29,7 @@
def __init__(self, ui, path, create=False):
self._url = path
self.ui = ui
+ self.pipeo = self.pipei = self.pipee = None
u = util.url(path, parsequery=False, parsefragment=False)
if u.scheme != 'ssh' or not u.host or u.path is None:
@@ -86,7 +87,8 @@
lines.append(l)
max_noise -= 1
else:
- self._abort(error.RepoError(_("no suitable response from remote hg")))
+ self._abort(error.RepoError(_('no suitable response from '
+ 'remote hg')))
self.capabilities = set()
for l in reversed(lines):
@@ -110,15 +112,17 @@
raise exception
def cleanup(self):
+ if self.pipeo is None:
+ return
+ self.pipeo.close()
+ self.pipei.close()
try:
- self.pipeo.close()
- self.pipei.close()
# read the error descriptor until EOF
for l in self.pipee:
self.ui.status(_("remote: "), l)
- self.pipee.close()
- except:
+ except (IOError, ValueError):
pass
+ self.pipee.close()
__del__ = cleanup
--- a/mercurial/subrepo.py Sun May 13 11:19:48 2012 +0200
+++ b/mercurial/subrepo.py Sun May 13 12:52:24 2012 +0200
@@ -200,7 +200,8 @@
'use (l)ocal source (%s) or (r)emote source (%s)?\n')
% (subrelpath(sub), local, remote))
else:
- msg = (_(' subrepository sources for %s differ (in checked out version)\n'
+ msg = (_(' subrepository sources for %s differ (in checked out '
+ 'version)\n'
'use (l)ocal source (%s) or (r)emote source (%s)?\n')
% (subrelpath(sub), local, remote))
return ui.promptchoice(msg, (_('&Local'), _('&Remote')), 0)
@@ -498,8 +499,9 @@
% (subrelpath(self), srcurl))
parentrepo = self._repo._subparent
shutil.rmtree(self._repo.path)
- other, self._repo = hg.clone(self._repo._subparent.ui, {}, other,
- self._repo.root, update=False)
+ other, self._repo = hg.clone(self._repo._subparent.ui, {},
+ other, self._repo.root,
+ update=False)
self._initrepo(parentrepo, source, create=True)
else:
self._repo.ui.status(_('pulling subrepo %s from %s\n')
--- a/mercurial/tags.py Sun May 13 11:19:48 2012 +0200
+++ b/mercurial/tags.py Sun May 13 12:52:24 2012 +0200
@@ -181,7 +181,7 @@
for line in cachelines:
if line == "\n":
break
- line = line.rstrip().split()
+ line = line.split()
cacherevs.append(int(line[0]))
headnode = bin(line[1])
cacheheads.append(headnode)
--- a/mercurial/templatefilters.py Sun May 13 11:19:48 2012 +0200
+++ b/mercurial/templatefilters.py Sun May 13 12:52:24 2012 +0200
@@ -260,7 +260,7 @@
>>> person('"Foo Bar <foo@bar>')
'Foo Bar'
"""
- if not '@' in author:
+ if '@' not in author:
return author
f = author.find('<')
if f != -1:
--- a/mercurial/templater.py Sun May 13 11:19:48 2012 +0200
+++ b/mercurial/templater.py Sun May 13 12:52:24 2012 +0200
@@ -312,7 +312,7 @@
def load(self, t):
'''Get the template for the given template name. Use a local cache.'''
- if not t in self.cache:
+ if t not in self.cache:
try:
self.cache[t] = util.readfile(self.map[t][1])
except KeyError, inst:
--- a/mercurial/transaction.py Sun May 13 11:19:48 2012 +0200
+++ b/mercurial/transaction.py Sun May 13 12:52:24 2012 +0200
@@ -164,7 +164,7 @@
_playback(self.journal, self.report, self.opener,
self.entries, False)
self.report(_("rollback completed\n"))
- except:
+ except Exception:
self.report(_("rollback failed - please run hg recover\n"))
finally:
self.journal = None
--- a/mercurial/ui.py Sun May 13 11:19:48 2012 +0200
+++ b/mercurial/ui.py Sun May 13 12:52:24 2012 +0200
@@ -680,7 +680,8 @@
printed.'''
if self.tracebackflag:
if exc:
- traceback.print_exception(exc[0], exc[1], exc[2], file=self.ferr)
+ traceback.print_exception(exc[0], exc[1], exc[2],
+ file=self.ferr)
else:
traceback.print_exc(file=self.ferr)
return self.tracebackflag
--- a/mercurial/url.py Sun May 13 11:19:48 2012 +0200
+++ b/mercurial/url.py Sun May 13 12:52:24 2012 +0200
@@ -377,7 +377,8 @@
keyfile = self.auth['key']
certfile = self.auth['cert']
- conn = httpsconnection(host, port, keyfile, certfile, *args, **kwargs)
+ conn = httpsconnection(host, port, keyfile, certfile, *args,
+ **kwargs)
conn.ui = self.ui
return conn
--- a/mercurial/util.h Sun May 13 11:19:48 2012 +0200
+++ b/mercurial/util.h Sun May 13 12:52:24 2012 +0200
@@ -109,6 +109,7 @@
typedef int Py_ssize_t;
typedef Py_ssize_t (*lenfunc)(PyObject *);
typedef PyObject *(*ssizeargfunc)(PyObject *, Py_ssize_t);
+#define PyInt_FromSsize_t PyInt_FromLong
#if !defined(PY_SSIZE_T_MIN)
#define PY_SSIZE_T_MAX INT_MAX
--- a/mercurial/util.py Sun May 13 11:19:48 2012 +0200
+++ b/mercurial/util.py Sun May 13 12:52:24 2012 +0200
@@ -1079,7 +1079,7 @@
try:
d["d"] = days
return parsedate(date, extendeddateformats, d)[0]
- except:
+ except Abort:
pass
d["d"] = "28"
return parsedate(date, extendeddateformats, d)[0]
--- a/mercurial/verify.py Sun May 13 11:19:48 2012 +0200
+++ b/mercurial/verify.py Sun May 13 12:52:24 2012 +0200
@@ -87,7 +87,7 @@
# attempt to filter down to real linkrevs
linkrevs = [l for l in linkrevs
if lrugetctx(l)[f].filenode() == node]
- except:
+ except Exception:
pass
warn(_(" (expected %s)") % " ".join(map(str, linkrevs)))
lr = None # can't be trusted
@@ -189,7 +189,7 @@
try:
fl = repo.file(f)
lr = min([fl.linkrev(fl.rev(n)) for n in filenodes[f]])
- except:
+ except Exception:
lr = None
err(lr, _("in manifest but not in changeset"), f)
--- a/mercurial/win32.py Sun May 13 11:19:48 2012 +0200
+++ b/mercurial/win32.py Sun May 13 12:52:24 2012 +0200
@@ -305,7 +305,7 @@
buf = ctypes.create_string_buffer(size + 1)
len = _kernel32.GetModuleFileNameA(None, ctypes.byref(buf), size)
if len == 0:
- raise ctypes.WinError()
+ raise ctypes.WinError
elif len == size:
raise ctypes.WinError(_ERROR_INSUFFICIENT_BUFFER)
return buf.value
@@ -315,7 +315,7 @@
size = _DWORD(300)
buf = ctypes.create_string_buffer(size.value + 1)
if not _advapi32.GetUserNameA(ctypes.byref(buf), ctypes.byref(size)):
- raise ctypes.WinError()
+ raise ctypes.WinError
return buf.value
_signalhandler = []
@@ -333,7 +333,7 @@
h = _SIGNAL_HANDLER(handler)
_signalhandler.append(h) # needed to prevent garbage collection
if not _kernel32.SetConsoleCtrlHandler(h, True):
- raise ctypes.WinError()
+ raise ctypes.WinError
def hidewindow():
@@ -396,7 +396,7 @@
None, args, None, None, False, _DETACHED_PROCESS,
env, os.getcwd(), ctypes.byref(si), ctypes.byref(pi))
if not res:
- raise ctypes.WinError()
+ raise ctypes.WinError
return pi.dwProcessId
--- a/mercurial/windows.py Sun May 13 11:19:48 2012 +0200
+++ b/mercurial/windows.py Sun May 13 12:52:24 2012 +0200
@@ -304,7 +304,7 @@
def groupmembers(name):
# Don't support groups on Windows for now
- raise KeyError()
+ raise KeyError
def isexec(f):
return False
--- a/mercurial/wireproto.py Sun May 13 11:19:48 2012 +0200
+++ b/mercurial/wireproto.py Sun May 13 12:52:24 2012 +0200
@@ -24,9 +24,9 @@
class batcher(object):
'''base class for batches of commands submittable in a single request
- All methods invoked on instances of this class are simply queued and return a
- a future for the result. Once you call submit(), all the queued calls are
- performed and the results set in their respective futures.
+ All methods invoked on instances of this class are simply queued and
+ return a a future for the result. Once you call submit(), all the queued
+ calls are performed and the results set in their respective futures.
'''
def __init__(self):
self.calls = []
@@ -51,7 +51,8 @@
class remotebatch(batcher):
'''batches the queued calls; uses as few roundtrips as possible'''
def __init__(self, remote):
- '''remote must support _submitbatch(encbatch) and _submitone(op, encargs)'''
+ '''remote must support _submitbatch(encbatch) and
+ _submitone(op, encargs)'''
batcher.__init__(self)
self.remote = remote
def submit(self):
@@ -97,14 +98,14 @@
encresref = future()
# Return encoded arguments and future:
yield encargs, encresref
- # Assuming the future to be filled with the result from the batched request
- # now. Decode it:
+ # Assuming the future to be filled with the result from the batched
+ # request now. Decode it:
yield decode(encresref.value)
- The decorator returns a function which wraps this coroutine as a plain method,
- but adds the original method as an attribute called "batchable", which is
- used by remotebatch to split the call into separate encoding and decoding
- phases.
+ The decorator returns a function which wraps this coroutine as a plain
+ method, but adds the original method as an attribute called "batchable",
+ which is used by remotebatch to split the call into separate encoding and
+ decoding phases.
'''
def plain(*args, **opts):
batchable = f(*args, **opts)
--- a/setup.py Sun May 13 11:19:48 2012 +0200
+++ b/setup.py Sun May 13 12:52:24 2012 +0200
@@ -23,24 +23,25 @@
try:
import hashlib
sha = hashlib.sha1()
-except:
+except ImportError:
try:
import sha
- except:
+ except ImportError:
raise SystemExit(
"Couldn't import standard hashlib (incomplete Python install).")
try:
import zlib
-except:
+except ImportError:
raise SystemExit(
"Couldn't import standard zlib (incomplete Python install).")
# The base IronPython distribution (as of 2.7.1) doesn't support bz2
isironpython = False
try:
- isironpython = platform.python_implementation().lower().find("ironpython") != -1
-except:
+ isironpython = (platform.python_implementation()
+ .lower().find("ironpython") != -1)
+except AttributeError:
pass
if isironpython:
@@ -48,7 +49,7 @@
else:
try:
import bz2
- except:
+ except ImportError:
raise SystemExit(
"Couldn't import standard bz2 (incomplete Python install).")
@@ -107,7 +108,7 @@
os.dup2(devnull.fileno(), sys.stderr.fileno())
objects = cc.compile([fname], output_dir=tmpdir)
cc.link_executable(objects, os.path.join(tmpdir, "a.out"))
- except:
+ except Exception:
return False
return True
finally:
@@ -211,10 +212,12 @@
# Insert hgbuildmo first so that files in mercurial/locale/ are found
# when build_py is run next.
sub_commands = [('build_mo', None),
- # We also need build_ext before build_py. Otherwise, when 2to3 is called (in
- # build_py), it will not find osutil & friends, thinking that those modules are
- # global and, consequently, making a mess, now that all module imports are
- # global.
+
+ # We also need build_ext before build_py. Otherwise, when 2to3 is
+ # called (in build_py), it will not find osutil & friends,
+ # thinking that those modules are global and, consequently, making
+ # a mess, now that all module imports are global.
+
('build_ext', build.has_ext_modules),
] + build.sub_commands
@@ -292,7 +295,8 @@
self.distribution.ext_modules = []
else:
if not os.path.exists(os.path.join(get_python_inc(), 'Python.h')):
- raise SystemExit("Python headers are required to build Mercurial")
+ raise SystemExit('Python headers are required to build '
+ 'Mercurial')
def find_modules(self):
modules = build_py.find_modules(self)
--- a/tests/hghave Sun May 13 11:19:48 2012 +0200
+++ b/tests/hghave Sun May 13 12:52:24 2012 +0200
@@ -31,14 +31,14 @@
def has_bzr():
try:
import bzrlib
- return bzrlib.__doc__ != None
+ return bzrlib.__doc__ is not None
except ImportError:
return False
def has_bzr114():
try:
import bzrlib
- return (bzrlib.__doc__ != None
+ return (bzrlib.__doc__ is not None
and bzrlib.version_info[:2] >= (1, 14))
except ImportError:
return False
@@ -60,7 +60,7 @@
os.close(fd)
os.remove(path)
return True
- except:
+ except (IOError, OSError):
return False
def has_executablebit():
@@ -93,7 +93,7 @@
try:
s2 = os.stat(p2)
return s2 == s1
- except:
+ except OSError:
return False
finally:
os.remove(path)
@@ -106,7 +106,7 @@
return False
def has_fifo():
- return hasattr(os, "mkfifo")
+ return getattr(os, "mkfifo", None) is not None
def has_cacheable_fs():
from mercurial import util
@@ -165,10 +165,11 @@
return False
def has_p4():
- return matchoutput('p4 -V', r'Rev\. P4/') and matchoutput('p4d -V', r'Rev\. P4D/')
+ return (matchoutput('p4 -V', r'Rev\. P4/') and
+ matchoutput('p4d -V', r'Rev\. P4D/'))
def has_symlink():
- if not hasattr(os, "symlink"):
+ if getattr(os, "symlink", None) is None:
return False
name = tempfile.mktemp(dir=".", prefix='hg-checklink-')
try:
--- a/tests/run-tests.py Sun May 13 11:19:48 2012 +0200
+++ b/tests/run-tests.py Sun May 13 12:52:24 2012 +0200
@@ -860,7 +860,7 @@
tf = open(testpath)
firstline = tf.readline().rstrip()
tf.close()
- except:
+ except IOError:
firstline = ''
lctest = test.lower()
@@ -1187,6 +1187,7 @@
os.environ['http_proxy'] = ''
os.environ['no_proxy'] = ''
os.environ['NO_PROXY'] = ''
+ os.environ['TERM'] = 'xterm'
# unset env related to hooks
for k in os.environ.keys():
--- a/tests/test-bisect.t Sun May 13 11:19:48 2012 +0200
+++ b/tests/test-bisect.t Sun May 13 12:52:24 2012 +0200
@@ -224,6 +224,7 @@
Testing changeset 12:1941b52820a5 (23 changesets remaining, ~4 tests)
1 files updated, 0 files merged, 0 files removed, 0 files unresolved
$ cat .hg/bisect.state
+ current 1941b52820a544549596820a8ae006842b0e2c64
skip 9d7d07bc967ca98ad0600c24953fd289ad5fa991
skip ce8f0998e922c179e80819d5066fbe46e2998784
skip e7fa0811edb063f6319531f0d0a865882138e180
@@ -396,6 +397,12 @@
date: Thu Jan 01 00:00:06 1970 +0000
summary: msg 6
+ $ hg log -r "bisect(current)"
+ changeset: 5:7874a09ea728
+ user: test
+ date: Thu Jan 01 00:00:05 1970 +0000
+ summary: msg 5
+
$ hg log -r "bisect(skip)"
changeset: 1:5cd978ea5149
user: test
@@ -466,3 +473,40 @@
date: Thu Jan 01 00:00:06 1970 +0000
summary: msg 6
+
+
+test bisecting via a command without updating the working dir, and
+ensure that the bisect state file is updated before running a test
+command
+
+ $ hg update null
+ 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
+ $ cat > script.sh <<'EOF'
+ > #!/bin/sh
+ > test -n "$HG_NODE" || (echo HG_NODE missing; exit 127)
+ > current="`hg log -r \"bisect(current)\" --template {node}`"
+ > test "$current" = "$HG_NODE" || (echo current is bad: $current; exit 127)
+ > rev="`hg log -r $HG_NODE --template {rev}`"
+ > test "$rev" -ge 6
+ > EOF
+ $ chmod +x script.sh
+ $ hg bisect -r
+ $ hg bisect --good tip --noupdate
+ $ hg bisect --bad 0 --noupdate
+ Testing changeset 15:e7fa0811edb0 (31 changesets remaining, ~4 tests)
+ $ hg bisect --command "'`pwd`/script.sh' and some params" --noupdate
+ Changeset 15:e7fa0811edb0: good
+ Changeset 7:03750880c6b5: good
+ Changeset 3:b53bea5e2fcb: bad
+ Changeset 5:7874a09ea728: bad
+ Changeset 6:a3d5c6fdf0d3: good
+ The first good revision is:
+ changeset: 6:a3d5c6fdf0d3
+ user: test
+ date: Thu Jan 01 00:00:06 1970 +0000
+ summary: msg 6
+
+
+ensure that we still don't have a working dir
+
+ $ hg parents
--- a/tests/test-bookmarks-pushpull.t Sun May 13 11:19:48 2012 +0200
+++ b/tests/test-bookmarks-pushpull.t Sun May 13 12:52:24 2012 +0200
@@ -29,9 +29,13 @@
adding file changes
added 1 changesets with 1 changes to 1 files
updating bookmark Y
+ adding remote bookmark X
+ adding remote bookmark Z
(run 'hg update' to get a working copy)
$ hg bookmarks
+ X 0:4e3505fd9583
Y 0:4e3505fd9583
+ Z 0:4e3505fd9583
$ hg debugpushkey ../a namespaces
bookmarks
phases
@@ -47,6 +51,7 @@
$ hg bookmark
X 0:4e3505fd9583
Y 0:4e3505fd9583
+ Z 0:4e3505fd9583
export bookmark by name
@@ -111,6 +116,7 @@
$ hg book
* X 1:9b140be10808
Y 0:4e3505fd9583
+ Z 0:4e3505fd9583
foo -1:000000000000
foobar 1:9b140be10808
@@ -122,11 +128,13 @@
adding file changes
added 1 changesets with 1 changes to 1 files (+1 heads)
divergent bookmark X stored as X@foo
+ updating bookmark Z
(run 'hg heads' to see heads, 'hg merge' to merge)
$ hg book
* X 1:9b140be10808
X@foo 2:0d2164f0ce0d
Y 0:4e3505fd9583
+ Z 2:0d2164f0ce0d
foo -1:000000000000
foobar 1:9b140be10808
$ hg push -f ../a
@@ -159,13 +167,15 @@
namespaces
$ hg debugpushkey http://localhost:$HGPORT/ bookmarks
Y 4e3505fd95835d721066b76e75dbb8cc554d7f77
- X 9b140be1080824d768c5a4691a564088eede71f9
+ foobar 9b140be1080824d768c5a4691a564088eede71f9
+ Z 0d2164f0ce0d8f1d6f94351eba04b794909be66c
foo 0000000000000000000000000000000000000000
- foobar 9b140be1080824d768c5a4691a564088eede71f9
+ X 9b140be1080824d768c5a4691a564088eede71f9
$ hg out -B http://localhost:$HGPORT/
comparing with http://localhost:$HGPORT/
searching for changed bookmarks
- Z 0d2164f0ce0d
+ no changed bookmarks found
+ [1]
$ hg push -B Z http://localhost:$HGPORT/
pushing to http://localhost:$HGPORT/
searching for changes
@@ -182,6 +192,9 @@
$ hg pull -B Z http://localhost:$HGPORT/
pulling from http://localhost:$HGPORT/
no changes found
+ adding remote bookmark foobar
+ adding remote bookmark Z
+ adding remote bookmark foo
divergent bookmark X stored as X@1
importing bookmark Z
$ hg clone http://localhost:$HGPORT/ cloned-bookmarks
--- a/tests/test-branches.t Sun May 13 11:19:48 2012 +0200
+++ b/tests/test-branches.t Sun May 13 12:52:24 2012 +0200
@@ -241,6 +241,11 @@
default 0:19709c5a4e75 (inactive)
$ hg branches -a
a branch name much longer than the default justification used by branches 7:10ff5895aa57
+ $ hg branches -q
+ a branch name much longer than the default justification used by branches
+ c
+ a
+ default
$ hg heads b
no open branch heads found on branches b
[1]
--- a/tests/test-check-code-hg.t Sun May 13 11:19:48 2012 +0200
+++ b/tests/test-check-code-hg.t Sun May 13 12:52:24 2012 +0200
@@ -8,63 +8,9 @@
$ hg manifest | xargs "$check_code" || echo 'FAILURE IS NOT AN OPTION!!!'
$ hg manifest | xargs "$check_code" --warnings --nolineno --per-file=0 || true
- contrib/check-code.py:0:
- > # (r'^\s+[^_ \n][^_. \n]+_[^_\n]+\s*=', "don't use underbars in identifiers"),
- warning: line over 80 characters
- contrib/perf.py:0:
- > except:
- warning: naked except clause
- contrib/perf.py:0:
- > #timer(lambda: sum(map(len, repo.dirstate.status(m, [], False, False, False))))
- warning: line over 80 characters
- contrib/perf.py:0:
- > except:
- warning: naked except clause
- contrib/setup3k.py:0:
- > except:
- warning: naked except clause
- contrib/setup3k.py:0:
- > except:
- warning: naked except clause
- contrib/setup3k.py:0:
- > except:
- warning: naked except clause
- warning: naked except clause
- warning: naked except clause
contrib/shrink-revlog.py:0:
> except:
warning: naked except clause
- doc/gendoc.py:0:
- > "together with Mercurial. Help for other extensions is available "
- warning: line over 80 characters
- hgext/bugzilla.py:0:
- > raise util.Abort(_('cannot find bugzilla user id for %s or %s') %
- warning: line over 80 characters
- hgext/bugzilla.py:0:
- > bzdir = self.ui.config('bugzilla', 'bzdir', '/var/www/html/bugzilla')
- warning: line over 80 characters
- hgext/convert/__init__.py:0:
- > ('', 'ancestors', '', _('show current changeset in ancestor branches')),
- warning: line over 80 characters
- hgext/convert/bzr.py:0:
- > except:
- warning: naked except clause
- hgext/convert/common.py:0:
- > except:
- warning: naked except clause
- hgext/convert/common.py:0:
- > except:
- warning: naked except clause
- warning: naked except clause
- hgext/convert/convcmd.py:0:
- > except:
- warning: naked except clause
- hgext/convert/cvs.py:0:
- > # /1 :pserver:user@example.com:2401/cvsroot/foo Ah<Z
- warning: line over 80 characters
- hgext/convert/cvsps.py:0:
- > assert len(branches) == 1, 'unknown branch: %s' % e.mergepoint
- warning: line over 80 characters
hgext/convert/cvsps.py:0:
> ui.write('Ancestors: %s\n' % (','.join(r)))
warning: unwrapped ui message
@@ -75,9 +21,6 @@
> ui.write('Parents: %s\n' %
warning: unwrapped ui message
hgext/convert/cvsps.py:0:
- > except:
- warning: naked except clause
- hgext/convert/cvsps.py:0:
> ui.write('Branchpoints: %s \n' % ', '.join(branchpoints))
warning: unwrapped ui message
hgext/convert/cvsps.py:0:
@@ -101,59 +44,6 @@
hgext/convert/cvsps.py:0:
> ui.write('Tag%s: %s \n' % (['', 's'][len(cs.tags) > 1],
warning: unwrapped ui message
- hgext/convert/git.py:0:
- > except:
- warning: naked except clause
- hgext/convert/git.py:0:
- > fh = self.gitopen('git diff-tree --name-only --root -r %s "%s^%s" --'
- warning: line over 80 characters
- hgext/convert/hg.py:0:
- > # detect missing revlogs and abort on errors or populate self.ignored
- warning: line over 80 characters
- hgext/convert/hg.py:0:
- > except:
- warning: naked except clause
- warning: naked except clause
- hgext/convert/hg.py:0:
- > except:
- warning: naked except clause
- hgext/convert/monotone.py:0:
- > except:
- warning: naked except clause
- hgext/convert/monotone.py:0:
- > except:
- warning: naked except clause
- hgext/convert/subversion.py:0:
- > raise util.Abort(_('svn: branch has no revision %s') % to_revnum)
- warning: line over 80 characters
- hgext/convert/subversion.py:0:
- > except:
- warning: naked except clause
- hgext/convert/subversion.py:0:
- > args = [self.baseurl, relpaths, start, end, limit, discover_changed_paths,
- warning: line over 80 characters
- hgext/convert/subversion.py:0:
- > self.trunkname = self.ui.config('convert', 'svn.trunk', 'trunk').strip('/')
- warning: line over 80 characters
- hgext/convert/subversion.py:0:
- > except:
- warning: naked except clause
- hgext/convert/subversion.py:0:
- > def get_log_child(fp, url, paths, start, end, limit=0, discover_changed_paths=True,
- warning: line over 80 characters
- hgext/eol.py:0:
- > if ui.configbool('eol', 'fix-trailing-newline', False) and s and s[-1] != '\n':
- warning: line over 80 characters
- warning: line over 80 characters
- hgext/gpg.py:0:
- > except:
- warning: naked except clause
- hgext/hgcia.py:0:
- > except:
- warning: naked except clause
- hgext/hgk.py:0:
- > ui.write("%s%s\n" % (prefix, description.replace('\n', nlprefix).strip()))
- warning: line over 80 characters
hgext/hgk.py:0:
> ui.write("parent %s\n" % p)
warning: unwrapped ui message
@@ -173,40 +63,14 @@
> ui.write("revision %d\n" % ctx.rev())
warning: unwrapped ui message
hgext/hgk.py:0:
- > ui.write("tree %s\n" % short(ctx.changeset()[0])) # use ctx.node() instead ??
- warning: line over 80 characters
+ > ui.write("tree %s\n" % short(ctx.changeset()[0]))
warning: unwrapped ui message
- hgext/highlight/__init__.py:0:
- > extensions.wrapfunction(webcommands, '_filerevision', filerevision_highlight)
- warning: line over 80 characters
- hgext/highlight/__init__.py:0:
- > return ['/* pygments_style = %s */\n\n' % pg_style, fmter.get_style_defs('')]
- warning: line over 80 characters
- hgext/inotify/__init__.py:0:
- > if self._inotifyon and not ignored and not subrepos and not self._dirty:
- warning: line over 80 characters
- hgext/inotify/server.py:0:
- > except:
- warning: naked except clause
- hgext/inotify/server.py:0:
- > except:
- warning: naked except clause
hgext/keyword.py:0:
> ui.note("hg ci -m '%s'\n" % msg)
warning: unwrapped ui message
hgext/mq.py:0:
- > raise util.Abort(_("cannot push --exact with applied patches"))
- warning: line over 80 characters
- hgext/mq.py:0:
- > raise util.Abort(_("cannot use --exact and --move together"))
- warning: line over 80 characters
- hgext/mq.py:0:
- > self.ui.warn(_('Tag %s overrides mq patch of the same name\n')
- warning: line over 80 characters
- hgext/mq.py:0:
> except:
warning: naked except clause
- warning: naked except clause
hgext/mq.py:0:
> except:
warning: naked except clause
@@ -214,72 +78,14 @@
warning: naked except clause
warning: naked except clause
hgext/mq.py:0:
- > raise util.Abort(_('cannot mix -l/--list with options or arguments'))
- warning: line over 80 characters
- hgext/mq.py:0:
- > raise util.Abort(_('qfold cannot fold already applied patch %s') % p)
- warning: line over 80 characters
- hgext/mq.py:0:
- > ('U', 'noupdate', None, _('do not update the new working directories')),
- warning: line over 80 characters
- hgext/mq.py:0:
- > ('e', 'exact', None, _('apply the target patch to its recorded parent')),
- warning: line over 80 characters
- hgext/mq.py:0:
- > except:
- warning: naked except clause
- hgext/mq.py:0:
> ui.write("mq: %s\n" % ', '.join(m))
warning: unwrapped ui message
- hgext/mq.py:0:
- > repo.mq.qseries(repo, missing=opts.get('missing'), summary=opts.get('summary'))
- warning: line over 80 characters
- hgext/notify.py:0:
- > ui.note(_('notify: suppressing notification for merge %d:%s\n') %
- warning: line over 80 characters
- hgext/patchbomb.py:0:
- > binnode, seqno=idx, total=total)
- warning: line over 80 characters
- hgext/patchbomb.py:0:
- > except:
- warning: naked except clause
hgext/patchbomb.py:0:
> ui.write('Subject: %s\n' % subj)
warning: unwrapped ui message
hgext/patchbomb.py:0:
- > p = mail.mimetextpatch('\n'.join(patchlines), 'x-patch', opts.get('test'))
- warning: line over 80 characters
- hgext/patchbomb.py:0:
> ui.write('From: %s\n' % sender)
warning: unwrapped ui message
- hgext/record.py:0:
- > ignoreblanklines=opts.get('ignore_blank_lines'))
- warning: line over 80 characters
- hgext/record.py:0:
- > ignorewsamount=opts.get('ignore_space_change'),
- warning: line over 80 characters
- hgext/zeroconf/__init__.py:0:
- > publish(name, desc, path, util.getport(u.config("web", "port", 8000)))
- warning: line over 80 characters
- hgext/zeroconf/__init__.py:0:
- > except:
- warning: naked except clause
- warning: naked except clause
- mercurial/bundlerepo.py:0:
- > is a bundlerepo for the obtained bundle when the original "other" is remote.
- warning: line over 80 characters
- mercurial/bundlerepo.py:0:
- > "local" is a local repo from which to obtain the actual incoming changesets; it
- warning: line over 80 characters
- mercurial/bundlerepo.py:0:
- > tmp = discovery.findcommonincoming(repo, other, heads=onlyheads, force=force)
- warning: line over 80 characters
- mercurial/commands.py:0:
- > " size " + basehdr + " link p1 p2 nodeid\n")
- warning: line over 80 characters
- mercurial/commands.py:0:
- > raise util.Abort('cannot use localheads with old style discovery')
- warning: line over 80 characters
mercurial/commands.py:0:
> ui.note('branch %s\n' % data)
warning: unwrapped ui message
@@ -293,18 +99,6 @@
> ui.write("unpruned common: %s\n" % " ".join([short(n)
warning: unwrapped ui message
mercurial/commands.py:0:
- > yield 'n', (r, list(set(p for p in cl.parentrevs(r) if p != -1)))
- warning: line over 80 characters
- mercurial/commands.py:0:
- > yield 'n', (r, list(set(p for p in rlog.parentrevs(r) if p != -1)))
- warning: line over 80 characters
- mercurial/commands.py:0:
- > except:
- warning: naked except clause
- mercurial/commands.py:0:
- > ui.status(_("(run 'hg heads .' to see heads, 'hg merge' to merge)\n"))
- warning: line over 80 characters
- mercurial/commands.py:0:
> ui.write("format: id, p1, p2, cset, delta base, len(delta)\n")
warning: unwrapped ui message
mercurial/commands.py:0:
@@ -314,17 +108,7 @@
> ui.write("remote is subset\n")
warning: unwrapped ui message
mercurial/commands.py:0:
- > ui.write(' other : ' + fmt2 % pcfmt(numoprev, numprev))
- warning: line over 80 characters
- mercurial/commands.py:0:
- > ui.write(' where prev = p1 : ' + fmt2 % pcfmt(nump1prev, numprev))
- warning: line over 80 characters
- mercurial/commands.py:0:
- > ui.write(' where prev = p2 : ' + fmt2 % pcfmt(nump2prev, numprev))
- warning: line over 80 characters
- mercurial/commands.py:0:
- > ui.write('deltas against other : ' + fmt % pcfmt(numother, numdeltas))
- warning: line over 80 characters
+ > ui.write('deltas against other : ' + fmt % pcfmt(numother,
warning: unwrapped ui message
mercurial/commands.py:0:
> ui.write('deltas against p1 : ' + fmt % pcfmt(nump1, numdeltas))
@@ -336,9 +120,6 @@
> except:
warning: naked except clause
mercurial/commands.py:0:
- > revs, checkout = hg.addbranchrevs(repo, other, branches, opts.get('rev'))
- warning: line over 80 characters
- mercurial/commands.py:0:
> ui.write("common heads: %s\n" % " ".join([short(n) for n in common]))
warning: unwrapped ui message
mercurial/commands.py:0:
@@ -354,12 +135,6 @@
> ui.write('uncompressed data size (min/max/avg) : %d / %d / %d\n'
warning: unwrapped ui message
mercurial/commands.py:0:
- > Every ID must be a full-length hex node id string. Returns a list of 0s and 1s
- warning: line over 80 characters
- mercurial/commands.py:0:
- > remoteurl, branches = hg.parseurl(ui.expandpath(remoteurl), opts.get('branch'))
- warning: line over 80 characters
- mercurial/commands.py:0:
> ui.write("digraph G {\n")
warning: unwrapped ui message
mercurial/commands.py:0:
@@ -402,229 +177,52 @@
mercurial/commands.py:0:
> ui.write('symlink: %s\n' % (util.checklink(path) and 'yes' or 'no'))
warning: unwrapped ui message
- mercurial/commandserver.py:0:
- > # the ui here is really the repo ui so take its baseui so we don't end up
- warning: line over 80 characters
- mercurial/context.py:0:
- > return self._manifestdelta[path], self._manifestdelta.flags(path)
- warning: line over 80 characters
- mercurial/dagparser.py:0:
- > raise util.Abort(_("invalid character in dag description: %s...") % s)
- warning: line over 80 characters
- mercurial/dagparser.py:0:
- > >>> dagtext([('n', (0, [-1])), ('C', 'my command line'), ('n', (1, [0]))])
- warning: line over 80 characters
- mercurial/dirstate.py:0:
- > if not st is None and not getkind(st.st_mode) in (regkind, lnkkind):
- warning: line over 80 characters
- mercurial/discovery.py:0:
- > If onlyheads is given, only nodes ancestral to nodes in onlyheads (inclusive)
- warning: line over 80 characters
- mercurial/discovery.py:0:
- > def findcommonoutgoing(repo, other, onlyheads=None, force=False, commoninc=None):
- warning: line over 80 characters
- mercurial/dispatch.py:0:
- > " (.hg not found)") % os.getcwd())
- warning: line over 80 characters
mercurial/dispatch.py:0:
> except:
warning: naked except clause
mercurial/dispatch.py:0:
- > return lambda: runcommand(lui, None, cmd, args[:1], ui, options, d, [], {})
- warning: line over 80 characters
- mercurial/dispatch.py:0:
- > def __init__(self, args, ui=None, repo=None, fin=None, fout=None, ferr=None):
- warning: line over 80 characters
- mercurial/dispatch.py:0:
> except:
warning: naked except clause
mercurial/hg.py:0:
> except:
warning: naked except clause
- mercurial/hgweb/hgweb_mod.py:0:
- > self.maxshortchanges = int(self.config("web", "maxshortchanges", 60))
- warning: line over 80 characters
mercurial/keepalive.py:0:
> except:
warning: naked except clause
- mercurial/keepalive.py:0:
- > except:
- warning: naked except clause
- mercurial/localrepo.py:0:
- > # we return an integer indicating remote head count change
- warning: line over 80 characters
- mercurial/localrepo.py:0:
- > raise util.Abort(_("empty or missing revlog for %s") % fname)
- warning: line over 80 characters
- warning: line over 80 characters
- mercurial/localrepo.py:0:
- > if self._tagscache.tagtypes and name in self._tagscache.tagtypes:
- warning: line over 80 characters
- mercurial/localrepo.py:0:
- > self.hook("precommit", throw=True, parent1=hookp1, parent2=hookp2)
- warning: line over 80 characters
- mercurial/localrepo.py:0:
- > # new requirements = old non-format requirements + new format-related
- warning: line over 80 characters
mercurial/localrepo.py:0:
> except:
warning: naked except clause
- mercurial/localrepo.py:0:
- > """return status of files between two nodes or node and working directory
- warning: line over 80 characters
- mercurial/localrepo.py:0:
- > '''Returns a tagscache object that contains various tags related caches.'''
- warning: line over 80 characters
- mercurial/manifest.py:0:
- > return "".join(struct.pack(">lll", start, end, len(content)) + content
- warning: line over 80 characters
- mercurial/merge.py:0:
- > subrepo.submerge(repo, wctx, mctx, wctx.ancestor(mctx), overwrite)
- warning: line over 80 characters
- mercurial/patch.py:0:
- > modified, added, removed, copy, getfilectx, opts, losedata, prefix)
- warning: line over 80 characters
- mercurial/patch.py:0:
- > diffhelpers.addlines(lr, self.hunk, self.lena, self.lenb, self.a, self.b)
- warning: line over 80 characters
- mercurial/patch.py:0:
- > output.append(_(' %d files changed, %d insertions(+), %d deletions(-)\n')
- warning: line over 80 characters
mercurial/patch.py:0:
> except:
warning: naked except clause
- mercurial/pure/mpatch.py:0:
- > frags.extend(reversed(new)) # what was left at the end
- warning: line over 80 characters
mercurial/repair.py:0:
> except:
warning: naked except clause
mercurial/repair.py:0:
> except:
warning: naked except clause
- mercurial/revset.py:0:
- > elif c.isalnum() or c in '._' or ord(c) > 127: # gather up a symbol/keyword
- warning: line over 80 characters
- mercurial/revset.py:0:
- > Changesets that are the Nth ancestor (first parents only) of a changeset in set.
- warning: line over 80 characters
- mercurial/scmutil.py:0:
- > raise util.Abort(_("path '%s' is inside nested repo %r") %
- warning: line over 80 characters
- mercurial/scmutil.py:0:
- > "requires features '%s' (upgrade Mercurial)") % "', '".join(missings))
- warning: line over 80 characters
- mercurial/scmutil.py:0:
- > elif repo.dirstate[abs] != 'r' and (not good or not os.path.lexists(target)
- warning: line over 80 characters
- mercurial/setdiscovery.py:0:
- > # treat remote heads (and maybe own heads) as a first implicit sample response
- warning: line over 80 characters
- mercurial/setdiscovery.py:0:
- > undecided = dag.nodeset() # own nodes where I don't know if remote knows them
- warning: line over 80 characters
- mercurial/similar.py:0:
- > repo.ui.progress(_('searching for similar files'), i, total=len(removed))
- warning: line over 80 characters
- mercurial/simplemerge.py:0:
- > for zmatch, zend, amatch, aend, bmatch, bend in self.find_sync_regions():
- warning: line over 80 characters
- mercurial/sshrepo.py:0:
- > self._abort(error.RepoError(_("no suitable response from remote hg")))
- warning: line over 80 characters
- mercurial/sshrepo.py:0:
- > except:
- warning: naked except clause
- mercurial/subrepo.py:0:
- > other, self._repo = hg.clone(self._repo._subparent.ui, {}, other,
- warning: line over 80 characters
- mercurial/subrepo.py:0:
- > msg = (_(' subrepository sources for %s differ (in checked out version)\n'
- warning: line over 80 characters
- mercurial/transaction.py:0:
- > except:
- warning: naked except clause
- mercurial/ui.py:0:
- > traceback.print_exception(exc[0], exc[1], exc[2], file=self.ferr)
- warning: line over 80 characters
- mercurial/url.py:0:
- > conn = httpsconnection(host, port, keyfile, certfile, *args, **kwargs)
- warning: line over 80 characters
- mercurial/util.py:0:
- > except:
- warning: naked except clause
mercurial/util.py:0:
> except:
warning: naked except clause
- mercurial/verify.py:0:
- > except:
- warning: naked except clause
- mercurial/verify.py:0:
- > except:
- warning: naked except clause
- mercurial/wireproto.py:0:
- > # Assuming the future to be filled with the result from the batched request
- warning: line over 80 characters
- mercurial/wireproto.py:0:
- > '''remote must support _submitbatch(encbatch) and _submitone(op, encargs)'''
- warning: line over 80 characters
- mercurial/wireproto.py:0:
- > All methods invoked on instances of this class are simply queued and return a
- warning: line over 80 characters
- mercurial/wireproto.py:0:
- > The decorator returns a function which wraps this coroutine as a plain method,
- warning: line over 80 characters
- setup.py:0:
- > raise SystemExit("Python headers are required to build Mercurial")
- warning: line over 80 characters
- setup.py:0:
- > except:
- warning: naked except clause
- setup.py:0:
- > # build_py), it will not find osutil & friends, thinking that those modules are
- warning: line over 80 characters
- setup.py:0:
- > except:
- warning: naked except clause
- warning: naked except clause
- setup.py:0:
- > isironpython = platform.python_implementation().lower().find("ironpython") != -1
- warning: line over 80 characters
- setup.py:0:
- > except:
- warning: naked except clause
- warning: naked except clause
- warning: naked except clause
tests/autodiff.py:0:
> ui.write('data lost for: %s\n' % fn)
warning: unwrapped ui message
- tests/run-tests.py:0:
- > except:
- warning: naked except clause
- tests/test-commandserver.py:0:
- > 'hooks.pre-identify=python:test-commandserver.hook', 'id'],
- warning: line over 80 characters
- tests/test-commandserver.py:0:
- > # the cached repo local hgrc contains ui.foo=bar, so showconfig should show it
- warning: line over 80 characters
- tests/test-commandserver.py:0:
- > print '%c, %r' % (ch, re.sub('encoding: [a-zA-Z0-9-]+', 'encoding: ***', data))
- warning: line over 80 characters
- tests/test-filecache.py:0:
- > except:
- warning: naked except clause
- tests/test-filecache.py:0:
- > if subprocess.call(['python', '%s/hghave' % os.environ['TESTDIR'], 'cacheable']):
- warning: line over 80 characters
+ tests/test-convert-mtn.t:0:
+ > > function get_passphrase(keypair_id)
+ don't use 'function', use old style
+ tests/test-import-git.t:0:
+ > > Mc\${NkU|\`?^000jF3jhEB
+ ^ must be quoted
+ tests/test-import.t:0:
+ > > diff -Naur proj-orig/foo proj-new/foo
+ don't use 'diff -N'
+ don't use 'diff -N'
+ tests/test-schemes.t:0:
+ > > z = file:\$PWD/
+ don't use $PWD, use `pwd`
tests/test-ui-color.py:0:
> testui.warn('warning\n')
warning: unwrapped ui message
tests/test-ui-color.py:0:
> testui.write('buffered\n')
warning: unwrapped ui message
- tests/test-walkrepo.py:0:
- > print "Found %d repositories when I should have found 2" % (len(reposet),)
- warning: line over 80 characters
- tests/test-walkrepo.py:0:
- > print "Found %d repositories when I should have found 3" % (len(reposet),)
- warning: line over 80 characters
--- a/tests/test-commandserver.py Sun May 13 11:19:48 2012 +0200
+++ b/tests/test-commandserver.py Sun May 13 12:52:24 2012 +0200
@@ -18,7 +18,7 @@
def readchannel(server):
data = server.stdout.read(5)
if not data:
- raise EOFError()
+ raise EOFError
channel, length = struct.unpack('>cI', data)
if channel in 'IL':
return channel, length
@@ -71,7 +71,8 @@
def hellomessage(server):
ch, data = readchannel(server)
# escaping python tests output not supported
- print '%c, %r' % (ch, re.sub('encoding: [a-zA-Z0-9-]+', 'encoding: ***', data))
+ print '%c, %r' % (ch, re.sub('encoding: [a-zA-Z0-9-]+', 'encoding: ***',
+ data))
# run an arbitrary command to make sure the next thing the server sends
# isn't part of the hello message
@@ -142,7 +143,8 @@
is used """
readchannel(server)
- # the cached repo local hgrc contains ui.foo=bar, so showconfig should show it
+ # the cached repo local hgrc contains ui.foo=bar, so showconfig should
+ # show it
runcommand(server, ['showconfig'])
# but not for this repo
@@ -157,7 +159,8 @@
def hookoutput(server):
readchannel(server)
runcommand(server, ['--config',
- 'hooks.pre-identify=python:test-commandserver.hook', 'id'],
+ 'hooks.pre-identify=python:test-commandserver.hook',
+ 'id'],
input=cStringIO.StringIO('some input'))
def outsidechanges(server):
--- a/tests/test-convert-baz Sun May 13 11:19:48 2012 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,79 +0,0 @@
-#!/bin/sh
-
-"$TESTDIR/hghave" baz || exit 80
-
-baz my-id "mercurial <mercurial@selenic.com>"
-
-echo "[extensions]" >> $HGRCPATH
-echo "convert=" >> $HGRCPATH
-echo 'graphlog =' >> $HGRCPATH
-
-echo % create baz archive
-baz make-archive baz@mercurial--convert hg-test-convert-baz
-
-echo % initialize baz repo
-mkdir baz-repo
-cd baz-repo/
-baz init-tree baz@mercurial--convert/baz--test--0
-baz import
-
-echo % create initial files
-echo 'this is a file' > a
-baz add a
-mkdir src
-baz add src
-cd src
-dd count=1 if=/dev/zero of=b > /dev/null 2> /dev/null
-baz add b
-# HACK: hide GNU tar-1.22 "tar: The --preserve option is deprecated, use --preserve-permissions --preserve-order instead"
-baz commit -s "added a file, src and src/b (binary)" 2>&1 | grep -v '^tar'
-
-echo % create link file and modify a
-ln -s ../a a-link
-baz add a-link
-echo 'this a modification to a' >> ../a
-baz commit -s "added link to a and modify a"
-
-echo % create second link and modify b
-ln -s ../a a-link-2
-baz add a-link-2
-dd count=1 seek=1 if=/dev/zero of=b > /dev/null 2> /dev/null
-baz commit -s "added second link and modify b"
-
-echo % b file to link and a-link-2 to regular file
-rm -f a-link-2
-echo 'this is now a regular file' > a-link-2
-ln -sf ../a b
-baz commit -s "file to link and link to file test"
-
-echo % move a-link-2 file and src directory
-cd ..
-baz mv src/a-link-2 c
-baz mv src test
-baz commit -s "move and rename a-link-2 file and src directory"
-
-echo % move and add the moved file again
-echo e > e
-baz add e
-baz commit -s "add e"
-baz mv e f
-echo ee > e
-baz add e
-baz commit -s "move e and recreate it again"
-cd ..
-
-echo % converting baz repo to Mercurial
-hg convert baz-repo baz-repo-hg
-
-baz register-archive -d baz@mercurial--convert
-
-glog()
-{
- hg glog --template '{rev} "{desc|firstline}" files: {files}\n' "$@"
-}
-
-echo % show graph log
-glog -R baz-repo-hg
-hg up -q -R baz-repo-hg
-hg -R baz-repo-hg manifest --debug
-hg -R baz-repo-hg log -r 5 -r 7 -C --debug | grep copies
--- a/tests/test-convert-baz.out Sun May 13 11:19:48 2012 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,96 +0,0 @@
-% create baz archive
-% initialize baz repo
-* creating version baz@mercurial--convert/baz--test--0
-* imported baz@mercurial--convert/baz--test--0
-% create initial files
-* build pristine tree for baz@mercurial--convert/baz--test--0--base-0
-* Scanning for full-tree revision: .
-* from import revision: baz@mercurial--convert/baz--test--0--base-0
-A/ .arch-ids
-A/ src
-A/ src/.arch-ids
-A .arch-ids/a.id
-A a
-A src/.arch-ids/=id
-A src/.arch-ids/b.id
-A src/b
-* update pristine tree (baz@mercurial--convert/baz--test--0--base-0 => baz--test--0--patch-1)
-* committed baz@mercurial--convert/baz--test--0--patch-1
-% create link file and modify a
-A src/.arch-ids/a-link.id
-A src/a-link
-M a
-* update pristine tree (baz@mercurial--convert/baz--test--0--patch-1 => baz--test--0--patch-2)
-* committed baz@mercurial--convert/baz--test--0--patch-2
-% create second link and modify b
-A src/.arch-ids/a-link-2.id
-A src/a-link-2
-Mb src/b
-* update pristine tree (baz@mercurial--convert/baz--test--0--patch-2 => baz--test--0--patch-3)
-* committed baz@mercurial--convert/baz--test--0--patch-3
-% b file to link and a-link-2 to regular file
-fl src/b
-lf src/a-link-2
-* update pristine tree (baz@mercurial--convert/baz--test--0--patch-3 => baz--test--0--patch-4)
-* committed baz@mercurial--convert/baz--test--0--patch-4
-% move a-link-2 file and src directory
-D/ src/.arch-ids
-A/ test/.arch-ids
-/> src test
-=> src/.arch-ids/a-link-2.id .arch-ids/c.id
-=> src/a-link-2 c
-=> src/.arch-ids/=id test/.arch-ids/=id
-=> src/.arch-ids/a-link.id test/.arch-ids/a-link.id
-=> src/.arch-ids/b.id test/.arch-ids/b.id
-* update pristine tree (baz@mercurial--convert/baz--test--0--patch-4 => baz--test--0--patch-5)
-* committed baz@mercurial--convert/baz--test--0--patch-5
-% move and add the moved file again
-A .arch-ids/e.id
-A e
-* update pristine tree (baz@mercurial--convert/baz--test--0--patch-5 => baz--test--0--patch-6)
-* committed baz@mercurial--convert/baz--test--0--patch-6
-A .arch-ids/e.id
-A e
-=> .arch-ids/e.id .arch-ids/f.id
-=> e f
-* update pristine tree (baz@mercurial--convert/baz--test--0--patch-6 => baz--test--0--patch-7)
-* committed baz@mercurial--convert/baz--test--0--patch-7
-% converting baz repo to Mercurial
-initializing destination baz-repo-hg repository
-analyzing tree version baz@mercurial--convert/baz--test--0...
-scanning source...
-sorting...
-converting...
-7 initial import
-6 added a file, src and src/b (binary)
-5 added link to a and modify a
-4 added second link and modify b
-3 file to link and link to file test
-2 move and rename a-link-2 file and src directory
-1 add e
-0 move e and recreate it again
-% show graph log
-o 7 "move e and recreate it again" files: e f
-|
-o 6 "add e" files: e
-|
-o 5 "move and rename a-link-2 file and src directory" files: c src/a-link src/a-link-2 src/b test/a-link test/b
-|
-o 4 "file to link and link to file test" files: src/a-link-2 src/b
-|
-o 3 "added second link and modify b" files: src/a-link-2 src/b
-|
-o 2 "added link to a and modify a" files: a src/a-link
-|
-o 1 "added a file, src and src/b (binary)" files: a src/b
-|
-o 0 "initial import" files:
-
-c4072c4b72e1cabace081888efa148ee80ca3cbb 644 a
-0201ac32a3a8e86e303dff60366382a54b48a72e 644 c
-1a4a864db0073705a11b1439f563bfa4b46d9246 644 e
-09e0222742fc3f75777fa9d68a5d8af7294cb5e7 644 f
-c0067ba5ff0b7c9a3eb17270839d04614c435623 644 @ test/a-link
-375f4263d86feacdea7e3c27100abd1560f2a973 644 @ test/b
-copies: c (src/a-link-2) test/a-link (src/a-link) test/b (src/b)
-copies: f (e)
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/test-convert-baz.t Sun May 13 12:52:24 2012 +0200
@@ -0,0 +1,163 @@
+ $ "$TESTDIR/hghave" baz || exit 80
+
+ $ baz my-id "mercurial <mercurial@selenic.com>"
+
+ $ echo "[extensions]" >> $HGRCPATH
+ $ echo "convert=" >> $HGRCPATH
+ $ echo 'graphlog =' >> $HGRCPATH
+
+create baz archive
+ $ baz make-archive baz@mercurial--convert hg-test-convert-baz
+
+initialize baz repo
+ $ mkdir baz-repo
+ $ cd baz-repo/
+ $ baz init-tree baz@mercurial--convert/baz--test--0
+ $ baz import
+ * creating version baz@mercurial--convert/baz--test--0
+ * imported baz@mercurial--convert/baz--test--0
+
+create initial files
+ $ echo 'this is a file' > a
+ $ baz add a
+ $ mkdir src
+ $ baz add src
+ $ cd src
+ $ dd count=1 if=/dev/zero of=b > /dev/null 2> /dev/null
+ $ baz add b
+HACK: hide GNU tar-1.22 "tar: The --preserve option is deprecated, use --preserve-permissions --preserve-order instead"
+ $ baz commit -s "added a file, src and src/b (binary)" 2>&1 | grep -v '^tar'
+ * build pristine tree for baz@mercurial--convert/baz--test--0--base-0
+ * Scanning for full-tree revision: .
+ * from import revision: baz@mercurial--convert/baz--test--0--base-0
+ A/ .arch-ids
+ A/ src
+ A/ src/.arch-ids
+ A .arch-ids/a.id
+ A a
+ A src/.arch-ids/=id
+ A src/.arch-ids/b.id
+ A src/b
+ * update pristine tree (baz@mercurial--convert/baz--test--0--base-0 => baz--test--0--patch-1)
+ * committed baz@mercurial--convert/baz--test--0--patch-1
+
+create link file and modify a
+ $ ln -s ../a a-link
+ $ baz add a-link
+ $ echo 'this a modification to a' >> ../a
+ $ baz commit -s "added link to a and modify a"
+ A src/.arch-ids/a-link.id
+ A src/a-link
+ M a
+ * update pristine tree (baz@mercurial--convert/baz--test--0--patch-1 => baz--test--0--patch-2)
+ * committed baz@mercurial--convert/baz--test--0--patch-2
+
+create second link and modify b
+ $ ln -s ../a a-link-2
+ $ baz add a-link-2
+ $ dd count=1 seek=1 if=/dev/zero of=b > /dev/null 2> /dev/null
+ $ baz commit -s "added second link and modify b"
+ A src/.arch-ids/a-link-2.id
+ A src/a-link-2
+ Mb src/b
+ * update pristine tree (baz@mercurial--convert/baz--test--0--patch-2 => baz--test--0--patch-3)
+ * committed baz@mercurial--convert/baz--test--0--patch-3
+
+b file to link and a-link-2 to regular file
+ $ rm -f a-link-2
+ $ echo 'this is now a regular file' > a-link-2
+ $ ln -sf ../a b
+ $ baz commit -s "file to link and link to file test"
+ fl src/b
+ lf src/a-link-2
+ * update pristine tree (baz@mercurial--convert/baz--test--0--patch-3 => baz--test--0--patch-4)
+ * committed baz@mercurial--convert/baz--test--0--patch-4
+
+move a-link-2 file and src directory
+ $ cd ..
+ $ baz mv src/a-link-2 c
+ $ baz mv src test
+ $ baz commit -s "move and rename a-link-2 file and src directory"
+ D/ src/.arch-ids
+ A/ test/.arch-ids
+ /> src test
+ => src/.arch-ids/a-link-2.id .arch-ids/c.id
+ => src/a-link-2 c
+ => src/.arch-ids/=id test/.arch-ids/=id
+ => src/.arch-ids/a-link.id test/.arch-ids/a-link.id
+ => src/.arch-ids/b.id test/.arch-ids/b.id
+ * update pristine tree (baz@mercurial--convert/baz--test--0--patch-4 => baz--test--0--patch-5)
+ * committed baz@mercurial--convert/baz--test--0--patch-5
+
+move and add the moved file again
+ $ echo e > e
+ $ baz add e
+ $ baz commit -s "add e"
+ A .arch-ids/e.id
+ A e
+ * update pristine tree (baz@mercurial--convert/baz--test--0--patch-5 => baz--test--0--patch-6)
+ * committed baz@mercurial--convert/baz--test--0--patch-6
+ $ baz mv e f
+ $ echo ee > e
+ $ baz add e
+ $ baz commit -s "move e and recreate it again"
+ A .arch-ids/e.id
+ A e
+ => .arch-ids/e.id .arch-ids/f.id
+ => e f
+ * update pristine tree (baz@mercurial--convert/baz--test--0--patch-6 => baz--test--0--patch-7)
+ * committed baz@mercurial--convert/baz--test--0--patch-7
+ $ cd ..
+
+converting baz repo to Mercurial
+ $ hg convert baz-repo baz-repo-hg
+ initializing destination baz-repo-hg repository
+ analyzing tree version baz@mercurial--convert/baz--test--0...
+ scanning source...
+ sorting...
+ converting...
+ 7 initial import
+ 6 added a file, src and src/b (binary)
+ 5 added link to a and modify a
+ 4 added second link and modify b
+ 3 file to link and link to file test
+ 2 move and rename a-link-2 file and src directory
+ 1 add e
+ 0 move e and recreate it again
+
+ $ baz register-archive -d baz@mercurial--convert
+
+ $ glog()
+ > {
+ > hg glog --template '{rev} "{desc|firstline}" files: {files}\n' "$@"
+ > }
+
+show graph log
+ $ glog -R baz-repo-hg
+ o 7 "move e and recreate it again" files: e f
+ |
+ o 6 "add e" files: e
+ |
+ o 5 "move and rename a-link-2 file and src directory" files: c src/a-link src/a-link-2 src/b test/a-link test/b
+ |
+ o 4 "file to link and link to file test" files: src/a-link-2 src/b
+ |
+ o 3 "added second link and modify b" files: src/a-link-2 src/b
+ |
+ o 2 "added link to a and modify a" files: a src/a-link
+ |
+ o 1 "added a file, src and src/b (binary)" files: a src/b
+ |
+ o 0 "initial import" files:
+
+ $ hg up -q -R baz-repo-hg
+ $ hg -R baz-repo-hg manifest --debug
+ c4072c4b72e1cabace081888efa148ee80ca3cbb 644 a
+ 0201ac32a3a8e86e303dff60366382a54b48a72e 644 c
+ 1a4a864db0073705a11b1439f563bfa4b46d9246 644 e
+ 09e0222742fc3f75777fa9d68a5d8af7294cb5e7 644 f
+ c0067ba5ff0b7c9a3eb17270839d04614c435623 644 @ test/a-link
+ 375f4263d86feacdea7e3c27100abd1560f2a973 644 @ test/b
+ $ hg -R baz-repo-hg log -r 5 -r 7 -C --debug | grep copies
+ copies: c (src/a-link-2) test/a-link (src/a-link) test/b (src/b)
+ copies: f (e)
--- a/tests/test-convert-darcs.t Sun May 13 11:19:48 2012 +0200
+++ b/tests/test-convert-darcs.t Sun May 13 12:52:24 2012 +0200
@@ -32,7 +32,7 @@
branch and update
- $ darcs get darcs-repo darcs-clone >/dev/null
+ $ darcs get -q darcs-repo darcs-clone >/dev/null
$ cd darcs-clone
$ echo c >> a
$ echo c > c
@@ -48,11 +48,10 @@
$ darcs record -a -l -m p1.2
Finished recording patch 'p1.2'
- $ darcs pull -a --no-set-default ../darcs-clone
- Backing up ./a(-darcs-backup0)
+ $ darcs pull -q -a --no-set-default ../darcs-clone
+ Backing up ./a(*) (glob)
We have conflicts in the following files:
./a
- Finished pulling and applying.
$ sleep 1
$ echo e > a
$ echo f > f
--- a/tests/test-convert-p4 Sun May 13 11:19:48 2012 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,75 +0,0 @@
-#!/bin/sh
-
-"$TESTDIR/hghave" p4 || exit 80
-
-echo "[extensions]" >> $HGRCPATH
-echo "convert = " >> $HGRCPATH
-
-echo % create p4 depot
-P4ROOT=`pwd`/depot; export P4ROOT
-P4AUDIT=$P4ROOT/audit; export P4AUDIT
-P4JOURNAL=$P4ROOT/journal; export P4JOURNAL
-P4LOG=$P4ROOT/log; export P4LOG
-P4PORT=localhost:16661; export P4PORT
-P4DEBUG=1; export P4DEBUG
-
-echo % start the p4 server
-[ ! -d $P4ROOT ] && mkdir $P4ROOT
-p4d -f -J off >$P4ROOT/stdout 2>$P4ROOT/stderr &
-trap "echo % stop the p4 server ; p4 admin stop" EXIT
-
-# wait for the server to initialize
-while ! p4 ; do
- sleep 1
-done >/dev/null 2>/dev/null
-
-echo % create a client spec
-P4CLIENT=hg-p4-import; export P4CLIENT
-DEPOTPATH=//depot/test-mercurial-import/...
-p4 client -o | sed '/^View:/,$ d' >p4client
-echo View: >>p4client
-echo " $DEPOTPATH //$P4CLIENT/..." >>p4client
-p4 client -i <p4client
-
-echo % populate the depot
-echo a > a
-mkdir b
-echo c > b/c
-p4 add a b/c
-p4 submit -d initial
-
-echo % change some files
-p4 edit a
-echo aa >> a
-p4 submit -d "change a"
-
-p4 edit b/c
-echo cc >> b/c
-p4 submit -d "change b/c"
-
-echo % convert
-hg convert -s p4 $DEPOTPATH dst
-hg -R dst log --template 'rev={rev} desc="{desc}" tags="{tags}" files="{files}"\n'
-
-echo % change some files
-p4 edit a b/c
-echo aaa >> a
-echo ccc >> b/c
-p4 submit -d "change a b/c"
-
-echo % convert again
-hg convert -s p4 $DEPOTPATH dst
-hg -R dst log --template 'rev={rev} desc="{desc}" tags="{tags}" files="{files}"\n'
-
-echo % interesting names
-echo dddd > "d d"
-mkdir " e"
-echo fff >" e/ f"
-p4 add "d d" " e/ f"
-p4 submit -d "add d e f"
-
-echo % convert again
-hg convert -s p4 $DEPOTPATH dst
-hg -R dst log --template 'rev={rev} desc="{desc}" tags="{tags}" files="{files}"\n'
-
-
--- a/tests/test-convert-p4-filetypes Sun May 13 11:19:48 2012 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,104 +0,0 @@
-#!/bin/sh
-
-"$TESTDIR/hghave" p4 execbit symlink || exit 80
-
-echo "[extensions]" >> $HGRCPATH
-echo "convert = " >> $HGRCPATH
-
-echo % create p4 depot
-P4ROOT=`pwd`/depot; export P4ROOT
-P4AUDIT=$P4ROOT/audit; export P4AUDIT
-P4JOURNAL=$P4ROOT/journal; export P4JOURNAL
-P4LOG=$P4ROOT/log; export P4LOG
-P4PORT=localhost:16661; export P4PORT
-P4DEBUG=1; export P4DEBUG
-P4CHARSET=utf8; export P4CHARSET
-
-echo % start the p4 server
-[ ! -d $P4ROOT ] && mkdir $P4ROOT
-p4d -f -J off -xi >$P4ROOT/stdout 2>$P4ROOT/stderr
-p4d -f -J off >$P4ROOT/stdout 2>$P4ROOT/stderr &
-trap "echo % stop the p4 server ; p4 admin stop" EXIT
-
-# wait for the server to initialize
-while ! p4 ; do
- sleep 1
-done >/dev/null 2>/dev/null
-
-echo % create a client spec
-P4CLIENT=hg-p4-import; export P4CLIENT
-DEPOTPATH=//depot/test-mercurial-import/...
-p4 client -o | sed '/^View:/,$ d' >p4client
-echo View: >>p4client
-echo " $DEPOTPATH //$P4CLIENT/..." >>p4client
-p4 client -i <p4client
-
-echo % populate the depot
-TYPES="text binary symlink"
-TYPES="$TYPES text+m text+w text+x text+k text+kx text+ko text+l text+C text+D text+F text+S text+S2"
-TYPES="$TYPES binary+k binary+x binary+kx symlink+k"
-TYPES="$TYPES ctext cxtext ktext kxtext ltext tempobj ubinary uxbinary xbinary xltext xtempobj xtext"
-# not testing these
-#TYPES="$TYPES apple resource unicode utf16 uresource xunicode xutf16"
-for T in $TYPES ; do
- T2=`echo $T | tr [:upper:] [:lower:]`
- case $T in
- apple)
- ;;
- symlink*)
- echo "this is target $T" >target_$T2
- ln -s target_$T file_$T2
- p4 add target_$T2
- p4 add -t $T file_$T2
- ;;
- binary*)
- python -c "file('file_$T2', 'wb').write('this is $T')"
- p4 add -t $T file_$T2
- ;;
- *)
- echo "this is $T" >file_$T2
- p4 add -t $T file_$T2
- ;;
- esac
-done
-p4 submit -d initial
-
-echo % test keyword expansion
-p4 edit file_* target_*
-for T in $TYPES ; do
- T2=`echo $T | tr [:upper:] [:lower:]`
- echo '$Id$' >>file_$T2
- echo '$Header$' >>file_$T2
- echo '$Date$' >>file_$T2
- echo '$DateTime$' >>file_$T2
- echo '$Change$' >>file_$T2
- echo '$File$' >>file_$T2
- echo '$Revision$' >>file_$T2
- echo '$Header$$Header$Header$' >>file_$T2
-done
-
-ln -s 'target_$Header$' crazy_symlink+k
-p4 add -t symlink+k crazy_symlink+k
-
-p4 submit -d keywords
-
-echo % check keywords in p4
-grep -H Header file_*
-
-echo % convert
-hg convert -s p4 $DEPOTPATH dst
-hg -R dst log --template 'rev={rev} desc="{desc}" tags="{tags}" files="{files}"\n'g
-
-echo % revision 0
-hg -R dst update 0
-head dst/file_* | cat -v
-
-echo
-echo % revision 1
-hg -R dst update 1
-head dst/file_* | cat -v
-echo
-echo % crazy_symlink
-readlink crazy_symlink+k
-readlink dst/crazy_symlink+k
-
--- a/tests/test-convert-p4-filetypes.out Sun May 13 11:19:48 2012 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,642 +0,0 @@
-% create p4 depot
-% start the p4 server
-% create a client spec
-Client hg-p4-import saved.
-% populate the depot
-//depot/test-mercurial-import/file_text#1 - opened for add
-//depot/test-mercurial-import/file_binary#1 - opened for add
-//depot/test-mercurial-import/target_symlink#1 - opened for add
-//depot/test-mercurial-import/file_symlink#1 - opened for add
-//depot/test-mercurial-import/file_text+m#1 - opened for add
-//depot/test-mercurial-import/file_text+w#1 - opened for add
-//depot/test-mercurial-import/file_text+x#1 - opened for add
-//depot/test-mercurial-import/file_text+k#1 - opened for add
-//depot/test-mercurial-import/file_text+kx#1 - opened for add
-//depot/test-mercurial-import/file_text+ko#1 - opened for add
-//depot/test-mercurial-import/file_text+l#1 - opened for add
-//depot/test-mercurial-import/file_text+c#1 - opened for add
-//depot/test-mercurial-import/file_text+d#1 - opened for add
-//depot/test-mercurial-import/file_text+f#1 - opened for add
-//depot/test-mercurial-import/file_text+s#1 - opened for add
-//depot/test-mercurial-import/file_text+s2#1 - opened for add
-//depot/test-mercurial-import/file_binary+k#1 - opened for add
-//depot/test-mercurial-import/file_binary+x#1 - opened for add
-//depot/test-mercurial-import/file_binary+kx#1 - opened for add
-//depot/test-mercurial-import/target_symlink+k#1 - opened for add
-//depot/test-mercurial-import/file_symlink+k#1 - opened for add
-//depot/test-mercurial-import/file_ctext#1 - opened for add
-//depot/test-mercurial-import/file_cxtext#1 - opened for add
-//depot/test-mercurial-import/file_ktext#1 - opened for add
-//depot/test-mercurial-import/file_kxtext#1 - opened for add
-//depot/test-mercurial-import/file_ltext#1 - opened for add
-//depot/test-mercurial-import/file_tempobj#1 - opened for add
-//depot/test-mercurial-import/file_ubinary#1 - opened for add
-//depot/test-mercurial-import/file_uxbinary#1 - opened for add
-//depot/test-mercurial-import/file_xbinary#1 - opened for add
-//depot/test-mercurial-import/file_xltext#1 - opened for add
-//depot/test-mercurial-import/file_xtempobj#1 - opened for add
-//depot/test-mercurial-import/file_xtext#1 - opened for add
-Submitting change 1.
-Locking 33 files ...
-add //depot/test-mercurial-import/file_binary#1
-add //depot/test-mercurial-import/file_binary+k#1
-add //depot/test-mercurial-import/file_binary+kx#1
-add //depot/test-mercurial-import/file_binary+x#1
-add //depot/test-mercurial-import/file_ctext#1
-add //depot/test-mercurial-import/file_cxtext#1
-add //depot/test-mercurial-import/file_ktext#1
-add //depot/test-mercurial-import/file_kxtext#1
-add //depot/test-mercurial-import/file_ltext#1
-add //depot/test-mercurial-import/file_symlink#1
-add //depot/test-mercurial-import/file_symlink+k#1
-add //depot/test-mercurial-import/file_tempobj#1
-add //depot/test-mercurial-import/file_text#1
-add //depot/test-mercurial-import/file_text+c#1
-add //depot/test-mercurial-import/file_text+d#1
-add //depot/test-mercurial-import/file_text+f#1
-add //depot/test-mercurial-import/file_text+k#1
-add //depot/test-mercurial-import/file_text+ko#1
-add //depot/test-mercurial-import/file_text+kx#1
-add //depot/test-mercurial-import/file_text+l#1
-add //depot/test-mercurial-import/file_text+m#1
-add //depot/test-mercurial-import/file_text+s#1
-add //depot/test-mercurial-import/file_text+s2#1
-add //depot/test-mercurial-import/file_text+w#1
-add //depot/test-mercurial-import/file_text+x#1
-add //depot/test-mercurial-import/file_ubinary#1
-add //depot/test-mercurial-import/file_uxbinary#1
-add //depot/test-mercurial-import/file_xbinary#1
-add //depot/test-mercurial-import/file_xltext#1
-add //depot/test-mercurial-import/file_xtempobj#1
-add //depot/test-mercurial-import/file_xtext#1
-add //depot/test-mercurial-import/target_symlink#1
-add //depot/test-mercurial-import/target_symlink+k#1
-Change 1 submitted.
-//depot/test-mercurial-import/file_binary+k#1 - refreshing
-//depot/test-mercurial-import/file_binary+kx#1 - refreshing
-//depot/test-mercurial-import/file_ktext#1 - refreshing
-//depot/test-mercurial-import/file_kxtext#1 - refreshing
-//depot/test-mercurial-import/file_symlink+k#1 - refreshing
-//depot/test-mercurial-import/file_text+k#1 - refreshing
-//depot/test-mercurial-import/file_text+ko#1 - refreshing
-//depot/test-mercurial-import/file_text+kx#1 - refreshing
-% test keyword expansion
-//depot/test-mercurial-import/file_binary#1 - opened for edit
-//depot/test-mercurial-import/file_binary+k#1 - opened for edit
-//depot/test-mercurial-import/file_binary+kx#1 - opened for edit
-//depot/test-mercurial-import/file_binary+x#1 - opened for edit
-//depot/test-mercurial-import/file_ctext#1 - opened for edit
-//depot/test-mercurial-import/file_cxtext#1 - opened for edit
-//depot/test-mercurial-import/file_ktext#1 - opened for edit
-//depot/test-mercurial-import/file_kxtext#1 - opened for edit
-//depot/test-mercurial-import/file_ltext#1 - opened for edit
-//depot/test-mercurial-import/file_symlink#1 - opened for edit
-//depot/test-mercurial-import/file_symlink+k#1 - opened for edit
-//depot/test-mercurial-import/file_tempobj#1 - opened for edit
-//depot/test-mercurial-import/file_text#1 - opened for edit
-//depot/test-mercurial-import/file_text+c#1 - opened for edit
-//depot/test-mercurial-import/file_text+d#1 - opened for edit
-//depot/test-mercurial-import/file_text+f#1 - opened for edit
-//depot/test-mercurial-import/file_text+k#1 - opened for edit
-//depot/test-mercurial-import/file_text+ko#1 - opened for edit
-//depot/test-mercurial-import/file_text+kx#1 - opened for edit
-//depot/test-mercurial-import/file_text+l#1 - opened for edit
-//depot/test-mercurial-import/file_text+m#1 - opened for edit
-//depot/test-mercurial-import/file_text+s#1 - opened for edit
-//depot/test-mercurial-import/file_text+s2#1 - opened for edit
-//depot/test-mercurial-import/file_text+w#1 - opened for edit
-//depot/test-mercurial-import/file_text+x#1 - opened for edit
-//depot/test-mercurial-import/file_ubinary#1 - opened for edit
-//depot/test-mercurial-import/file_uxbinary#1 - opened for edit
-//depot/test-mercurial-import/file_xbinary#1 - opened for edit
-//depot/test-mercurial-import/file_xltext#1 - opened for edit
-//depot/test-mercurial-import/file_xtempobj#1 - opened for edit
-//depot/test-mercurial-import/file_xtext#1 - opened for edit
-//depot/test-mercurial-import/target_symlink#1 - opened for edit
-//depot/test-mercurial-import/target_symlink+k#1 - opened for edit
-//depot/test-mercurial-import/crazy_symlink+k#1 - opened for add
-Submitting change 2.
-Locking 34 files ...
-add //depot/test-mercurial-import/crazy_symlink+k#1
-edit //depot/test-mercurial-import/file_binary#2
-edit //depot/test-mercurial-import/file_binary+k#2
-edit //depot/test-mercurial-import/file_binary+kx#2
-edit //depot/test-mercurial-import/file_binary+x#2
-edit //depot/test-mercurial-import/file_ctext#2
-edit //depot/test-mercurial-import/file_cxtext#2
-edit //depot/test-mercurial-import/file_ktext#2
-edit //depot/test-mercurial-import/file_kxtext#2
-edit //depot/test-mercurial-import/file_ltext#2
-edit //depot/test-mercurial-import/file_symlink#2
-edit //depot/test-mercurial-import/file_symlink+k#2
-edit //depot/test-mercurial-import/file_tempobj#2
-edit //depot/test-mercurial-import/file_text#2
-edit //depot/test-mercurial-import/file_text+c#2
-edit //depot/test-mercurial-import/file_text+d#2
-edit //depot/test-mercurial-import/file_text+f#2
-edit //depot/test-mercurial-import/file_text+k#2
-edit //depot/test-mercurial-import/file_text+ko#2
-edit //depot/test-mercurial-import/file_text+kx#2
-edit //depot/test-mercurial-import/file_text+l#2
-edit //depot/test-mercurial-import/file_text+m#2
-edit //depot/test-mercurial-import/file_text+s#2
-edit //depot/test-mercurial-import/file_text+s2#2
-edit //depot/test-mercurial-import/file_text+w#2
-edit //depot/test-mercurial-import/file_text+x#2
-edit //depot/test-mercurial-import/file_ubinary#2
-edit //depot/test-mercurial-import/file_uxbinary#2
-edit //depot/test-mercurial-import/file_xbinary#2
-edit //depot/test-mercurial-import/file_xltext#2
-edit //depot/test-mercurial-import/file_xtempobj#2
-edit //depot/test-mercurial-import/file_xtext#2
-edit //depot/test-mercurial-import/target_symlink#2
-edit //depot/test-mercurial-import/target_symlink+k#2
-Change 2 submitted.
-//depot/test-mercurial-import/crazy_symlink+k#1 - refreshing
-//depot/test-mercurial-import/file_binary+k#2 - refreshing
-//depot/test-mercurial-import/file_binary+kx#2 - refreshing
-//depot/test-mercurial-import/file_ktext#2 - refreshing
-//depot/test-mercurial-import/file_kxtext#2 - refreshing
-//depot/test-mercurial-import/file_symlink+k#2 - refreshing
-//depot/test-mercurial-import/file_text+k#2 - refreshing
-//depot/test-mercurial-import/file_text+ko#2 - refreshing
-//depot/test-mercurial-import/file_text+kx#2 - refreshing
-% check keywords in p4
-file_binary:$Header$
-file_binary:$Header$$Header$Header$
-file_binary+k:$Header: //depot/test-mercurial-import/file_binary+k#2 $
-file_binary+k:$Header: //depot/test-mercurial-import/file_binary+k#2 $$Header: //depot/test-mercurial-import/file_binary+k#2 $Header$
-file_binary+kx:$Header: //depot/test-mercurial-import/file_binary+kx#2 $
-file_binary+kx:$Header: //depot/test-mercurial-import/file_binary+kx#2 $$Header: //depot/test-mercurial-import/file_binary+kx#2 $Header$
-file_binary+x:$Header$
-file_binary+x:$Header$$Header$Header$
-file_ctext:$Header$
-file_ctext:$Header$$Header$Header$
-file_cxtext:$Header$
-file_cxtext:$Header$$Header$Header$
-file_ktext:$Header: //depot/test-mercurial-import/file_ktext#2 $
-file_ktext:$Header: //depot/test-mercurial-import/file_ktext#2 $$Header: //depot/test-mercurial-import/file_ktext#2 $Header$
-file_kxtext:$Header: //depot/test-mercurial-import/file_kxtext#2 $
-file_kxtext:$Header: //depot/test-mercurial-import/file_kxtext#2 $$Header: //depot/test-mercurial-import/file_kxtext#2 $Header$
-file_ltext:$Header$
-file_ltext:$Header$$Header$Header$
-file_symlink:$Header$
-file_symlink:$Header$$Header$Header$
-file_symlink+k:$Header$
-file_symlink+k:$Header$$Header$Header$
-file_tempobj:$Header$
-file_tempobj:$Header$$Header$Header$
-file_text:$Header$
-file_text:$Header$$Header$Header$
-file_text+c:$Header$
-file_text+c:$Header$$Header$Header$
-file_text+d:$Header$
-file_text+d:$Header$$Header$Header$
-file_text+f:$Header$
-file_text+f:$Header$$Header$Header$
-file_text+k:$Header: //depot/test-mercurial-import/file_text+k#2 $
-file_text+k:$Header: //depot/test-mercurial-import/file_text+k#2 $$Header: //depot/test-mercurial-import/file_text+k#2 $Header$
-file_text+ko:$Header: //depot/test-mercurial-import/file_text+ko#2 $
-file_text+ko:$Header: //depot/test-mercurial-import/file_text+ko#2 $$Header: //depot/test-mercurial-import/file_text+ko#2 $Header$
-file_text+kx:$Header: //depot/test-mercurial-import/file_text+kx#2 $
-file_text+kx:$Header: //depot/test-mercurial-import/file_text+kx#2 $$Header: //depot/test-mercurial-import/file_text+kx#2 $Header$
-file_text+l:$Header$
-file_text+l:$Header$$Header$Header$
-file_text+m:$Header$
-file_text+m:$Header$$Header$Header$
-file_text+s:$Header$
-file_text+s:$Header$$Header$Header$
-file_text+s2:$Header$
-file_text+s2:$Header$$Header$Header$
-file_text+w:$Header$
-file_text+w:$Header$$Header$Header$
-file_text+x:$Header$
-file_text+x:$Header$$Header$Header$
-file_ubinary:$Header$
-file_ubinary:$Header$$Header$Header$
-file_uxbinary:$Header$
-file_uxbinary:$Header$$Header$Header$
-file_xbinary:$Header$
-file_xbinary:$Header$$Header$Header$
-file_xltext:$Header$
-file_xltext:$Header$$Header$Header$
-file_xtempobj:$Header$
-file_xtempobj:$Header$$Header$Header$
-file_xtext:$Header$
-file_xtext:$Header$$Header$Header$
-% convert
-initializing destination dst repository
-reading p4 views
-collecting p4 changelists
-1 initial
-2 keywords
-scanning source...
-sorting...
-converting...
-1 initial
-0 keywords
-rev=1 desc="keywords" tags="tip" files="crazy_symlink+k file_binary file_binary+k file_binary+kx file_binary+x file_ctext file_cxtext file_ktext file_kxtext file_ltext file_text file_text+c file_text+d file_text+f file_text+k file_text+ko file_text+kx file_text+l file_text+m file_text+s file_text+s2 file_text+w file_text+x file_ubinary file_uxbinary file_xbinary file_xltext file_xtext target_symlink target_symlink+k"
-grev=0 desc="initial" tags="" files="file_binary file_binary+k file_binary+kx file_binary+x file_ctext file_cxtext file_ktext file_kxtext file_ltext file_symlink file_symlink+k file_text file_text+c file_text+d file_text+f file_text+k file_text+ko file_text+kx file_text+l file_text+m file_text+s2 file_text+w file_text+x file_ubinary file_uxbinary file_xbinary file_xltext file_xtext target_symlink target_symlink+k"
-g% revision 0
-30 files updated, 0 files merged, 0 files removed, 0 files unresolved
-==> dst/file_binary <==
-this is binary
-==> dst/file_binary+k <==
-this is binary+k
-==> dst/file_binary+kx <==
-this is binary+kx
-==> dst/file_binary+x <==
-this is binary+x
-==> dst/file_ctext <==
-this is ctext
-
-==> dst/file_cxtext <==
-this is cxtext
-
-==> dst/file_ktext <==
-this is ktext
-
-==> dst/file_kxtext <==
-this is kxtext
-
-==> dst/file_ltext <==
-this is ltext
-
-==> dst/file_symlink <==
-this is target symlink
-
-==> dst/file_symlink+k <==
-this is target symlink+k
-
-==> dst/file_text <==
-this is text
-
-==> dst/file_text+c <==
-this is text+C
-
-==> dst/file_text+d <==
-this is text+D
-
-==> dst/file_text+f <==
-this is text+F
-
-==> dst/file_text+k <==
-this is text+k
-
-==> dst/file_text+ko <==
-this is text+ko
-
-==> dst/file_text+kx <==
-this is text+kx
-
-==> dst/file_text+l <==
-this is text+l
-
-==> dst/file_text+m <==
-this is text+m
-
-==> dst/file_text+s2 <==
-this is text+S2
-
-==> dst/file_text+w <==
-this is text+w
-
-==> dst/file_text+x <==
-this is text+x
-
-==> dst/file_ubinary <==
-this is ubinary
-
-==> dst/file_uxbinary <==
-this is uxbinary
-
-==> dst/file_xbinary <==
-this is xbinary
-
-==> dst/file_xltext <==
-this is xltext
-
-==> dst/file_xtext <==
-this is xtext
-
-% revision 1
-30 files updated, 0 files merged, 0 files removed, 0 files unresolved
-==> dst/file_binary <==
-this is binary$Id$
-$Header$
-$Date$
-$DateTime$
-$Change$
-$File$
-$Revision$
-$Header$$Header$Header$
-
-==> dst/file_binary+k <==
-this is binary+k$Id$
-$Header$
-$Date$
-$DateTime$
-$Change$
-$File$
-$Revision$
-$Header$$Header$Header$
-
-==> dst/file_binary+kx <==
-this is binary+kx$Id$
-$Header$
-$Date$
-$DateTime$
-$Change$
-$File$
-$Revision$
-$Header$$Header$Header$
-
-==> dst/file_binary+x <==
-this is binary+x$Id$
-$Header$
-$Date$
-$DateTime$
-$Change$
-$File$
-$Revision$
-$Header$$Header$Header$
-
-==> dst/file_ctext <==
-this is ctext
-$Id$
-$Header$
-$Date$
-$DateTime$
-$Change$
-$File$
-$Revision$
-$Header$$Header$Header$
-
-==> dst/file_cxtext <==
-this is cxtext
-$Id$
-$Header$
-$Date$
-$DateTime$
-$Change$
-$File$
-$Revision$
-$Header$$Header$Header$
-
-==> dst/file_ktext <==
-this is ktext
-$Id$
-$Header$
-$Date$
-$DateTime$
-$Change$
-$File$
-$Revision$
-$Header$$Header$Header$
-
-==> dst/file_kxtext <==
-this is kxtext
-$Id$
-$Header$
-$Date$
-$DateTime$
-$Change$
-$File$
-$Revision$
-$Header$$Header$Header$
-
-==> dst/file_ltext <==
-this is ltext
-$Id$
-$Header$
-$Date$
-$DateTime$
-$Change$
-$File$
-$Revision$
-$Header$$Header$Header$
-
-==> dst/file_symlink <==
-this is target symlink
-$Id$
-$Header$
-$Date$
-$DateTime$
-$Change$
-$File$
-$Revision$
-$Header$$Header$Header$
-
-==> dst/file_symlink+k <==
-this is target symlink+k
-$Id$
-$Header$
-$Date$
-$DateTime$
-$Change$
-$File$
-$Revision$
-$Header$$Header$Header$
-
-==> dst/file_text <==
-this is text
-$Id$
-$Header$
-$Date$
-$DateTime$
-$Change$
-$File$
-$Revision$
-$Header$$Header$Header$
-
-==> dst/file_text+c <==
-this is text+C
-$Id$
-$Header$
-$Date$
-$DateTime$
-$Change$
-$File$
-$Revision$
-$Header$$Header$Header$
-
-==> dst/file_text+d <==
-this is text+D
-$Id$
-$Header$
-$Date$
-$DateTime$
-$Change$
-$File$
-$Revision$
-$Header$$Header$Header$
-
-==> dst/file_text+f <==
-this is text+F
-$Id$
-$Header$
-$Date$
-$DateTime$
-$Change$
-$File$
-$Revision$
-$Header$$Header$Header$
-
-==> dst/file_text+k <==
-this is text+k
-$Id$
-$Header$
-$Date$
-$DateTime$
-$Change$
-$File$
-$Revision$
-$Header$$Header$Header$
-
-==> dst/file_text+ko <==
-this is text+ko
-$Id$
-$Header$
-$Date$
-$DateTime$
-$Change$
-$File$
-$Revision$
-$Header$$Header$Header$
-
-==> dst/file_text+kx <==
-this is text+kx
-$Id$
-$Header$
-$Date$
-$DateTime$
-$Change$
-$File$
-$Revision$
-$Header$$Header$Header$
-
-==> dst/file_text+l <==
-this is text+l
-$Id$
-$Header$
-$Date$
-$DateTime$
-$Change$
-$File$
-$Revision$
-$Header$$Header$Header$
-
-==> dst/file_text+m <==
-this is text+m
-$Id$
-$Header$
-$Date$
-$DateTime$
-$Change$
-$File$
-$Revision$
-$Header$$Header$Header$
-
-==> dst/file_text+s <==
-this is text+S
-$Id$
-$Header$
-$Date$
-$DateTime$
-$Change$
-$File$
-$Revision$
-$Header$$Header$Header$
-
-==> dst/file_text+s2 <==
-this is text+S2
-$Id$
-$Header$
-$Date$
-$DateTime$
-$Change$
-$File$
-$Revision$
-$Header$$Header$Header$
-
-==> dst/file_text+w <==
-this is text+w
-$Id$
-$Header$
-$Date$
-$DateTime$
-$Change$
-$File$
-$Revision$
-$Header$$Header$Header$
-
-==> dst/file_text+x <==
-this is text+x
-$Id$
-$Header$
-$Date$
-$DateTime$
-$Change$
-$File$
-$Revision$
-$Header$$Header$Header$
-
-==> dst/file_ubinary <==
-this is ubinary
-$Id$
-$Header$
-$Date$
-$DateTime$
-$Change$
-$File$
-$Revision$
-$Header$$Header$Header$
-
-==> dst/file_uxbinary <==
-this is uxbinary
-$Id$
-$Header$
-$Date$
-$DateTime$
-$Change$
-$File$
-$Revision$
-$Header$$Header$Header$
-
-==> dst/file_xbinary <==
-this is xbinary
-$Id$
-$Header$
-$Date$
-$DateTime$
-$Change$
-$File$
-$Revision$
-$Header$$Header$Header$
-
-==> dst/file_xltext <==
-this is xltext
-$Id$
-$Header$
-$Date$
-$DateTime$
-$Change$
-$File$
-$Revision$
-$Header$$Header$Header$
-
-==> dst/file_xtext <==
-this is xtext
-$Id$
-$Header$
-$Date$
-$DateTime$
-$Change$
-$File$
-$Revision$
-$Header$$Header$Header$
-
-% crazy_symlink
-target_$Header: //depot/test-mercurial-import/crazy_symlink+k#1 $
-target_$Header$
-% stop the p4 server
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/test-convert-p4-filetypes.t Sun May 13 12:52:24 2012 +0200
@@ -0,0 +1,733 @@
+ $ "$TESTDIR/hghave" p4 execbit symlink || exit 80
+
+ $ echo "[extensions]" >> $HGRCPATH
+ $ echo "convert = " >> $HGRCPATH
+
+create p4 depot
+ $ P4ROOT=`pwd`/depot; export P4ROOT
+ $ P4AUDIT=$P4ROOT/audit; export P4AUDIT
+ $ P4JOURNAL=$P4ROOT/journal; export P4JOURNAL
+ $ P4LOG=$P4ROOT/log; export P4LOG
+ $ P4PORT=localhost:16661; export P4PORT
+ $ P4DEBUG=1; export P4DEBUG
+ $ P4CHARSET=utf8; export P4CHARSET
+
+start the p4 server
+ $ [ ! -d $P4ROOT ] && mkdir $P4ROOT
+ $ p4d -f -J off -xi >$P4ROOT/stdout 2>$P4ROOT/stderr
+ $ p4d -f -J off >$P4ROOT/stdout 2>$P4ROOT/stderr &
+ $ echo $! >> $DAEMON_PIDS
+ $ trap "echo stopping the p4 server ; p4 admin stop" EXIT
+
+wait for the server to initialize
+ $ while ! p4 ; do
+ > sleep 1
+ > done >/dev/null 2>/dev/null
+
+create a client spec
+ $ P4CLIENT=hg-p4-import; export P4CLIENT
+ $ DEPOTPATH=//depot/test-mercurial-import/...
+ $ p4 client -o | sed '/^View:/,$ d' >p4client
+ $ echo View: >>p4client
+ $ echo " $DEPOTPATH //$P4CLIENT/..." >>p4client
+ $ p4 client -i <p4client
+ Client hg-p4-import saved.
+
+populate the depot
+ $ TYPES="text binary symlink"
+ $ TYPES="$TYPES text+m text+w text+x text+k text+kx text+ko text+l text+C text+D text+F text+S text+S2"
+ $ TYPES="$TYPES binary+k binary+x binary+kx symlink+k"
+ $ TYPES="$TYPES ctext cxtext ktext kxtext ltext tempobj ubinary uxbinary xbinary xltext xtempobj xtext"
+not testing these
+ $ #TYPES="$TYPES apple resource unicode utf16 uresource xunicode xutf16"
+ $ for T in $TYPES ; do
+ > T2=`echo $T | tr [:upper:] [:lower:]`
+ > case $T in
+ > apple)
+ > ;;
+ > symlink*)
+ > echo "this is target $T" >target_$T2
+ > ln -s target_$T file_$T2
+ > p4 add target_$T2
+ > p4 add -t $T file_$T2
+ > ;;
+ > binary*)
+ > python -c "file('file_$T2', 'wb').write('this is $T')"
+ > p4 add -t $T file_$T2
+ > ;;
+ > *)
+ > echo "this is $T" >file_$T2
+ > p4 add -t $T file_$T2
+ > ;;
+ > esac
+ > done
+ //depot/test-mercurial-import/file_text#1 - opened for add
+ //depot/test-mercurial-import/file_binary#1 - opened for add
+ //depot/test-mercurial-import/target_symlink#1 - opened for add
+ //depot/test-mercurial-import/file_symlink#1 - opened for add
+ //depot/test-mercurial-import/file_text+m#1 - opened for add
+ //depot/test-mercurial-import/file_text+w#1 - opened for add
+ //depot/test-mercurial-import/file_text+x#1 - opened for add
+ //depot/test-mercurial-import/file_text+k#1 - opened for add
+ //depot/test-mercurial-import/file_text+kx#1 - opened for add
+ //depot/test-mercurial-import/file_text+ko#1 - opened for add
+ //depot/test-mercurial-import/file_text+l#1 - opened for add
+ //depot/test-mercurial-import/file_text+c#1 - opened for add
+ //depot/test-mercurial-import/file_text+d#1 - opened for add
+ //depot/test-mercurial-import/file_text+f#1 - opened for add
+ //depot/test-mercurial-import/file_text+s#1 - opened for add
+ //depot/test-mercurial-import/file_text+s2#1 - opened for add
+ //depot/test-mercurial-import/file_binary+k#1 - opened for add
+ //depot/test-mercurial-import/file_binary+x#1 - opened for add
+ //depot/test-mercurial-import/file_binary+kx#1 - opened for add
+ //depot/test-mercurial-import/target_symlink+k#1 - opened for add
+ //depot/test-mercurial-import/file_symlink+k#1 - opened for add
+ //depot/test-mercurial-import/file_ctext#1 - opened for add
+ //depot/test-mercurial-import/file_cxtext#1 - opened for add
+ //depot/test-mercurial-import/file_ktext#1 - opened for add
+ //depot/test-mercurial-import/file_kxtext#1 - opened for add
+ //depot/test-mercurial-import/file_ltext#1 - opened for add
+ //depot/test-mercurial-import/file_tempobj#1 - opened for add
+ //depot/test-mercurial-import/file_ubinary#1 - opened for add
+ //depot/test-mercurial-import/file_uxbinary#1 - opened for add
+ //depot/test-mercurial-import/file_xbinary#1 - opened for add
+ //depot/test-mercurial-import/file_xltext#1 - opened for add
+ //depot/test-mercurial-import/file_xtempobj#1 - opened for add
+ //depot/test-mercurial-import/file_xtext#1 - opened for add
+ $ p4 submit -d initial
+ Submitting change 1.
+ Locking 33 files ...
+ add //depot/test-mercurial-import/file_binary#1
+ add //depot/test-mercurial-import/file_binary+k#1
+ add //depot/test-mercurial-import/file_binary+kx#1
+ add //depot/test-mercurial-import/file_binary+x#1
+ add //depot/test-mercurial-import/file_ctext#1
+ add //depot/test-mercurial-import/file_cxtext#1
+ add //depot/test-mercurial-import/file_ktext#1
+ add //depot/test-mercurial-import/file_kxtext#1
+ add //depot/test-mercurial-import/file_ltext#1
+ add //depot/test-mercurial-import/file_symlink#1
+ add //depot/test-mercurial-import/file_symlink+k#1
+ add //depot/test-mercurial-import/file_tempobj#1
+ add //depot/test-mercurial-import/file_text#1
+ add //depot/test-mercurial-import/file_text+c#1
+ add //depot/test-mercurial-import/file_text+d#1
+ add //depot/test-mercurial-import/file_text+f#1
+ add //depot/test-mercurial-import/file_text+k#1
+ add //depot/test-mercurial-import/file_text+ko#1
+ add //depot/test-mercurial-import/file_text+kx#1
+ add //depot/test-mercurial-import/file_text+l#1
+ add //depot/test-mercurial-import/file_text+m#1
+ add //depot/test-mercurial-import/file_text+s#1
+ add //depot/test-mercurial-import/file_text+s2#1
+ add //depot/test-mercurial-import/file_text+w#1
+ add //depot/test-mercurial-import/file_text+x#1
+ add //depot/test-mercurial-import/file_ubinary#1
+ add //depot/test-mercurial-import/file_uxbinary#1
+ add //depot/test-mercurial-import/file_xbinary#1
+ add //depot/test-mercurial-import/file_xltext#1
+ add //depot/test-mercurial-import/file_xtempobj#1
+ add //depot/test-mercurial-import/file_xtext#1
+ add //depot/test-mercurial-import/target_symlink#1
+ add //depot/test-mercurial-import/target_symlink+k#1
+ Change 1 submitted.
+ //depot/test-mercurial-import/file_binary+k#1 - refreshing
+ //depot/test-mercurial-import/file_binary+kx#1 - refreshing
+ //depot/test-mercurial-import/file_ktext#1 - refreshing
+ //depot/test-mercurial-import/file_kxtext#1 - refreshing
+ //depot/test-mercurial-import/file_symlink+k#1 - refreshing
+ //depot/test-mercurial-import/file_text+k#1 - refreshing
+ //depot/test-mercurial-import/file_text+ko#1 - refreshing
+ //depot/test-mercurial-import/file_text+kx#1 - refreshing
+
+test keyword expansion
+ $ p4 edit file_* target_*
+ //depot/test-mercurial-import/file_binary#1 - opened for edit
+ //depot/test-mercurial-import/file_binary+k#1 - opened for edit
+ //depot/test-mercurial-import/file_binary+kx#1 - opened for edit
+ //depot/test-mercurial-import/file_binary+x#1 - opened for edit
+ //depot/test-mercurial-import/file_ctext#1 - opened for edit
+ //depot/test-mercurial-import/file_cxtext#1 - opened for edit
+ //depot/test-mercurial-import/file_ktext#1 - opened for edit
+ //depot/test-mercurial-import/file_kxtext#1 - opened for edit
+ //depot/test-mercurial-import/file_ltext#1 - opened for edit
+ //depot/test-mercurial-import/file_symlink#1 - opened for edit
+ //depot/test-mercurial-import/file_symlink+k#1 - opened for edit
+ //depot/test-mercurial-import/file_tempobj#1 - opened for edit
+ //depot/test-mercurial-import/file_text#1 - opened for edit
+ //depot/test-mercurial-import/file_text+c#1 - opened for edit
+ //depot/test-mercurial-import/file_text+d#1 - opened for edit
+ //depot/test-mercurial-import/file_text+f#1 - opened for edit
+ //depot/test-mercurial-import/file_text+k#1 - opened for edit
+ //depot/test-mercurial-import/file_text+ko#1 - opened for edit
+ //depot/test-mercurial-import/file_text+kx#1 - opened for edit
+ //depot/test-mercurial-import/file_text+l#1 - opened for edit
+ //depot/test-mercurial-import/file_text+m#1 - opened for edit
+ //depot/test-mercurial-import/file_text+s#1 - opened for edit
+ //depot/test-mercurial-import/file_text+s2#1 - opened for edit
+ //depot/test-mercurial-import/file_text+w#1 - opened for edit
+ //depot/test-mercurial-import/file_text+x#1 - opened for edit
+ //depot/test-mercurial-import/file_ubinary#1 - opened for edit
+ //depot/test-mercurial-import/file_uxbinary#1 - opened for edit
+ //depot/test-mercurial-import/file_xbinary#1 - opened for edit
+ //depot/test-mercurial-import/file_xltext#1 - opened for edit
+ //depot/test-mercurial-import/file_xtempobj#1 - opened for edit
+ //depot/test-mercurial-import/file_xtext#1 - opened for edit
+ //depot/test-mercurial-import/target_symlink#1 - opened for edit
+ //depot/test-mercurial-import/target_symlink+k#1 - opened for edit
+ $ for T in $TYPES ; do
+ > T2=`echo $T | tr [:upper:] [:lower:]`
+ > echo '$Id$' >>file_$T2
+ > echo '$Header$' >>file_$T2
+ > echo '$Date$' >>file_$T2
+ > echo '$DateTime$' >>file_$T2
+ > echo '$Change$' >>file_$T2
+ > echo '$File$' >>file_$T2
+ > echo '$Revision$' >>file_$T2
+ > echo '$Header$$Header$Header$' >>file_$T2
+ > done
+
+ $ ln -s 'target_$Header$' crazy_symlink+k
+ $ p4 add -t symlink+k crazy_symlink+k
+ //depot/test-mercurial-import/crazy_symlink+k#1 - opened for add
+
+ $ p4 submit -d keywords
+ Submitting change 2.
+ Locking 34 files ...
+ add //depot/test-mercurial-import/crazy_symlink+k#1
+ edit //depot/test-mercurial-import/file_binary#2
+ edit //depot/test-mercurial-import/file_binary+k#2
+ edit //depot/test-mercurial-import/file_binary+kx#2
+ edit //depot/test-mercurial-import/file_binary+x#2
+ edit //depot/test-mercurial-import/file_ctext#2
+ edit //depot/test-mercurial-import/file_cxtext#2
+ edit //depot/test-mercurial-import/file_ktext#2
+ edit //depot/test-mercurial-import/file_kxtext#2
+ edit //depot/test-mercurial-import/file_ltext#2
+ edit //depot/test-mercurial-import/file_symlink#2
+ edit //depot/test-mercurial-import/file_symlink+k#2
+ edit //depot/test-mercurial-import/file_tempobj#2
+ edit //depot/test-mercurial-import/file_text#2
+ edit //depot/test-mercurial-import/file_text+c#2
+ edit //depot/test-mercurial-import/file_text+d#2
+ edit //depot/test-mercurial-import/file_text+f#2
+ edit //depot/test-mercurial-import/file_text+k#2
+ edit //depot/test-mercurial-import/file_text+ko#2
+ edit //depot/test-mercurial-import/file_text+kx#2
+ edit //depot/test-mercurial-import/file_text+l#2
+ edit //depot/test-mercurial-import/file_text+m#2
+ edit //depot/test-mercurial-import/file_text+s#2
+ edit //depot/test-mercurial-import/file_text+s2#2
+ edit //depot/test-mercurial-import/file_text+w#2
+ edit //depot/test-mercurial-import/file_text+x#2
+ edit //depot/test-mercurial-import/file_ubinary#2
+ edit //depot/test-mercurial-import/file_uxbinary#2
+ edit //depot/test-mercurial-import/file_xbinary#2
+ edit //depot/test-mercurial-import/file_xltext#2
+ edit //depot/test-mercurial-import/file_xtempobj#2
+ edit //depot/test-mercurial-import/file_xtext#2
+ edit //depot/test-mercurial-import/target_symlink#2
+ edit //depot/test-mercurial-import/target_symlink+k#2
+ Change 2 submitted.
+ //depot/test-mercurial-import/crazy_symlink+k#1 - refreshing
+ //depot/test-mercurial-import/file_binary+k#2 - refreshing
+ //depot/test-mercurial-import/file_binary+kx#2 - refreshing
+ //depot/test-mercurial-import/file_ktext#2 - refreshing
+ //depot/test-mercurial-import/file_kxtext#2 - refreshing
+ //depot/test-mercurial-import/file_symlink+k#2 - refreshing
+ //depot/test-mercurial-import/file_text+k#2 - refreshing
+ //depot/test-mercurial-import/file_text+ko#2 - refreshing
+ //depot/test-mercurial-import/file_text+kx#2 - refreshing
+
+check keywords in p4
+ $ grep -H Header file_*
+ file_binary:$Header$
+ file_binary:$Header$$Header$Header$
+ file_binary+k:$Header: //depot/test-mercurial-import/file_binary+k#2 $
+ file_binary+k:$Header: //depot/test-mercurial-import/file_binary+k#2 $$Header: //depot/test-mercurial-import/file_binary+k#2 $Header$
+ file_binary+kx:$Header: //depot/test-mercurial-import/file_binary+kx#2 $
+ file_binary+kx:$Header: //depot/test-mercurial-import/file_binary+kx#2 $$Header: //depot/test-mercurial-import/file_binary+kx#2 $Header$
+ file_binary+x:$Header$
+ file_binary+x:$Header$$Header$Header$
+ file_ctext:$Header$
+ file_ctext:$Header$$Header$Header$
+ file_cxtext:$Header$
+ file_cxtext:$Header$$Header$Header$
+ file_ktext:$Header: //depot/test-mercurial-import/file_ktext#2 $
+ file_ktext:$Header: //depot/test-mercurial-import/file_ktext#2 $$Header: //depot/test-mercurial-import/file_ktext#2 $Header$
+ file_kxtext:$Header: //depot/test-mercurial-import/file_kxtext#2 $
+ file_kxtext:$Header: //depot/test-mercurial-import/file_kxtext#2 $$Header: //depot/test-mercurial-import/file_kxtext#2 $Header$
+ file_ltext:$Header$
+ file_ltext:$Header$$Header$Header$
+ file_symlink:$Header$
+ file_symlink:$Header$$Header$Header$
+ file_symlink+k:$Header$
+ file_symlink+k:$Header$$Header$Header$
+ file_tempobj:$Header$
+ file_tempobj:$Header$$Header$Header$
+ file_text:$Header$
+ file_text:$Header$$Header$Header$
+ file_text+c:$Header$
+ file_text+c:$Header$$Header$Header$
+ file_text+d:$Header$
+ file_text+d:$Header$$Header$Header$
+ file_text+f:$Header$
+ file_text+f:$Header$$Header$Header$
+ file_text+k:$Header: //depot/test-mercurial-import/file_text+k#2 $
+ file_text+k:$Header: //depot/test-mercurial-import/file_text+k#2 $$Header: //depot/test-mercurial-import/file_text+k#2 $Header$
+ file_text+ko:$Header: //depot/test-mercurial-import/file_text+ko#2 $
+ file_text+ko:$Header: //depot/test-mercurial-import/file_text+ko#2 $$Header: //depot/test-mercurial-import/file_text+ko#2 $Header$
+ file_text+kx:$Header: //depot/test-mercurial-import/file_text+kx#2 $
+ file_text+kx:$Header: //depot/test-mercurial-import/file_text+kx#2 $$Header: //depot/test-mercurial-import/file_text+kx#2 $Header$
+ file_text+l:$Header$
+ file_text+l:$Header$$Header$Header$
+ file_text+m:$Header$
+ file_text+m:$Header$$Header$Header$
+ file_text+s:$Header$
+ file_text+s:$Header$$Header$Header$
+ file_text+s2:$Header$
+ file_text+s2:$Header$$Header$Header$
+ file_text+w:$Header$
+ file_text+w:$Header$$Header$Header$
+ file_text+x:$Header$
+ file_text+x:$Header$$Header$Header$
+ file_ubinary:$Header$
+ file_ubinary:$Header$$Header$Header$
+ file_uxbinary:$Header$
+ file_uxbinary:$Header$$Header$Header$
+ file_xbinary:$Header$
+ file_xbinary:$Header$$Header$Header$
+ file_xltext:$Header$
+ file_xltext:$Header$$Header$Header$
+ file_xtempobj:$Header$
+ file_xtempobj:$Header$$Header$Header$
+ file_xtext:$Header$
+ file_xtext:$Header$$Header$Header$
+
+convert
+ $ hg convert -s p4 $DEPOTPATH dst
+ initializing destination dst repository
+ reading p4 views
+ collecting p4 changelists
+ 1 initial
+ 2 keywords
+ scanning source...
+ sorting...
+ converting...
+ 1 initial
+ 0 keywords
+ $ hg -R dst log --template 'rev={rev} desc="{desc}" tags="{tags}" files="{files}"\n'
+ rev=1 desc="keywords" tags="tip" files="crazy_symlink+k file_binary file_binary+k file_binary+kx file_binary+x file_ctext file_cxtext file_ktext file_kxtext file_ltext file_text file_text+c file_text+d file_text+f file_text+k file_text+ko file_text+kx file_text+l file_text+m file_text+s file_text+s2 file_text+w file_text+x file_ubinary file_uxbinary file_xbinary file_xltext file_xtext target_symlink target_symlink+k"
+ rev=0 desc="initial" tags="" files="file_binary file_binary+k file_binary+kx file_binary+x file_ctext file_cxtext file_ktext file_kxtext file_ltext file_symlink file_symlink+k file_text file_text+c file_text+d file_text+f file_text+k file_text+ko file_text+kx file_text+l file_text+m file_text+s2 file_text+w file_text+x file_ubinary file_uxbinary file_xbinary file_xltext file_xtext target_symlink target_symlink+k"
+
+revision 0
+ $ hg -R dst update 0
+ 30 files updated, 0 files merged, 0 files removed, 0 files unresolved
+ $ head dst/file_* | cat -v
+ ==> dst/file_binary <==
+ this is binary
+ ==> dst/file_binary+k <==
+ this is binary+k
+ ==> dst/file_binary+kx <==
+ this is binary+kx
+ ==> dst/file_binary+x <==
+ this is binary+x
+ ==> dst/file_ctext <==
+ this is ctext
+
+ ==> dst/file_cxtext <==
+ this is cxtext
+
+ ==> dst/file_ktext <==
+ this is ktext
+
+ ==> dst/file_kxtext <==
+ this is kxtext
+
+ ==> dst/file_ltext <==
+ this is ltext
+
+ ==> dst/file_symlink <==
+ this is target symlink
+
+ ==> dst/file_symlink+k <==
+ this is target symlink+k
+
+ ==> dst/file_text <==
+ this is text
+
+ ==> dst/file_text+c <==
+ this is text+C
+
+ ==> dst/file_text+d <==
+ this is text+D
+
+ ==> dst/file_text+f <==
+ this is text+F
+
+ ==> dst/file_text+k <==
+ this is text+k
+
+ ==> dst/file_text+ko <==
+ this is text+ko
+
+ ==> dst/file_text+kx <==
+ this is text+kx
+
+ ==> dst/file_text+l <==
+ this is text+l
+
+ ==> dst/file_text+m <==
+ this is text+m
+
+ ==> dst/file_text+s2 <==
+ this is text+S2
+
+ ==> dst/file_text+w <==
+ this is text+w
+
+ ==> dst/file_text+x <==
+ this is text+x
+
+ ==> dst/file_ubinary <==
+ this is ubinary
+
+ ==> dst/file_uxbinary <==
+ this is uxbinary
+
+ ==> dst/file_xbinary <==
+ this is xbinary
+
+ ==> dst/file_xltext <==
+ this is xltext
+
+ ==> dst/file_xtext <==
+ this is xtext
+
+revision 1
+ $ hg -R dst update 1
+ 30 files updated, 0 files merged, 0 files removed, 0 files unresolved
+ $ head dst/file_* | cat -v
+ ==> dst/file_binary <==
+ this is binary$Id$
+ $Header$
+ $Date$
+ $DateTime$
+ $Change$
+ $File$
+ $Revision$
+ $Header$$Header$Header$
+
+ ==> dst/file_binary+k <==
+ this is binary+k$Id$
+ $Header$
+ $Date$
+ $DateTime$
+ $Change$
+ $File$
+ $Revision$
+ $Header$$Header$Header$
+
+ ==> dst/file_binary+kx <==
+ this is binary+kx$Id$
+ $Header$
+ $Date$
+ $DateTime$
+ $Change$
+ $File$
+ $Revision$
+ $Header$$Header$Header$
+
+ ==> dst/file_binary+x <==
+ this is binary+x$Id$
+ $Header$
+ $Date$
+ $DateTime$
+ $Change$
+ $File$
+ $Revision$
+ $Header$$Header$Header$
+
+ ==> dst/file_ctext <==
+ this is ctext
+ $Id$
+ $Header$
+ $Date$
+ $DateTime$
+ $Change$
+ $File$
+ $Revision$
+ $Header$$Header$Header$
+
+ ==> dst/file_cxtext <==
+ this is cxtext
+ $Id$
+ $Header$
+ $Date$
+ $DateTime$
+ $Change$
+ $File$
+ $Revision$
+ $Header$$Header$Header$
+
+ ==> dst/file_ktext <==
+ this is ktext
+ $Id$
+ $Header$
+ $Date$
+ $DateTime$
+ $Change$
+ $File$
+ $Revision$
+ $Header$$Header$Header$
+
+ ==> dst/file_kxtext <==
+ this is kxtext
+ $Id$
+ $Header$
+ $Date$
+ $DateTime$
+ $Change$
+ $File$
+ $Revision$
+ $Header$$Header$Header$
+
+ ==> dst/file_ltext <==
+ this is ltext
+ $Id$
+ $Header$
+ $Date$
+ $DateTime$
+ $Change$
+ $File$
+ $Revision$
+ $Header$$Header$Header$
+
+ ==> dst/file_symlink <==
+ this is target symlink
+ $Id$
+ $Header$
+ $Date$
+ $DateTime$
+ $Change$
+ $File$
+ $Revision$
+ $Header$$Header$Header$
+
+ ==> dst/file_symlink+k <==
+ this is target symlink+k
+ $Id$
+ $Header$
+ $Date$
+ $DateTime$
+ $Change$
+ $File$
+ $Revision$
+ $Header$$Header$Header$
+
+ ==> dst/file_text <==
+ this is text
+ $Id$
+ $Header$
+ $Date$
+ $DateTime$
+ $Change$
+ $File$
+ $Revision$
+ $Header$$Header$Header$
+
+ ==> dst/file_text+c <==
+ this is text+C
+ $Id$
+ $Header$
+ $Date$
+ $DateTime$
+ $Change$
+ $File$
+ $Revision$
+ $Header$$Header$Header$
+
+ ==> dst/file_text+d <==
+ this is text+D
+ $Id$
+ $Header$
+ $Date$
+ $DateTime$
+ $Change$
+ $File$
+ $Revision$
+ $Header$$Header$Header$
+
+ ==> dst/file_text+f <==
+ this is text+F
+ $Id$
+ $Header$
+ $Date$
+ $DateTime$
+ $Change$
+ $File$
+ $Revision$
+ $Header$$Header$Header$
+
+ ==> dst/file_text+k <==
+ this is text+k
+ $Id$
+ $Header$
+ $Date$
+ $DateTime$
+ $Change$
+ $File$
+ $Revision$
+ $Header$$Header$Header$
+
+ ==> dst/file_text+ko <==
+ this is text+ko
+ $Id$
+ $Header$
+ $Date$
+ $DateTime$
+ $Change$
+ $File$
+ $Revision$
+ $Header$$Header$Header$
+
+ ==> dst/file_text+kx <==
+ this is text+kx
+ $Id$
+ $Header$
+ $Date$
+ $DateTime$
+ $Change$
+ $File$
+ $Revision$
+ $Header$$Header$Header$
+
+ ==> dst/file_text+l <==
+ this is text+l
+ $Id$
+ $Header$
+ $Date$
+ $DateTime$
+ $Change$
+ $File$
+ $Revision$
+ $Header$$Header$Header$
+
+ ==> dst/file_text+m <==
+ this is text+m
+ $Id$
+ $Header$
+ $Date$
+ $DateTime$
+ $Change$
+ $File$
+ $Revision$
+ $Header$$Header$Header$
+
+ ==> dst/file_text+s <==
+ this is text+S
+ $Id$
+ $Header$
+ $Date$
+ $DateTime$
+ $Change$
+ $File$
+ $Revision$
+ $Header$$Header$Header$
+
+ ==> dst/file_text+s2 <==
+ this is text+S2
+ $Id$
+ $Header$
+ $Date$
+ $DateTime$
+ $Change$
+ $File$
+ $Revision$
+ $Header$$Header$Header$
+
+ ==> dst/file_text+w <==
+ this is text+w
+ $Id$
+ $Header$
+ $Date$
+ $DateTime$
+ $Change$
+ $File$
+ $Revision$
+ $Header$$Header$Header$
+
+ ==> dst/file_text+x <==
+ this is text+x
+ $Id$
+ $Header$
+ $Date$
+ $DateTime$
+ $Change$
+ $File$
+ $Revision$
+ $Header$$Header$Header$
+
+ ==> dst/file_ubinary <==
+ this is ubinary
+ $Id$
+ $Header$
+ $Date$
+ $DateTime$
+ $Change$
+ $File$
+ $Revision$
+ $Header$$Header$Header$
+
+ ==> dst/file_uxbinary <==
+ this is uxbinary
+ $Id$
+ $Header$
+ $Date$
+ $DateTime$
+ $Change$
+ $File$
+ $Revision$
+ $Header$$Header$Header$
+
+ ==> dst/file_xbinary <==
+ this is xbinary
+ $Id$
+ $Header$
+ $Date$
+ $DateTime$
+ $Change$
+ $File$
+ $Revision$
+ $Header$$Header$Header$
+
+ ==> dst/file_xltext <==
+ this is xltext
+ $Id$
+ $Header$
+ $Date$
+ $DateTime$
+ $Change$
+ $File$
+ $Revision$
+ $Header$$Header$Header$
+
+ ==> dst/file_xtext <==
+ this is xtext
+ $Id$
+ $Header$
+ $Date$
+ $DateTime$
+ $Change$
+ $File$
+ $Revision$
+ $Header$$Header$Header$
+
+crazy_symlink
+ $ readlink crazy_symlink+k
+ target_$Header: //depot/test-mercurial-import/crazy_symlink+k#1 $
+ $ readlink dst/crazy_symlink+k
+ target_$Header$
+
+exit trap:
+ stopping the p4 server
--- a/tests/test-convert-p4.out Sun May 13 11:19:48 2012 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,88 +0,0 @@
-% create p4 depot
-% start the p4 server
-% create a client spec
-Client hg-p4-import saved.
-% populate the depot
-//depot/test-mercurial-import/a#1 - opened for add
-//depot/test-mercurial-import/b/c#1 - opened for add
-Submitting change 1.
-Locking 2 files ...
-add //depot/test-mercurial-import/a#1
-add //depot/test-mercurial-import/b/c#1
-Change 1 submitted.
-% change some files
-//depot/test-mercurial-import/a#1 - opened for edit
-Submitting change 2.
-Locking 1 files ...
-edit //depot/test-mercurial-import/a#2
-Change 2 submitted.
-//depot/test-mercurial-import/b/c#1 - opened for edit
-Submitting change 3.
-Locking 1 files ...
-edit //depot/test-mercurial-import/b/c#2
-Change 3 submitted.
-% convert
-initializing destination dst repository
-reading p4 views
-collecting p4 changelists
-1 initial
-2 change a
-3 change b/c
-scanning source...
-sorting...
-converting...
-2 initial
-1 change a
-0 change b/c
-rev=2 desc="change b/c" tags="tip" files="b/c"
-rev=1 desc="change a" tags="" files="a"
-rev=0 desc="initial" tags="" files="a b/c"
-% change some files
-//depot/test-mercurial-import/a#2 - opened for edit
-//depot/test-mercurial-import/b/c#2 - opened for edit
-Submitting change 4.
-Locking 2 files ...
-edit //depot/test-mercurial-import/a#3
-edit //depot/test-mercurial-import/b/c#3
-Change 4 submitted.
-% convert again
-reading p4 views
-collecting p4 changelists
-1 initial
-2 change a
-3 change b/c
-4 change a b/c
-scanning source...
-sorting...
-converting...
-0 change a b/c
-rev=3 desc="change a b/c" tags="tip" files="a b/c"
-rev=2 desc="change b/c" tags="" files="b/c"
-rev=1 desc="change a" tags="" files="a"
-rev=0 desc="initial" tags="" files="a b/c"
-% interesting names
-//depot/test-mercurial-import/d d#1 - opened for add
-//depot/test-mercurial-import/ e/ f#1 - opened for add
-Submitting change 5.
-Locking 2 files ...
-add //depot/test-mercurial-import/ e/ f#1
-add //depot/test-mercurial-import/d d#1
-Change 5 submitted.
-% convert again
-reading p4 views
-collecting p4 changelists
-1 initial
-2 change a
-3 change b/c
-4 change a b/c
-5 add d e f
-scanning source...
-sorting...
-converting...
-0 add d e f
-rev=4 desc="add d e f" tags="tip" files=" e/ f d d"
-rev=3 desc="change a b/c" tags="" files="a b/c"
-rev=2 desc="change b/c" tags="" files="b/c"
-rev=1 desc="change a" tags="" files="a"
-rev=0 desc="initial" tags="" files="a b/c"
-% stop the p4 server
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/test-convert-p4.t Sun May 13 12:52:24 2012 +0200
@@ -0,0 +1,152 @@
+ $ "$TESTDIR/hghave" p4 || exit 80
+
+ $ echo "[extensions]" >> $HGRCPATH
+ $ echo "convert = " >> $HGRCPATH
+
+create p4 depot
+ $ P4ROOT=`pwd`/depot; export P4ROOT
+ $ P4AUDIT=$P4ROOT/audit; export P4AUDIT
+ $ P4JOURNAL=$P4ROOT/journal; export P4JOURNAL
+ $ P4LOG=$P4ROOT/log; export P4LOG
+ $ P4PORT=localhost:16661; export P4PORT
+ $ P4DEBUG=1; export P4DEBUG
+
+start the p4 server
+ $ [ ! -d $P4ROOT ] && mkdir $P4ROOT
+ $ p4d -f -J off >$P4ROOT/stdout 2>$P4ROOT/stderr &
+ $ echo $! >> $DAEMON_PIDS
+ $ trap "echo stopping the p4 server ; p4 admin stop" EXIT
+
+ $ # wait for the server to initialize
+ $ while ! p4 ; do
+ > sleep 1
+ > done >/dev/null 2>/dev/null
+
+create a client spec
+ $ P4CLIENT=hg-p4-import; export P4CLIENT
+ $ DEPOTPATH=//depot/test-mercurial-import/...
+ $ p4 client -o | sed '/^View:/,$ d' >p4client
+ $ echo View: >>p4client
+ $ echo " $DEPOTPATH //$P4CLIENT/..." >>p4client
+ $ p4 client -i <p4client
+ Client hg-p4-import saved.
+
+populate the depot
+ $ echo a > a
+ $ mkdir b
+ $ echo c > b/c
+ $ p4 add a b/c
+ //depot/test-mercurial-import/a#1 - opened for add
+ //depot/test-mercurial-import/b/c#1 - opened for add
+ $ p4 submit -d initial
+ Submitting change 1.
+ Locking 2 files ...
+ add //depot/test-mercurial-import/a#1
+ add //depot/test-mercurial-import/b/c#1
+ Change 1 submitted.
+
+change some files
+ $ p4 edit a
+ //depot/test-mercurial-import/a#1 - opened for edit
+ $ echo aa >> a
+ $ p4 submit -d "change a"
+ Submitting change 2.
+ Locking 1 files ...
+ edit //depot/test-mercurial-import/a#2
+ Change 2 submitted.
+
+ $ p4 edit b/c
+ //depot/test-mercurial-import/b/c#1 - opened for edit
+ $ echo cc >> b/c
+ $ p4 submit -d "change b/c"
+ Submitting change 3.
+ Locking 1 files ...
+ edit //depot/test-mercurial-import/b/c#2
+ Change 3 submitted.
+
+convert
+ $ hg convert -s p4 $DEPOTPATH dst
+ initializing destination dst repository
+ reading p4 views
+ collecting p4 changelists
+ 1 initial
+ 2 change a
+ 3 change b/c
+ scanning source...
+ sorting...
+ converting...
+ 2 initial
+ 1 change a
+ 0 change b/c
+ $ hg -R dst log --template 'rev={rev} desc="{desc}" tags="{tags}" files="{files}"\n'
+ rev=2 desc="change b/c" tags="tip" files="b/c"
+ rev=1 desc="change a" tags="" files="a"
+ rev=0 desc="initial" tags="" files="a b/c"
+
+change some files
+ $ p4 edit a b/c
+ //depot/test-mercurial-import/a#2 - opened for edit
+ //depot/test-mercurial-import/b/c#2 - opened for edit
+ $ echo aaa >> a
+ $ echo ccc >> b/c
+ $ p4 submit -d "change a b/c"
+ Submitting change 4.
+ Locking 2 files ...
+ edit //depot/test-mercurial-import/a#3
+ edit //depot/test-mercurial-import/b/c#3
+ Change 4 submitted.
+
+convert again
+ $ hg convert -s p4 $DEPOTPATH dst
+ reading p4 views
+ collecting p4 changelists
+ 1 initial
+ 2 change a
+ 3 change b/c
+ 4 change a b/c
+ scanning source...
+ sorting...
+ converting...
+ 0 change a b/c
+ $ hg -R dst log --template 'rev={rev} desc="{desc}" tags="{tags}" files="{files}"\n'
+ rev=3 desc="change a b/c" tags="tip" files="a b/c"
+ rev=2 desc="change b/c" tags="" files="b/c"
+ rev=1 desc="change a" tags="" files="a"
+ rev=0 desc="initial" tags="" files="a b/c"
+
+interesting names
+ $ echo dddd > "d d"
+ $ mkdir " e"
+ $ echo fff >" e/ f"
+ $ p4 add "d d" " e/ f"
+ //depot/test-mercurial-import/d d#1 - opened for add
+ //depot/test-mercurial-import/ e/ f#1 - opened for add
+ $ p4 submit -d "add d e f"
+ Submitting change 5.
+ Locking 2 files ...
+ add //depot/test-mercurial-import/ e/ f#1
+ add //depot/test-mercurial-import/d d#1
+ Change 5 submitted.
+
+convert again
+ $ hg convert -s p4 $DEPOTPATH dst
+ reading p4 views
+ collecting p4 changelists
+ 1 initial
+ 2 change a
+ 3 change b/c
+ 4 change a b/c
+ 5 add d e f
+ scanning source...
+ sorting...
+ converting...
+ 0 add d e f
+ $ hg -R dst log --template 'rev={rev} desc="{desc}" tags="{tags}" files="{files}"\n'
+ rev=4 desc="add d e f" tags="tip" files=" e/ f d d"
+ rev=3 desc="change a b/c" tags="" files="a b/c"
+ rev=2 desc="change b/c" tags="" files="b/c"
+ rev=1 desc="change a" tags="" files="a"
+ rev=0 desc="initial" tags="" files="a b/c"
+
+exit trap:
+ stopping the p4 server
--- a/tests/test-debugcomplete.t Sun May 13 11:19:48 2012 +0200
+++ b/tests/test-debugcomplete.t Sun May 13 12:52:24 2012 +0200
@@ -247,7 +247,7 @@
debugsub: rev
debugwalk: include, exclude
debugwireargs: three, four, five, ssh, remotecmd, insecure
- graft: continue, edit, currentdate, currentuser, date, user, tool, dry-run
+ graft: continue, edit, log, currentdate, currentuser, date, user, tool, dry-run
grep: print0, all, text, follow, ignore-case, files-with-matches, line-number, rev, user, date, include, exclude
heads: rev, topo, active, closed, style, template
help: extension, command
--- a/tests/test-filecache.py Sun May 13 11:19:48 2012 +0200
+++ b/tests/test-filecache.py Sun May 13 12:52:24 2012 +0200
@@ -1,6 +1,7 @@
import sys, os, subprocess
-if subprocess.call(['python', '%s/hghave' % os.environ['TESTDIR'], 'cacheable']):
+if subprocess.call(['python', '%s/hghave' % os.environ['TESTDIR'],
+ 'cacheable']):
sys.exit(80)
from mercurial import util, scmutil, extensions
@@ -77,7 +78,7 @@
try:
os.remove('x')
- except:
+ except OSError:
pass
basic(fakerepo())
--- a/tests/test-graft.t Sun May 13 11:19:48 2012 +0200
+++ b/tests/test-graft.t Sun May 13 12:52:24 2012 +0200
@@ -72,28 +72,23 @@
# HG changeset patch
# User foo
# Date 0 0
- # Node ID d2e44c99fd3f31c176ea4efb9eca9f6306c81756
+ # Node ID ef0ef43d49e79e81ddafdc7997401ba0041efc82
# Parent 68795b066622ca79a25816a662041d8f78f3cd9e
2
diff --git a/a b/b
rename from a
rename to b
- --- a/a
- +++ b/b
- @@ -1,1 +1,1 @@
- -a
- +b
Look for extra:source
$ hg log --debug -r tip
- changeset: 7:d2e44c99fd3f31c176ea4efb9eca9f6306c81756
+ changeset: 7:ef0ef43d49e79e81ddafdc7997401ba0041efc82
tag: tip
phase: draft
parent: 0:68795b066622ca79a25816a662041d8f78f3cd9e
parent: -1:0000000000000000000000000000000000000000
- manifest: 7:5d59766436fd8fbcd38e7bebef0f6eaf3eebe637
+ manifest: 7:e59b6b228f9cbf9903d5e9abf996e083a1f533eb
user: foo
date: Thu Jan 01 00:00:00 1970 +0000
files+: b
@@ -128,15 +123,20 @@
checking for directory renames
resolving manifests
overwrite: False, partial: False
- ancestor: 68795b066622, local: d2e44c99fd3f+, remote: 5d205f8b35b6
+ ancestor: 68795b066622, local: ef0ef43d49e7+, remote: 5d205f8b35b6
b: local copied/moved to a -> m
preserving b for resolve of b
updating: b 1/1 files (100.00%)
+ picked tool 'internal:merge' for b (binary False symlink False)
+ merging b and a to b
+ my b@ef0ef43d49e7+ other a@5d205f8b35b6 ancestor a@68795b066622
+ premerge successful
+ b
grafting revision 5
searching for copies back to rev 1
resolving manifests
overwrite: False, partial: False
- ancestor: 4c60f11aa304, local: d2e44c99fd3f+, remote: 97f8bfe72746
+ ancestor: 4c60f11aa304, local: 6b9e5368ca4e+, remote: 97f8bfe72746
e: remote is newer -> g
updating: e 1/1 files (100.00%)
getting e
@@ -145,7 +145,7 @@
searching for copies back to rev 1
resolving manifests
overwrite: False, partial: False
- ancestor: 4c60f11aa304, local: 839a7e8fcf80+, remote: 9c233e8e184d
+ ancestor: 4c60f11aa304, local: 1905859650ec+, remote: 9c233e8e184d
e: versions differ -> m
d: remote is newer -> g
preserving e for resolve of e
@@ -154,7 +154,7 @@
updating: e 2/2 files (100.00%)
picked tool 'internal:merge' for e (binary False symlink False)
merging e
- my e@839a7e8fcf80+ other e@9c233e8e184d ancestor e@68795b066622
+ my e@1905859650ec+ other e@9c233e8e184d ancestor e@68795b066622
warning: conflicts during merge.
merging e incomplete! (edit conflicts, then use 'hg resolve --mark')
abort: unresolved conflicts, can't continue
@@ -200,11 +200,13 @@
View graph:
$ hg --config extensions.graphlog= log -G --template '{author}@{rev}.{phase}: {desc}\n'
- @ test@10.draft: 3
+ @ test@11.draft: 3
+ |
+ o test@10.draft: 4
|
- o test@9.draft: 4
+ o test@9.draft: 5
|
- o test@8.draft: 5
+ o bar@8.draft: 1
|
o foo@7.draft: 2
|
@@ -232,17 +234,17 @@
grafting revision 7
$ hg log -r 7 --template '{rev}:{node}\n'
- 7:d2e44c99fd3f31c176ea4efb9eca9f6306c81756
+ 7:ef0ef43d49e79e81ddafdc7997401ba0041efc82
$ hg log -r 2 --template '{rev}:{node}\n'
2:5c095ad7e90f871700f02dd1fa5012cb4498a2d4
$ hg log --debug -r tip
- changeset: 12:95adbe5de6b10f376b699ece9ed5a57cd7b4b0f6
+ changeset: 13:9db0f28fd3747e92c57d015f53b5593aeec53c2d
tag: tip
phase: draft
- parent: 11:b592ea63bb0c19a6c5c44685ee29a2284f9f1b8f
+ parent: 12:b592ea63bb0c19a6c5c44685ee29a2284f9f1b8f
parent: -1:0000000000000000000000000000000000000000
- manifest: 12:9944044f82a462bbaccc9bdf7e0ac5b811db7d1b
+ manifest: 13:dc313617b8c32457c0d589e0dbbedfe71f3cd637
user: foo
date: Thu Jan 01 00:00:00 1970 +0000
files+: b
@@ -260,7 +262,7 @@
[255]
Disallow grafting already grafted csets with the same origin onto each other
- $ hg up -q 12
+ $ hg up -q 13
$ hg graft 2
skipping already grafted revision 2
[255]
@@ -273,5 +275,15 @@
skipping already grafted revision 2
[255]
$ hg graft tip
- skipping already grafted revision 12 (same origin 2)
+ skipping already grafted revision 13 (same origin 2)
[255]
+
+Graft with --log
+
+ $ hg up -Cq 1
+ $ hg graft 3 --log -u foo
+ grafting revision 3
+ warning: can't find ancestor for 'c' copied from 'b'!
+ $ hg log --template '{rev} {parents} {desc}\n' -r tip
+ 14 1:5d205f8b35b6 3
+ (grafted from 4c60f11aa304a54ae1c199feb94e7fc771e51ed8)
--- a/tests/test-hook.t Sun May 13 11:19:48 2012 +0200
+++ b/tests/test-hook.t Sun May 13 12:52:24 2012 +0200
@@ -195,6 +195,7 @@
no changes found
listkeys hook: HG_NAMESPACE=phases HG_VALUES={'cb9a9f314b8b07ba71012fcdbc544b5a4d82ff5b': '1', 'publishing': 'True'}
listkeys hook: HG_NAMESPACE=bookmarks HG_VALUES={'bar': '0000000000000000000000000000000000000000', 'foo': '0000000000000000000000000000000000000000'}
+ adding remote bookmark bar
importing bookmark bar
$ cd ../a
@@ -279,6 +280,7 @@
adding manifests
adding file changes
added 1 changesets with 1 changes to 1 files
+ adding remote bookmark quux
(run 'hg update' to get a working copy)
$ hg rollback
repository tip rolled back to revision 3 (undo pull)
@@ -447,6 +449,7 @@
adding manifests
adding file changes
added 1 changesets with 1 changes to 1 files
+ adding remote bookmark quux
(run 'hg update' to get a working copy)
make sure --traceback works
--- a/tests/test-keyword.t Sun May 13 11:19:48 2012 +0200
+++ b/tests/test-keyword.t Sun May 13 12:52:24 2012 +0200
@@ -558,6 +558,7 @@
$ hg --debug commit -ma2c -d '1 0' -u 'User Name <user@example.com>'
c
c: copy a:0045e12f6c5791aac80ca6cbfd97709a88307292
+ removing unknown node 40a904bbbe4c from 1-phase boundary
overwriting c expanding keywords
committed changeset 2:25736cf2f5cbe41f6be4e6784ef6ecf9f3bbcc7d
$ cat a c
@@ -722,6 +723,7 @@
$ hg --debug commit -l log -d '2 0' -u 'User Name <user@example.com>'
a
+ removing unknown node 40a904bbbe4c from 1-phase boundary
overwriting a expanding keywords
committed changeset 2:bb948857c743469b22bbf51f7ec8112279ca5d83
$ rm log
--- a/tests/test-largefiles.t Sun May 13 11:19:48 2012 +0200
+++ b/tests/test-largefiles.t Sun May 13 12:52:24 2012 +0200
@@ -432,11 +432,48 @@
large11
$ cat sub/large2
large22
+ $ cd ..
+
+Test cloning with --all-largefiles flag
+
+ $ rm -Rf ${USERCACHE}/*
+ $ hg clone --all-largefiles a a-backup
+ updating to branch default
+ 5 files updated, 0 files merged, 0 files removed, 0 files unresolved
+ getting changed largefiles
+ 3 largefiles updated, 0 removed
+ 8 additional largefiles cached
+
+Test pulling with --all-largefiles flag
+
+ $ rm -Rf a-backup
+ $ hg clone -r 1 a a-backup
+ adding changesets
+ adding manifests
+ adding file changes
+ added 2 changesets with 8 changes to 4 files
+ updating to branch default
+ 4 files updated, 0 files merged, 0 files removed, 0 files unresolved
+ getting changed largefiles
+ 2 largefiles updated, 0 removed
+ $ rm -Rf ${USERCACHE}/*
+ $ cd a-backup
+ $ hg pull --all-largefiles
+ pulling from $TESTTMP/a
+ searching for changes
+ adding changesets
+ adding manifests
+ adding file changes
+ added 6 changesets with 16 changes to 8 files
+ (run 'hg update' to get a working copy)
+ caching new largefiles
+ 3 largefiles cached
+ 3 additional largefiles cached
+ $ cd ..
Rebasing between two repositories does not revert largefiles to old
revisions (this was a very bad bug that took a lot of work to fix).
- $ cd ..
$ hg clone a d
updating to branch default
5 files updated, 0 files merged, 0 files removed, 0 files unresolved
@@ -1136,4 +1173,37 @@
abort: uncommitted changes in subrepo subrepo
(use --subrepos for recursive commit)
[255]
+
+Add a normal file to the subrepo, then test archiving
+
+ $ echo 'normal file' > subrepo/normal.txt
+ $ hg -R subrepo add subrepo/normal.txt
+
+Lock in subrepo, otherwise the change isn't archived
+
+ $ hg ci -S -m "add normal file to top level"
+ committing subrepository subrepo
+ Invoking status precommit hook
+ M large.txt
+ A normal.txt
+ Invoking status precommit hook
+ M .hgsubstate
+ $ hg archive -S lf_subrepo_archive
+ $ find lf_subrepo_archive | sort
+ lf_subrepo_archive
+ lf_subrepo_archive/.hg_archival.txt
+ lf_subrepo_archive/.hgsub
+ lf_subrepo_archive/.hgsubstate
+ lf_subrepo_archive/a
+ lf_subrepo_archive/a/b
+ lf_subrepo_archive/a/b/c
+ lf_subrepo_archive/a/b/c/d
+ lf_subrepo_archive/a/b/c/d/e.large.txt
+ lf_subrepo_archive/a/b/c/d/e.normal.txt
+ lf_subrepo_archive/a/b/c/x
+ lf_subrepo_archive/a/b/c/x/y.normal.txt
+ lf_subrepo_archive/subrepo
+ lf_subrepo_archive/subrepo/large.txt
+ lf_subrepo_archive/subrepo/normal.txt
+
$ cd ..
--- a/tests/test-mq-qpush-fail.t Sun May 13 11:19:48 2012 +0200
+++ b/tests/test-mq-qpush-fail.t Sun May 13 12:52:24 2012 +0200
@@ -202,6 +202,42 @@
$ test -f a.orig && echo 'error: backup with --no-backup'
[1]
+test qpop --check
+
+ $ hg qpush
+ applying p1
+ now at: p1
+ $ hg qpop --check --force
+ abort: cannot use both --force and --check
+ [255]
+ $ echo a >> a
+ $ hg qpop --check
+ abort: local changes found, refresh first
+ [255]
+ $ hg revert -qa a
+ $ rm a
+ $ hg qpop --check
+ abort: local changes found, refresh first
+ [255]
+ $ hg rm -A a
+ $ hg qpop --check
+ abort: local changes found, refresh first
+ [255]
+ $ hg revert -qa a
+ $ echo b > b
+ $ hg add b
+ $ hg qpop --check
+ abort: local changes found, refresh first
+ [255]
+ $ hg forget b
+ $ echo d > d
+ $ hg add d
+ $ hg qpop --check
+ popping p1
+ patch queue now empty
+ $ hg forget d
+ $ rm d
+
test qpush --force and backup files
$ echo a >> a
@@ -281,3 +317,108 @@
now at: p2
$ test -f a.orig && echo 'error: backup with --no-backup'
[1]
+
+test qpush --check
+
+ $ hg qpush --check --force
+ abort: cannot use both --force and --check
+ [255]
+ $ hg qpush --check --exact
+ abort: cannot use --exact and --check together
+ [255]
+ $ echo b >> b
+ $ hg qpush --check
+ applying p3
+ errors during apply, please fix and refresh p2
+ [2]
+ $ rm b
+ $ hg qpush --check
+ applying p3
+ errors during apply, please fix and refresh p2
+ [2]
+ $ hg rm -A b
+ $ hg qpush --check
+ applying p3
+ errors during apply, please fix and refresh p2
+ [2]
+ $ hg revert -aq b
+ $ echo d > d
+ $ hg add d
+ $ hg qpush --check
+ applying p3
+ errors during apply, please fix and refresh p2
+ [2]
+ $ hg forget d
+ $ rm d
+ $ hg qpop
+ popping p2
+ patch queue now empty
+ $ echo b >> b
+ $ hg qpush -a --check
+ applying p2
+ applying p3
+ errors during apply, please fix and refresh p2
+ [2]
+ $ hg qtop
+ p2
+ $ hg parents --template "{rev} {desc}\n"
+ 2 imported patch p2
+ $ hg st b
+ M b
+ $ cat b
+ b
+ b
+
+test qgoto --check
+
+ $ hg revert -aq b
+ $ rm e
+ $ hg qgoto --check --force p3
+ abort: cannot use both --force and --check
+ [255]
+ $ echo a >> a
+ $ hg qgoto --check p3
+ applying p3
+ now at: p3
+ $ hg st a
+ M a
+ $ hg qgoto --check p2
+ popping p3
+ now at: p2
+ $ hg st a
+ M a
+
+test mq.check setting
+
+ $ hg --config mq.check=1 qpush
+ applying p3
+ now at: p3
+ $ hg st a
+ M a
+ $ hg --config mq.check=1 qpop
+ popping p3
+ now at: p2
+ $ hg st a
+ M a
+ $ hg --config mq.check=1 qgoto p3
+ applying p3
+ now at: p3
+ $ hg st a
+ M a
+ $ echo b >> b
+ $ hg --config mq.check=1 qpop --force
+ popping p3
+ now at: p2
+ $ hg st b
+ $ hg --config mq.check=1 qpush --exact
+ abort: local changes found, refresh first
+ [255]
+ $ hg revert -qa a
+ $ hg qpop
+ popping p2
+ patch queue now empty
+ $ echo a >> a
+ $ hg --config mq.check=1 qpush --force
+ applying p2
+ now at: p2
+ $ hg st a
--- a/tests/test-mq.t Sun May 13 11:19:48 2012 +0200
+++ b/tests/test-mq.t Sun May 13 12:52:24 2012 +0200
@@ -59,6 +59,15 @@
You will by default be managing a patch queue named "patches". You can create
other, independent patch queues with the "hg qqueue" command.
+ If the working directory contains uncommitted files, qpush, qpop and qgoto
+ abort immediately. If -f/--force is used, the changes are discarded. Setting:
+
+ [mq] check = True
+
+ make them behave as if -c/--check 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.
+
list of commands:
qapplied print the patches already applied
--- a/tests/test-phases.t Sun May 13 11:19:48 2012 +0200
+++ b/tests/test-phases.t Sun May 13 12:52:24 2012 +0200
@@ -9,6 +9,15 @@
$ hg init initialrepo
$ cd initialrepo
+
+Cannot change null revision phase
+
+ $ hg phase --force --secret null
+ abort: cannot change null revision phase
+ [255]
+ $ hg phase null
+ -1: public
+
$ mkcommit A
New commit are draft by default
--- a/tests/test-progress.t Sun May 13 11:19:48 2012 +0200
+++ b/tests/test-progress.t Sun May 13 12:52:24 2012 +0200
@@ -40,7 +40,7 @@
$ echo "progress=" >> $HGRCPATH
$ echo "loop=`pwd`/loop.py" >> $HGRCPATH
$ echo "[progress]" >> $HGRCPATH
- $ echo "format = topic bar number" >> $HGRCPATH
+ $ echo "format = topic bar number" >> $HGRCPATH
$ echo "assume-tty=1" >> $HGRCPATH
$ echo "width=60" >> $HGRCPATH
--- a/tests/test-rebase-collapse.t Sun May 13 11:19:48 2012 +0200
+++ b/tests/test-rebase-collapse.t Sun May 13 12:52:24 2012 +0200
@@ -589,4 +589,44 @@
b
$ hg log -r . --template "{file_copies}\n"
d (a)g (b)
+
+Test collapsing a middle revision in-place
+
+ $ hg tglog
+ @ 2: 'Collapsed revision
+ | * move1
+ | * move2'
+ o 1: 'change'
+ |
+ o 0: 'add'
+
+ $ hg rebase --collapse -r 1 -d 0
+ abort: can't remove original changesets with unrebased descendants
+ (use --keep to keep original changesets)
+ [255]
+
+Test collapsing in place
+
+ $ hg rebase --collapse -b . -d 0
+ saved backup bundle to $TESTTMP/copies/.hg/strip-backup/1352765a01d4-backup.hg
+ $ hg st --change . --copies
+ M a
+ M c
+ A d
+ a
+ A g
+ b
+ R b
+ $ cat a
+ a
+ a
+ $ cat c
+ c
+ c
+ $ cat d
+ a
+ a
+ $ cat g
+ b
+ b
$ cd ..
--- a/tests/test-rebase-parameters.t Sun May 13 11:19:48 2012 +0200
+++ b/tests/test-rebase-parameters.t Sun May 13 12:52:24 2012 +0200
@@ -158,12 +158,12 @@
$ cd ..
-Rebase with dest == `hg branch` => same as no arguments (from 3 onto 8):
+Rebase with dest == branch(.) => same as no arguments (from 3 onto 8):
$ hg clone -q -u 3 a a3
$ cd a3
- $ hg rebase --dest `hg branch`
+ $ hg rebase --dest 'branch(.)'
saved backup bundle to $TESTTMP/a3/.hg/strip-backup/*-backup.hg (glob)
$ hg tglog
--- a/tests/test-revset.t Sun May 13 11:19:48 2012 +0200
+++ b/tests/test-revset.t Sun May 13 12:52:24 2012 +0200
@@ -32,6 +32,13 @@
(branches are permanent and global, did you want a bookmark?)
$ hg ci -Aqm2 -u Bob
+ $ hg log -r "extra('branch', 'a-b-c-')" --template '{rev}\n'
+ 2
+ $ hg log -r "extra('branch')" --template '{rev}\n'
+ 0
+ 1
+ 2
+
$ hg co 1
1 files updated, 0 files merged, 0 files removed, 0 files unresolved
$ hg branch +a+b+c+
--- a/tests/test-transplant.t Sun May 13 11:19:48 2012 +0200
+++ b/tests/test-transplant.t Sun May 13 12:52:24 2012 +0200
@@ -120,7 +120,25 @@
1 r2
0 r1
+test same-parent transplant with --log
+ $ hg clone -r 1 ../t ../sameparent
+ adding changesets
+ adding manifests
+ adding file changes
+ added 2 changesets with 2 changes to 2 files
+ updating to branch default
+ 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
+ $ cd ../sameparent
+ $ hg transplant --log -s ../prune 5
+ searching for changes
+ applying e234d668f844
+ e234d668f844 transplanted to e07aea8ecf9c
+ $ hg log --template '{rev} {parents} {desc}\n'
+ 2 b1
+ (transplanted from e234d668f844e1b1a765f01db83a32c0c7bfa170)
+ 1 r2
+ 0 r1
remote transplant
$ hg clone -r 1 ../t ../remote
--- a/tests/test-walkrepo.py Sun May 13 11:19:48 2012 +0200
+++ b/tests/test-walkrepo.py Sun May 13 12:52:24 2012 +0200
@@ -24,10 +24,12 @@
reposet = frozenset(walkrepos('.', followsym=True))
if sym and (len(reposet) != 3):
print "reposet = %r" % (reposet,)
- print "Found %d repositories when I should have found 3" % (len(reposet),)
+ print ("Found %d repositories when I should have found 3"
+ % (len(reposet),))
if (not sym) and (len(reposet) != 2):
print "reposet = %r" % (reposet,)
- print "Found %d repositories when I should have found 2" % (len(reposet),)
+ print ("Found %d repositories when I should have found 2"
+ % (len(reposet),))
sub1set = frozenset((pjoin('.', 'sub1'),
pjoin('.', 'circle', 'subdir', 'sub1')))
if len(sub1set & reposet) != 1:
@@ -41,7 +43,7 @@
print "reposet = %r" % (reposet,)
print "sub1set and reposet should have exactly one path in common."
sub3 = pjoin('.', 'circle', 'top1')
- if sym and not (sub3 in reposet):
+ if sym and sub3 not in reposet:
print "reposet = %r" % (reposet,)
print "Symbolic links are supported and %s is not in reposet" % (sub3,)