--- a/hgext/convert/hg.py Sun Feb 01 08:24:08 2015 +0900
+++ b/hgext/convert/hg.py Sun Feb 01 18:47:04 2015 -0600
@@ -26,7 +26,7 @@
from common import NoRepo, commit, converter_source, converter_sink
import re
-sha1re = re.compile(r'\b[0-9a-f]{6,40}\b')
+sha1re = re.compile(r'\b[0-9a-f]{12,40}\b')
class mercurial_sink(converter_sink):
def __init__(self, ui, path):
--- a/hgext/largefiles/overrides.py Sun Feb 01 08:24:08 2015 +0900
+++ b/hgext/largefiles/overrides.py Sun Feb 01 18:47:04 2015 -0600
@@ -316,9 +316,14 @@
for i in range(0, len(m._files)):
standin = lfutil.standin(m._files[i])
+ # If the "standin" is a directory, append instead of replace to
+ # support naming a directory on the command line with only
+ # largefiles. The original directory is kept to support normal
+ # files.
if standin in repo[ctx.node()]:
m._files[i] = standin
- elif m._files[i] not in repo[ctx.node()]:
+ elif m._files[i] not in repo[ctx.node()] \
+ and repo.wvfs.isdir(standin):
m._files.append(standin)
pats.add(standin)
--- a/mercurial/context.py Sun Feb 01 08:24:08 2015 +0900
+++ b/mercurial/context.py Sun Feb 01 18:47:04 2015 -0600
@@ -22,41 +22,6 @@
# dirty in the working copy.
_newnode = '!' * 21
-def _adjustlinkrev(repo, path, filelog, fnode, srcrev, inclusive=False):
- """return the first ancestor of <srcrev> introducting <fnode>
-
- If the linkrev of the file revision does not point to an ancestor of
- srcrev, we'll walk down the ancestors until we find one introducing this
- file revision.
-
- :repo: a localrepository object (used to access changelog and manifest)
- :path: the file path
- :fnode: the nodeid of the file revision
- :filelog: the filelog of this path
- :srcrev: the changeset revision we search ancestors from
- :inclusive: if true, the src revision will also be checked
- """
- cl = repo.unfiltered().changelog
- ma = repo.manifest
- # fetch the linkrev
- fr = filelog.rev(fnode)
- lkr = filelog.linkrev(fr)
- # check if this linkrev is an ancestor of srcrev
- anc = cl.ancestors([srcrev], lkr, inclusive=inclusive)
- if lkr not in anc:
- for a in anc:
- ac = cl.read(a) # get changeset data (we avoid object creation).
- if path in ac[3]: # checking the 'files' field.
- # The file has been touched, check if the content is similar
- # to the one we search for.
- if fnode == ma.readfast(ac[0]).get(path):
- return a
- # In theory, we should never get out of that loop without a result. But
- # if manifest uses a buggy file revision (not children of the one it
- # replaces) we could. Such a buggy situation will likely result is crash
- # somewhere else at to some point.
- return lkr
-
class basectx(object):
"""A basectx object represents the common logic for its children:
changectx: read-only context that is already present in the repo,
@@ -668,6 +633,11 @@
return self._changeid
elif '_changectx' in self.__dict__:
return self._changectx.rev()
+ elif '_descendantrev' in self.__dict__:
+ # this file context was created from a revision with a known
+ # descendant, we can (lazily) correct for linkrev aliases
+ return self._adjustlinkrev(self._path, self._filelog,
+ self._filenode, self._descendantrev)
else:
return self._filelog.linkrev(self._filerev)
@@ -781,6 +751,49 @@
return True
+ def _adjustlinkrev(self, path, filelog, fnode, srcrev, inclusive=False):
+ """return the first ancestor of <srcrev> introducting <fnode>
+
+ If the linkrev of the file revision does not point to an ancestor of
+ srcrev, we'll walk down the ancestors until we find one introducing
+ this file revision.
+
+ :repo: a localrepository object (used to access changelog and manifest)
+ :path: the file path
+ :fnode: the nodeid of the file revision
+ :filelog: the filelog of this path
+ :srcrev: the changeset revision we search ancestors from
+ :inclusive: if true, the src revision will also be checked
+ """
+ repo = self._repo
+ cl = repo.unfiltered().changelog
+ ma = repo.manifest
+ # fetch the linkrev
+ fr = filelog.rev(fnode)
+ lkr = filelog.linkrev(fr)
+ # hack to reuse ancestor computation when searching for renames
+ memberanc = getattr(self, '_ancestrycontext', None)
+ iteranc = None
+ if memberanc is None:
+ memberanc = iteranc = cl.ancestors([srcrev], lkr,
+ inclusive=inclusive)
+ # check if this linkrev is an ancestor of srcrev
+ if lkr not in memberanc:
+ if iteranc is None:
+ iteranc = cl.ancestors([srcrev], lkr, inclusive=inclusive)
+ for a in iteranc:
+ ac = cl.read(a) # get changeset data (we avoid object creation)
+ if path in ac[3]: # checking the 'files' field.
+ # The file has been touched, check if the content is
+ # similar to the one we search for.
+ if fnode == ma.readfast(ac[0]).get(path):
+ return a
+ # In theory, we should never get out of that loop without a result.
+ # But if manifest uses a buggy file revision (not children of the
+ # one it replaces) we could. Such a buggy situation will likely
+ # result is crash somewhere else at to some point.
+ return lkr
+
def introrev(self):
"""return the rev of the changeset which introduced this file revision
@@ -795,8 +808,8 @@
noctx = not ('_changeid' in attrs or '_changectx' in attrs)
if noctx or self.rev() == lkr:
return self.linkrev()
- return _adjustlinkrev(self._repo, self._path, self._filelog,
- self._filenode, self.rev(), inclusive=True)
+ return self._adjustlinkrev(self._path, self._filelog, self._filenode,
+ self.rev(), inclusive=True)
def parents(self):
_path = self._path
@@ -822,9 +835,15 @@
# If self is associated with a changeset (probably explicitly
# fed), ensure the created filectx is associated with a
# changeset that is an ancestor of self.changectx.
- rev = _adjustlinkrev(self._repo, path, l, fnode, self.rev())
- fctx = filectx(self._repo, path, fileid=fnode, filelog=l,
- changeid=rev)
+ # This lets us later use _adjustlinkrev to get a correct link.
+ fctx = filectx(self._repo, path, fileid=fnode, filelog=l)
+ fctx._descendantrev = self.rev()
+ fctx._ancestrycontext = getattr(self, '_ancestrycontext', None)
+ elif '_descendantrev' in vars(self):
+ # Otherwise propagate _descendantrev if we have one associated.
+ fctx = filectx(self._repo, path, fileid=fnode, filelog=l)
+ fctx._descendantrev = self._descendantrev
+ fctx._ancestrycontext = getattr(self, '_ancestrycontext', None)
else:
fctx = filectx(self._repo, path, fileid=fnode, filelog=l)
ret.append(fctx)
@@ -944,7 +963,7 @@
cut = followfirst and 1 or None
while True:
for parent in c.parents()[:cut]:
- visit[(parent.rev(), parent.node())] = parent
+ visit[(parent.linkrev(), parent.filenode())] = parent
if not visit:
break
c = visit.pop(max(visit))
--- a/mercurial/copies.py Sun Feb 01 08:24:08 2015 +0900
+++ b/mercurial/copies.py Sun Feb 01 18:47:04 2015 -0600
@@ -133,7 +133,7 @@
for f in fctx.ancestors():
if am.get(f.path(), None) == f.filenode():
return f
- if f.rev() < limit:
+ if limit >= 0 and f.linkrev() < limit and f.rev() < limit:
return None
def _dirstatecopies(d):
@@ -170,8 +170,11 @@
missing = set(b.manifest().iterkeys())
missing.difference_update(a.manifest().iterkeys())
+ ancestrycontext = a._repo.changelog.ancestors([b.rev()], inclusive=True)
for f in missing:
- ofctx = _tracefile(b[f], am, limit)
+ fctx = b[f]
+ fctx._ancestrycontext = ancestrycontext
+ ofctx = _tracefile(fctx, am, limit)
if ofctx:
cm[f] = ofctx.path()
--- a/mercurial/exchange.py Sun Feb 01 08:24:08 2015 +0900
+++ b/mercurial/exchange.py Sun Feb 01 18:47:04 2015 -0600
@@ -946,8 +946,9 @@
scommon = set(common)
filteredrheads = []
for n in rheads:
- if n in nm and n not in scommon:
- common.append(n)
+ if n in nm:
+ if n not in scommon:
+ common.append(n)
else:
filteredrheads.append(n)
if not filteredrheads:
--- a/mercurial/merge.py Sun Feb 01 08:24:08 2015 +0900
+++ b/mercurial/merge.py Sun Feb 01 18:47:04 2015 -0600
@@ -741,7 +741,15 @@
numupdates = sum(len(l) for m, l in actions.items() if m != 'k')
+ def dirtysubstate():
+ # mark '.hgsubstate' as possibly dirty forcibly, because
+ # modified '.hgsubstate' is misunderstood as clean,
+ # when both st_size/st_mtime of '.hgsubstate' aren't changed,
+ # even if "submerge" fails and '.hgsubstate' is inconsistent
+ repo.dirstate.normallookup('.hgsubstate')
+
if [a for a in actions['r'] if a[0] == '.hgsubstate']:
+ dirtysubstate()
subrepo.submerge(repo, wctx, mctx, wctx, overwrite)
# remove in parallel (must come first)
@@ -760,6 +768,7 @@
updated = len(actions['g'])
if [a for a in actions['g'] if a[0] == '.hgsubstate']:
+ dirtysubstate()
subrepo.submerge(repo, wctx, mctx, wctx, overwrite)
# forget (manifest only, just log it) (must come first)
@@ -785,6 +794,7 @@
z += 1
progress(_updating, z, item=f, total=numupdates, unit=_files)
if f == '.hgsubstate': # subrepo states need updating
+ dirtysubstate()
subrepo.submerge(repo, wctx, mctx, wctx.ancestor(mctx),
overwrite)
continue
--- a/mercurial/obsolete.py Sun Feb 01 08:24:08 2015 +0900
+++ b/mercurial/obsolete.py Sun Feb 01 18:47:04 2015 -0600
@@ -462,6 +462,16 @@
"""The flags field of the marker"""
return self._data[2]
+def _checkinvalidmarkers(obsstore):
+ """search for marker with invalid data and raise error if needed
+
+ Exist as a separated function to allow the evolve extension for a more
+ subtle handling.
+ """
+ if node.nullid in obsstore.precursors:
+ raise util.Abort(_('bad obsolescence marker detected: '
+ 'invalid successors nullid'))
+
class obsstore(object):
"""Store obsolete markers
@@ -598,9 +608,8 @@
if parents is not None:
for p in parents:
self.children.setdefault(p, set()).add(mark)
- if node.nullid in self.precursors:
- raise util.Abort(_('bad obsolescence marker detected: '
- 'invalid successors nullid'))
+ _checkinvalidmarkers(self)
+
def relevantmarkers(self, nodes):
"""return a set of all obsolescence markers relevant to a set of nodes.
--- a/mercurial/revset.py Sun Feb 01 08:24:08 2015 +0900
+++ b/mercurial/revset.py Sun Feb 01 18:47:04 2015 -0600
@@ -496,7 +496,8 @@
if kind == 'literal':
bmrev = repo._bookmarks.get(pattern, None)
if not bmrev:
- raise util.Abort(_("bookmark '%s' does not exist") % bm)
+ raise error.RepoLookupError(_("bookmark '%s' does not exist")
+ % bm)
bms.add(repo[bmrev].rev())
else:
matchrevs = set()
@@ -504,8 +505,8 @@
if matcher(name):
matchrevs.add(bmrev)
if not matchrevs:
- raise util.Abort(_("no bookmarks exist that match '%s'")
- % pattern)
+ raise error.RepoLookupError(_("no bookmarks exist"
+ " that match '%s'") % pattern)
for bmrev in matchrevs:
bms.add(repo[bmrev].rev())
else:
@@ -1262,15 +1263,16 @@
namespaces = set()
if kind == 'literal':
if pattern not in repo.names:
- raise util.Abort(_("namespace '%s' does not exist") % ns)
+ raise error.RepoLookupError(_("namespace '%s' does not exist")
+ % ns)
namespaces.add(repo.names[pattern])
else:
for name, ns in repo.names.iteritems():
if matcher(name):
namespaces.add(ns)
if not namespaces:
- raise util.Abort(_("no namespace exists that match '%s'")
- % pattern)
+ raise error.RepoLookupError(_("no namespace exists"
+ " that match '%s'") % pattern)
names = set()
for ns in namespaces:
@@ -1816,7 +1818,8 @@
# avoid resolving all tags
tn = repo._tagscache.tags.get(pattern, None)
if tn is None:
- raise util.Abort(_("tag '%s' does not exist") % pattern)
+ raise error.RepoLookupError(_("tag '%s' does not exist")
+ % pattern)
s = set([repo[tn].rev()])
else:
s = set([cl.rev(n) for t, n in repo.tagslist() if matcher(t)])
--- a/mercurial/templatekw.py Sun Feb 01 08:24:08 2015 +0900
+++ b/mercurial/templatekw.py Sun Feb 01 18:47:04 2015 -0600
@@ -382,6 +382,13 @@
names = ns.names(repo, ctx.node())
return showlist(ns.templatename, names, plural=namespace, **args)
+# don't remove "showtags" definition, even though namespaces will put
+# a helper function for "tags" keyword into "keywords" map automatically,
+# because online help text is built without namespaces initialization
+def showtags(**args):
+ """:tags: List of strings. Any tags associated with the changeset."""
+ return shownames('tags', **args)
+
# keywords are callables like:
# fn(repo, ctx, templ, cache, revcache, **args)
# with:
@@ -420,6 +427,7 @@
'phaseidx': showphaseidx,
'rev': showrev,
'subrepos': showsubrepos,
+ 'tags': showtags,
}
def _showparents(**args):
--- a/tests/test-bookmarks.t Sun Feb 01 08:24:08 2015 +0900
+++ b/tests/test-bookmarks.t Sun Feb 01 18:47:04 2015 -0600
@@ -133,8 +133,13 @@
$ hg log -r 'bookmark(unknown)'
- abort: bookmark 'unknown' does not exist
+ abort: bookmark 'unknown' does not exist!
[255]
+ $ hg log -r 'bookmark("re:unknown")'
+ abort: no bookmarks exist that match 'unknown'!
+ [255]
+ $ hg log -r 'present(bookmark("literal:unknown"))'
+ $ hg log -r 'present(bookmark("re:unknown"))'
$ hg help revsets | grep 'bookmark('
"bookmark([name])"
--- a/tests/test-extdiff.t Sun Feb 01 08:24:08 2015 +0900
+++ b/tests/test-extdiff.t Sun Feb 01 18:47:04 2015 -0600
@@ -179,7 +179,7 @@
TODO
#else
$ hg --debug odd | grep '^running'
- running "/bin/echo --foo='sp ace' 'sp ace' --bar='sp ace' 'sp ace'" in * (glob)
+ running "*/bin/echo --foo='sp ace' 'sp ace' --bar='sp ace' 'sp ace'" in * (glob)
#endif
#if execbit
--- a/tests/test-log.t Sun Feb 01 08:24:08 2015 +0900
+++ b/tests/test-log.t Sun Feb 01 18:47:04 2015 -0600
@@ -45,6 +45,13 @@
$ hg mv dir/b e
$ hg ci -me -d '5 0'
+Make sure largefiles doesn't interfere with logging a regular file
+ $ hg log a --config extensions.largefiles=
+ changeset: 0:9161b9aeaf16
+ user: test
+ date: Thu Jan 01 00:00:01 1970 +0000
+ summary: a
+
$ hg log a
changeset: 0:9161b9aeaf16
user: test
@@ -1629,6 +1636,12 @@
|
o a
+Ensure that largefiles doesn't intefere with following a normal file
+ $ hg --config extensions.largefiles= log -f d -T '{desc}' -G
+ @ c
+ |
+ o a
+
$ hg log -f d/a -T '{desc}' -G
@ c
|
--- a/tests/test-revset.t Sun Feb 01 08:24:08 2015 +0900
+++ b/tests/test-revset.t Sun Feb 01 18:47:04 2015 -0600
@@ -709,7 +709,7 @@
we can use patterns when searching for tags
$ log 'tag("1..*")'
- abort: tag '1..*' does not exist
+ abort: tag '1..*' does not exist!
[255]
$ log 'tag("re:1..*")'
6
@@ -720,11 +720,17 @@
$ log 'tag("re:0..*")'
$ log 'tag(unknown)'
- abort: tag 'unknown' does not exist
+ abort: tag 'unknown' does not exist!
[255]
+ $ log 'tag("re:unknown")'
+ $ log 'present(tag("unknown"))'
+ $ log 'present(tag("re:unknown"))'
$ log 'branch(unknown)'
abort: unknown revision 'unknown'!
[255]
+ $ log 'branch("re:unknown")'
+ $ log 'present(branch("unknown"))'
+ $ log 'present(branch("re:unknown"))'
$ log 'user(bob)'
2
@@ -772,6 +778,15 @@
3
1
+ $ log 'named("unknown")'
+ abort: namespace 'unknown' does not exist!
+ [255]
+ $ log 'named("re:unknown")'
+ abort: no namespace exists that match 'unknown'!
+ [255]
+ $ log 'present(named("unknown"))'
+ $ log 'present(named("re:unknown"))'
+
issue2437
$ log '3 and p1(5)'
--- a/tests/test-subrepo.t Sun Feb 01 08:24:08 2015 +0900
+++ b/tests/test-subrepo.t Sun Feb 01 18:47:04 2015 -0600
@@ -758,6 +758,8 @@
$ echo issue3276_ok > repo/s/b
$ hg -R repo2 push -f -q
+ $ touch -t 200001010000 repo/.hgsubstate
+ $ hg -R repo status --config debug.dirstate.delaywrite=2 repo/.hgsubstate
$ hg -R repo update
b: untracked file differs
abort: untracked files in working directory differ from files in requested revision (in subrepo s)
@@ -766,6 +768,7 @@
$ cat repo/s/b
issue3276_ok
$ rm repo/s/b
+ $ touch -t 200001010000 repo/.hgsubstate
$ hg -R repo revert --all
reverting repo/.hgsubstate (glob)
reverting subrepo s
--- a/tests/test-treediscovery.t Sun Feb 01 08:24:08 2015 +0900
+++ b/tests/test-treediscovery.t Sun Feb 01 18:47:04 2015 -0600
@@ -520,7 +520,7 @@
"GET /?cmd=heads HTTP/1.1" 200 -
"GET /?cmd=branches HTTP/1.1" 200 - x-hgarg-1:nodes=d8f638ac69e9ae8dea4f09f11d696546a912d961
"GET /?cmd=between HTTP/1.1" 200 - x-hgarg-1:pairs=d8f638ac69e9ae8dea4f09f11d696546a912d961-d57206cc072a18317c1e381fb60aa31bd3401785
- "GET /?cmd=changegroupsubset HTTP/1.1" 200 - x-hgarg-1:bases=d8f638ac69e9ae8dea4f09f11d696546a912d961&heads=d8f638ac69e9ae8dea4f09f11d696546a912d961+2c8d5d5ec612be65cdfdeac78b7662ab1696324a
+ "GET /?cmd=changegroupsubset HTTP/1.1" 200 - x-hgarg-1:bases=d8f638ac69e9ae8dea4f09f11d696546a912d961&heads=d8f638ac69e9ae8dea4f09f11d696546a912d961
"GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=phases
"GET /?cmd=capabilities HTTP/1.1" 200 -
"GET /?cmd=heads HTTP/1.1" 200 -