--- a/contrib/perf.py Thu Jul 19 00:54:33 2012 +0200
+++ b/contrib/perf.py Wed Jul 18 19:08:11 2012 -0500
@@ -177,7 +177,7 @@
ui.popbuffer()
def perfcca(ui, repo):
- timer(lambda: scmutil.casecollisionauditor(ui, False, repo[None]))
+ timer(lambda: scmutil.casecollisionauditor(ui, False, repo.dirstate))
def perffncacheload(ui, repo):
from mercurial import scmutil, store
--- a/mercurial/commands.py Thu Jul 19 00:54:33 2012 +0200
+++ b/mercurial/commands.py Wed Jul 18 19:08:11 2012 -0500
@@ -5750,23 +5750,25 @@
none are found, the working directory is updated to the specified
changeset.
- The following rules apply when the working directory contains
- uncommitted changes:
-
- 1. If neither -c/--check nor -C/--clean is specified, and if
- the requested changeset is an ancestor or descendant of
- the working directory's parent, the uncommitted changes
- are merged into the requested changeset and the merged
- result is left uncommitted. If the requested changeset is
- not an ancestor or descendant (that is, it is on another
- branch), the update is aborted and the uncommitted changes
- are preserved.
-
- 2. With the -c/--check option, the update is aborted and the
- uncommitted changes are preserved.
-
- 3. With the -C/--clean option, uncommitted changes are discarded and
- the working directory is updated to the requested changeset.
+ .. container:: verbose
+
+ The following rules apply when the working directory contains
+ uncommitted changes:
+
+ 1. If neither -c/--check nor -C/--clean is specified, and if
+ the requested changeset is an ancestor or descendant of
+ the working directory's parent, the uncommitted changes
+ are merged into the requested changeset and the merged
+ result is left uncommitted. If the requested changeset is
+ not an ancestor or descendant (that is, it is on another
+ branch), the update is aborted and the uncommitted changes
+ are preserved.
+
+ 2. With the -c/--check option, the update is aborted and the
+ uncommitted changes are preserved.
+
+ 3. With the -C/--clean option, uncommitted changes are discarded and
+ the working directory is updated to the requested changeset.
To cancel an uncommitted merge (and lose your changes), use
:hg:`update --clean .`.
--- a/mercurial/extensions.py Thu Jul 19 00:54:33 2012 +0200
+++ b/mercurial/extensions.py Wed Jul 18 19:08:11 2012 -0500
@@ -42,7 +42,12 @@
fd, fpath, desc = imp.find_module(f, [d])
return imp.load_module(module_name, fd, fpath, desc)
else:
- return imp.load_source(module_name, path)
+ try:
+ return imp.load_source(module_name, path)
+ except IOError, exc:
+ if not exc.filename:
+ exc.filename = path # python does not fill this
+ raise
def load(ui, name, path):
# unused ui argument kept for backwards compatibility
--- a/mercurial/hook.py Thu Jul 19 00:54:33 2012 +0200
+++ b/mercurial/hook.py Wed Jul 18 19:08:11 2012 -0500
@@ -169,7 +169,11 @@
path = util.expandpath(path)
if repo:
path = os.path.join(repo.root, path)
- mod = extensions.loadpath(path, 'hghook.%s' % hname)
+ try:
+ mod = extensions.loadpath(path, 'hghook.%s' % hname)
+ except Exception:
+ ui.write(_("loading %s hook failed:\n") % hname)
+ raise
hookfn = getattr(mod, cmd)
else:
hookfn = cmd[7:].strip()
--- a/mercurial/httppeer.py Thu Jul 19 00:54:33 2012 +0200
+++ b/mercurial/httppeer.py Wed Jul 18 19:08:11 2012 -0500
@@ -79,6 +79,9 @@
elif data is not None:
size = len(data)
headers = args.pop('headers', {})
+ if data is not None and 'Content-Type' not in headers:
+ headers['Content-Type'] = 'application/mercurial-0.1'
+
if size and self.ui.configbool('ui', 'usehttp2', False):
headers['Expect'] = '100-Continue'
--- a/mercurial/obsolete.py Thu Jul 19 00:54:33 2012 +0200
+++ b/mercurial/obsolete.py Wed Jul 18 19:08:11 2012 -0500
@@ -164,8 +164,7 @@
self.sopener = sopener
data = sopener.tryread('obsstore')
if data:
- for marker in _readmarkers(data):
- self._load(marker)
+ self._load(_readmarkers(data))
def __iter__(self):
return iter(self._all)
@@ -188,11 +187,15 @@
if len(succ) != 20:
raise ValueError(succ)
marker = (str(prec), tuple(succs), int(flag), encodemeta(metadata))
- self.add(transaction, marker)
+ self.add(transaction, [marker])
+
+ def add(self, transaction, markers):
+ """Add new markers to the store
- def add(self, transaction, marker):
- """Add a new marker to the store"""
- if marker not in self._all:
+ Take care of filtering duplicate.
+ Return the number of new marker."""
+ new = [m for m in markers if m not in self._all]
+ if new:
f = self.sopener('obsstore', 'ab')
try:
# Whether the file's current position is at the begin or at
@@ -203,51 +206,48 @@
f.seek(0, 2) # os.SEEK_END
offset = f.tell()
transaction.add('obsstore', offset)
- if offset == 0:
- # new file add version header
- f.write(_pack('>B', _fmversion))
- _writemarkers(f.write, [marker])
+ # offset == 0: new file - add the version header
+ for bytes in _encodemarkers(new, offset == 0):
+ f.write(bytes)
finally:
# XXX: f.close() == filecache invalidation == obsstore rebuilt.
# call 'filecacheentry.refresh()' here
f.close()
- self._load(marker)
+ self._load(new)
+ return len(new)
def mergemarkers(self, transation, data):
- other = _readmarkers(data)
- local = set(self._all)
- new = [m for m in other if m not in local]
- for marker in new:
- # XXX: N marker == N x (open, write, close)
- # we should write them all at once
- self.add(transation, marker)
+ markers = _readmarkers(data)
+ self.add(transation, markers)
- def _load(self, marker):
- self._all.append(marker)
- pre, sucs = marker[:2]
- self.precursors.setdefault(pre, set()).add(marker)
- for suc in sucs:
- self.successors.setdefault(suc, set()).add(marker)
+ def _load(self, markers):
+ for mark in markers:
+ self._all.append(mark)
+ pre, sucs = mark[:2]
+ self.precursors.setdefault(pre, set()).add(mark)
+ for suc in sucs:
+ self.successors.setdefault(suc, set()).add(mark)
-def _writemarkers(write, markers):
+def _encodemarkers(markers, addheader=False):
# Kept separate from flushmarkers(), it will be reused for
# markers exchange.
+ if addheader:
+ yield _pack('>B', _fmversion)
for marker in markers:
pre, sucs, flags, metadata = marker
nbsuc = len(sucs)
format = _fmfixed + (_fmnode * nbsuc)
data = [nbsuc, len(metadata), flags, pre]
data.extend(sucs)
- write(_pack(format, *data))
- write(metadata)
+ yield _pack(format, *data)
+ yield metadata
def listmarkers(repo):
"""List markers over pushkey"""
if not repo.obsstore:
return {}
- data = [_pack('>B', _fmversion)]
- _writemarkers(data.append, repo.obsstore)
- return {'dump': base85.b85encode(''.join(data))}
+ markers = _encodemarkers(repo.obsstore, True)
+ return {'dump': base85.b85encode(''.join(markers))}
def pushmarker(repo, key, old, new):
"""Push markers over pushkey"""
--- a/tests/test-hook.t Thu Jul 19 00:54:33 2012 +0200
+++ b/tests/test-hook.t Wed Jul 18 19:08:11 2012 -0500
@@ -530,6 +530,20 @@
nothing changed
[1]
+ $ echo '[hooks]' > .hg/hgrc
+ $ echo "update.ne = python:`pwd`/nonexisting.py:testhook" >> .hg/hgrc
+ $ echo "pre-identify.npmd = python:`pwd`/:no_python_module_dir" >> .hg/hgrc
+
+ $ hg up null
+ loading update.ne hook failed:
+ abort: No such file or directory: $TESTTMP/d/repo/nonexisting.py
+ [255]
+
+ $ hg id
+ loading pre-identify.npmd hook failed:
+ abort: No module named repo!
+ [255]
+
$ cd ../../b
make sure --traceback works on hook import failure