--- a/hgext/churn.py Mon Mar 31 18:49:15 2008 +0200
+++ b/hgext/churn.py Mon Mar 31 21:49:26 2008 -0500
@@ -155,7 +155,7 @@
for l in f.readlines():
l = l.strip()
- alias, actual = l.split(" ")
+ alias, actual = l.split()
aliases[alias] = actual
return aliases
--- a/mercurial/ancestor.py Mon Mar 31 18:49:15 2008 +0200
+++ b/mercurial/ancestor.py Mon Mar 31 21:49:26 2008 -0500
@@ -81,54 +81,3 @@
gx = x.next()
except StopIteration:
return None
-
-def symmetricdifference(a, b, pfunc):
- """symmetric difference of the sets of ancestors of a and b
-
- I.e. revisions that are ancestors of a or b, but not both.
- """
- # basic idea:
- # - mark a and b with different colors
- # - walk the graph in topological order with the help of a heap;
- # for each revision r:
- # - if r has only one color, we want to return it
- # - add colors[r] to its parents
- #
- # We keep track of the number of revisions in the heap that
- # we may be interested in. We stop walking the graph as soon
- # as this number reaches 0.
- if a == b:
- return [a]
-
- WHITE = 1
- BLACK = 2
- ALLCOLORS = WHITE | BLACK
- colors = {a: WHITE, b: BLACK}
-
- visit = [-a, -b]
- heapq.heapify(visit)
- n_wanted = len(visit)
- ret = []
-
- while n_wanted:
- r = -heapq.heappop(visit)
- wanted = colors[r] != ALLCOLORS
- n_wanted -= wanted
- if wanted:
- ret.append(r)
-
- for p in pfunc(r):
- if p not in colors:
- # first time we see p; add it to visit
- n_wanted += wanted
- colors[p] = colors[r]
- heapq.heappush(visit, -p)
- elif colors[p] != ALLCOLORS and colors[p] != colors[r]:
- # at first we thought we wanted p, but now
- # we know we don't really want it
- n_wanted -= 1
- colors[p] |= colors[r]
-
- del colors[r]
-
- return ret
--- a/mercurial/commands.py Mon Mar 31 18:49:15 2008 +0200
+++ b/mercurial/commands.py Mon Mar 31 21:49:26 2008 -0500
@@ -227,7 +227,10 @@
raise util.Abort(_('cannot use --parent on non-merge changeset'))
parent = p1
+ # the backout should appear on the same branch
+ branch = repo.dirstate.branch()
hg.clean(repo, node, show_stats=False)
+ repo.dirstate.setbranch(branch)
revert_opts = opts.copy()
revert_opts['date'] = None
revert_opts['all'] = True
--- a/mercurial/copies.py Mon Mar 31 18:49:15 2008 +0200
+++ b/mercurial/copies.py Mon Mar 31 21:49:26 2008 -0500
@@ -7,7 +7,7 @@
from node import nullid, nullrev
from i18n import _
-import util, ancestor
+import util, heapq
def _nonoverlap(d1, d2, d3):
"Return list of elements in d1 not in d2 or d3"
@@ -35,40 +35,81 @@
old = {}
seen = {}
orig = fctx.path()
- visit = [fctx]
+ visit = [(fctx, 0)]
while visit:
- fc = visit.pop()
+ fc, depth = visit.pop()
s = str(fc)
if s in seen:
continue
seen[s] = 1
if fc.path() != orig and fc.path() not in old:
- old[fc.path()] = 1
+ old[fc.path()] = (depth, fc.path()) # remember depth
if fc.rev() < limit and fc.rev() is not None:
continue
- visit += fc.parents()
+ visit += [(p, depth - 1) for p in fc.parents()]
- old = old.keys()
+ # return old names sorted by depth
+ old = old.values()
old.sort()
- return old
+ return [o[1] for o in old]
+
+def _findlimit(repo, a, b):
+ "find the earliest revision that's an ancestor of a or b but not both"
+ # basic idea:
+ # - mark a and b with different sides
+ # - if a parent's children are all on the same side, the parent is
+ # on that side, otherwise it is on no side
+ # - walk the graph in topological order with the help of a heap;
+ # - add unseen parents to side map
+ # - clear side of any parent that has children on different sides
+ # - track number of interesting revs that might still be on a side
+ # - track the lowest interesting rev seen
+ # - quit when interesting revs is zero
+
+ cl = repo.changelog
+ working = cl.count() # pseudo rev for the working directory
+ if a is None:
+ a = working
+ if b is None:
+ b = working
-def copies(repo, c1, c2, ca):
+ side = {a: -1, b: 1}
+ visit = [-a, -b]
+ heapq.heapify(visit)
+ interesting = len(visit)
+ limit = working
+
+ while interesting:
+ r = -heapq.heappop(visit)
+ if r == working:
+ parents = [cl.rev(p) for p in repo.dirstate.parents()]
+ else:
+ parents = cl.parentrevs(r)
+ for p in parents:
+ if p not in side:
+ # first time we see p; add it to visit
+ side[p] = side[r]
+ if side[p]:
+ interesting += 1
+ heapq.heappush(visit, -p)
+ elif side[p] and side[p] != side[r]:
+ # p was interesting but now we know better
+ side[p] = 0
+ interesting -= 1
+ if side[r]:
+ limit = r # lowest rev visited
+ interesting -= 1
+ return limit
+
+def copies(repo, c1, c2, ca, checkdirs=False):
"""
Find moves and copies between context c1 and c2
"""
# avoid silly behavior for update from empty dir
- if not c1 or not c2:
+ if not c1 or not c2 or c1 == c2:
return {}, {}
- rev1, rev2 = c1.rev(), c2.rev()
- if rev1 is None: # c1 is a workingctx
- rev1 = c1.parents()[0].rev()
- if rev2 is None: # c2 is a workingctx
- rev2 = c2.parents()[0].rev()
- pr = repo.changelog.parentrevs
- def parents(rev):
- return [p for p in pr(rev) if p != nullrev]
- limit = min(ancestor.symmetricdifference(rev1, rev2, parents))
+ limit = _findlimit(repo, c1.rev(), c2.rev())
m1 = c1.manifest()
m2 = c2.manifest()
ma = ca.manifest()
@@ -97,15 +138,12 @@
c2 = ctx(of, m2[of])
ca = c1.ancestor(c2)
# related and named changed on only one side?
- if ca and ca.path() == f or ca.path() == c2.path():
+ if ca and (ca.path() == f or ca.path() == c2.path()):
if c1 != ca or c2 != ca: # merge needed?
copy[f] = of
elif of in ma:
diverge.setdefault(of, []).append(f)
- if not repo.ui.configbool("merge", "followcopies", True):
- return {}, {}
-
repo.ui.debug(_(" searching for copies back to rev %d\n") % limit)
u1 = _nonoverlap(m1, m2, ma)
@@ -139,7 +177,7 @@
repo.ui.debug(_(" %s -> %s %s\n") % (f, fullcopy[f], note))
del diverge2
- if not fullcopy or not repo.ui.configbool("merge", "followdirs", True):
+ if not fullcopy or not checkdirs:
return copy, diverge
repo.ui.debug(_(" checking for directory renames\n"))
@@ -186,8 +224,10 @@
for d in dirmove:
if f.startswith(d):
# new file added in a directory that was moved, move it
- copy[f] = dirmove[d] + f[len(d):]
- repo.ui.debug(_(" file %s -> %s\n") % (f, copy[f]))
+ df = dirmove[d] + f[len(d):]
+ if df not in copy:
+ copy[f] = df
+ repo.ui.debug(_(" file %s -> %s\n") % (f, copy[f]))
break
return copy, diverge
--- a/mercurial/merge.py Mon Mar 31 18:49:15 2008 +0200
+++ b/mercurial/merge.py Mon Mar 31 21:49:26 2008 -0500
@@ -101,7 +101,9 @@
action.append((f, m) + args)
if pa and not (backwards or overwrite):
- copy, diverge = copies.copies(repo, p1, p2, pa)
+ if repo.ui.configbool("merge", "followcopies", True):
+ dirs = repo.ui.configbool("merge", "followdirs", True)
+ copy, diverge = copies.copies(repo, p1, p2, pa, dirs)
copied = dict.fromkeys(copy.values())
for of, fl in diverge.items():
act("divergent renames", "dr", of, fl)
--- a/tests/test-backout.out Mon Mar 31 18:49:15 2008 +0200
+++ b/tests/test-backout.out Mon Mar 31 21:49:26 2008 -0500
@@ -74,7 +74,7 @@
adding file2
removing file1
created new head
-changeset 3:f1c642b1d8e5 backs out changeset 1:bf1602f437f3
+changeset 3:d4e8f6db59fb backs out changeset 1:bf1602f437f3
the backout changeset is a new head - do not forget to merge
(use "backout --merge" if you want to auto-merge)
% on branch2 with branch1 not merged, so file1 should still exist:
@@ -85,10 +85,11 @@
% on branch2 with branch1 merged, so file1 should be gone:
0 files updated, 0 files merged, 1 files removed, 0 files unresolved
(branch merge, don't forget to commit)
-21d4dc6f9a41 (branch2) tip
+22149cdde76d (branch2) tip
C default
C file2
% on branch1, so no file1 and file2:
-0 files updated, 0 files merged, 1 files removed, 0 files unresolved
-f1c642b1d8e5 (branch1)
+1 files updated, 0 files merged, 1 files removed, 0 files unresolved
+bf1602f437f3 (branch1)
C default
+C file1
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/test-diff-copy-depth Mon Mar 31 21:49:26 2008 -0500
@@ -0,0 +1,31 @@
+#!/bin/bash
+
+for i in aaa zzz; do
+ hg init t
+ cd t
+
+ echo "-- With $i"
+
+ touch file
+ hg add file
+ hg ci -m "Add"
+
+ hg cp file $i
+ hg ci -m "a -> $i"
+
+ hg cp $i other-file
+ echo "different" >> $i
+ hg ci -m "$i -> other-file"
+
+ hg cp other-file somename
+
+ echo "Status":
+ hg st -C
+ echo
+ echo "Diff:"
+ hg diff -g
+ echo
+
+ cd ..
+ rm -rf t
+done
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/test-diff-copy-depth.out Mon Mar 31 21:49:26 2008 -0500
@@ -0,0 +1,20 @@
+-- With aaa
+Status:
+A somename
+ other-file
+
+Diff:
+diff --git a/other-file b/somename
+copy from other-file
+copy to somename
+
+-- With zzz
+Status:
+A somename
+ other-file
+
+Diff:
+diff --git a/other-file b/somename
+copy from other-file
+copy to somename
+
--- a/tests/test-mv-cp-st-diff Mon Mar 31 18:49:15 2008 +0200
+++ b/tests/test-mv-cp-st-diff Mon Mar 31 21:49:26 2008 -0500
@@ -11,12 +11,17 @@
# set up a boring main branch
add a a
hg add a
+mkdir x
+add x/x x
+hg add x/x
hg ci -m0
add a m1
hg ci -m1
add a m2
+add x/y y1
+hg add x/y
hg ci -m2
show()
@@ -59,6 +64,7 @@
echo
}
+
tb "add a a1" "add a a2" "hg mv a b" "rename in working dir"
tb "add a a1" "add a a2" "hg cp a b" "copy in working dir"
tb "hg mv a b" "add b b1" "add b w" "single rename"
@@ -66,3 +72,5 @@
tb "hg mv a b" "hg mv b c" "hg mv c d" "rename chain"
tb "hg cp a b" "hg cp b c" "hg cp c d" "copy chain"
tb "add a a1" "hg mv a b" "hg mv b a" "circular rename"
+
+tb "hg mv x y" "add y/x x1" "add y/x x2" "directory move"
--- a/tests/test-mv-cp-st-diff.out Mon Mar 31 18:49:15 2008 +0200
+++ b/tests/test-mv-cp-st-diff.out Mon Mar 31 21:49:26 2008 -0500
@@ -30,6 +30,7 @@
A b
a
R a
+R x/y
diff --git a/a b/b
rename from a
@@ -43,6 +44,12 @@
+0
+a1
+a2
+diff --git a/x/y b/x/y
+deleted file mode 100644
+--- a/x/y
++++ /dev/null
+@@ -1,1 +0,0 @@
+-y1
- root to parent: --rev 0 --rev .
M a
@@ -70,6 +77,7 @@
- branch to parent: --rev 2 --rev .
M a
+R x/y
diff --git a/a b/a
--- a/a
@@ -81,9 +89,16 @@
+0
+a1
+a2
+diff --git a/x/y b/x/y
+deleted file mode 100644
+--- a/x/y
++++ /dev/null
+@@ -1,1 +0,0 @@
+-y1
- parent to branch: --rev . --rev 2
M a
+A x/y
diff --git a/a b/a
--- a/a
@@ -95,6 +110,12 @@
-a2
+m1
+m2
+diff --git a/x/y b/x/y
+new file mode 100644
+--- /dev/null
++++ b/x/y
+@@ -0,0 +1,1 @@
++y1
created new head
@@ -136,6 +157,7 @@
M a
A b
a
+R x/y
diff --git a/a b/a
--- a/a
@@ -159,6 +181,12 @@
+1
+a1
+a2
+diff --git a/x/y b/x/y
+deleted file mode 100644
+--- a/x/y
++++ /dev/null
+@@ -1,1 +0,0 @@
+-y1
- root to parent: --rev 0 --rev .
M a
@@ -186,6 +214,7 @@
- branch to parent: --rev 2 --rev .
M a
+R x/y
diff --git a/a b/a
--- a/a
@@ -197,9 +226,16 @@
+1
+a1
+a2
+diff --git a/x/y b/x/y
+deleted file mode 100644
+--- a/x/y
++++ /dev/null
+@@ -1,1 +0,0 @@
+-y1
- parent to branch: --rev . --rev 2
M a
+A x/y
diff --git a/a b/a
--- a/a
@@ -211,6 +247,12 @@
-a2
+m1
+m2
+diff --git a/x/y b/x/y
+new file mode 100644
+--- /dev/null
++++ b/x/y
+@@ -0,0 +1,1 @@
++y1
created new head
@@ -248,6 +290,7 @@
A b
a
R a
+R x/y
diff --git a/a b/b
rename from a
@@ -261,6 +304,12 @@
+2
+b1
+w
+diff --git a/x/y b/x/y
+deleted file mode 100644
+--- a/x/y
++++ /dev/null
+@@ -1,1 +0,0 @@
+-y1
- root to parent: --rev 0 --rev .
A b
@@ -296,6 +345,7 @@
A b
a
R a
+R x/y
diff --git a/a b/b
rename from a
@@ -308,10 +358,17 @@
-m2
+2
+b1
+diff --git a/x/y b/x/y
+deleted file mode 100644
+--- a/x/y
++++ /dev/null
+@@ -1,1 +0,0 @@
+-y1
- parent to branch: --rev . --rev 2
A a
b
+A x/y
R b
diff --git a/b b/a
@@ -325,6 +382,12 @@
-b1
+m1
+m2
+diff --git a/x/y b/x/y
+new file mode 100644
+--- /dev/null
++++ b/x/y
+@@ -0,0 +1,1 @@
++y1
created new head
@@ -367,6 +430,7 @@
M a
A b
a
+R x/y
diff --git a/a b/a
--- a/a
@@ -388,6 +452,12 @@
-m2
+3
+b1
+diff --git a/x/y b/x/y
+deleted file mode 100644
+--- a/x/y
++++ /dev/null
+@@ -1,1 +0,0 @@
+-y1
- root to parent: --rev 0 --rev .
M a
@@ -433,6 +503,7 @@
M a
A b
a
+R x/y
diff --git a/a b/a
--- a/a
@@ -453,9 +524,16 @@
-m2
+3
+b1
+diff --git a/x/y b/x/y
+deleted file mode 100644
+--- a/x/y
++++ /dev/null
+@@ -1,1 +0,0 @@
+-y1
- parent to branch: --rev . --rev 2
M a
+A x/y
R b
diff --git a/a b/a
@@ -474,6 +552,12 @@
-a
-3
-b1
+diff --git a/x/y b/x/y
+new file mode 100644
+--- /dev/null
++++ b/x/y
+@@ -0,0 +1,1 @@
++y1
created new head
@@ -506,6 +590,7 @@
A d
a
R a
+R x/y
diff --git a/a b/d
rename from a
@@ -517,6 +602,12 @@
-m1
-m2
+4
+diff --git a/x/y b/x/y
+deleted file mode 100644
+--- a/x/y
++++ /dev/null
+@@ -1,1 +0,0 @@
+-y1
- root to parent: --rev 0 --rev .
A c
@@ -550,6 +641,7 @@
A c
a
R a
+R x/y
diff --git a/a b/c
rename from a
@@ -561,10 +653,17 @@
-m1
-m2
+4
+diff --git a/x/y b/x/y
+deleted file mode 100644
+--- a/x/y
++++ /dev/null
+@@ -1,1 +0,0 @@
+-y1
- parent to branch: --rev . --rev 2
A a
c
+A x/y
R c
diff --git a/c b/a
@@ -577,6 +676,12 @@
-4
+m1
+m2
+diff --git a/x/y b/x/y
+new file mode 100644
+--- /dev/null
++++ b/x/y
+@@ -0,0 +1,1 @@
++y1
created new head
@@ -638,6 +743,7 @@
a
A d
a
+R x/y
diff --git a/a b/a
--- a/a
@@ -677,6 +783,12 @@
-m1
-m2
+5
+diff --git a/x/y b/x/y
+deleted file mode 100644
+--- a/x/y
++++ /dev/null
+@@ -1,1 +0,0 @@
+-y1
- root to parent: --rev 0 --rev .
M a
@@ -740,6 +852,7 @@
a
A c
a
+R x/y
diff --git a/a b/a
--- a/a
@@ -769,9 +882,16 @@
-m1
-m2
+5
+diff --git a/x/y b/x/y
+deleted file mode 100644
+--- a/x/y
++++ /dev/null
+@@ -1,1 +0,0 @@
+-y1
- parent to branch: --rev . --rev 2
M a
+A x/y
R b
R c
@@ -797,6 +917,12 @@
@@ -1,2 +0,0 @@
-a
-5
+diff --git a/x/y b/x/y
+new file mode 100644
+--- /dev/null
++++ b/x/y
+@@ -0,0 +1,1 @@
++y1
created new head
@@ -824,6 +950,7 @@
- working to branch: --rev 2
M a
+R x/y
diff --git a/a b/a
--- a/a
@@ -834,6 +961,12 @@
-m2
+6
+a1
+diff --git a/x/y b/x/y
+deleted file mode 100644
+--- a/x/y
++++ /dev/null
+@@ -1,1 +0,0 @@
+-y1
- root to parent: --rev 0 --rev .
A b
@@ -869,6 +1002,7 @@
A b
a
R a
+R x/y
diff --git a/a b/b
rename from a
@@ -881,10 +1015,17 @@
-m2
+6
+a1
+diff --git a/x/y b/x/y
+deleted file mode 100644
+--- a/x/y
++++ /dev/null
+@@ -1,1 +0,0 @@
+-y1
- parent to branch: --rev . --rev 2
A a
b
+A x/y
R b
diff --git a/b b/a
@@ -898,5 +1039,182 @@
-a1
+m1
+m2
+diff --git a/x/y b/x/y
+new file mode 100644
+--- /dev/null
++++ b/x/y
+@@ -0,0 +1,1 @@
++y1
+created new head
+moving x/x to y/x
+** directory move **
+** hg mv x y / add y/x x1 / add y/x x2
+- working to parent:
+M y/x
+
+diff --git a/y/x b/y/x
+--- a/y/x
++++ b/y/x
+@@ -1,2 +1,3 @@
+ x
+ x1
++x2
+
+- working to root: --rev 0
+M a
+A y/x
+ x/x
+R x/x
+
+diff --git a/a b/a
+--- a/a
++++ b/a
+@@ -1,1 +1,2 @@
+ a
++7
+diff --git a/x/x b/y/x
+rename from x/x
+rename to y/x
+--- a/x/x
++++ b/y/x
+@@ -1,1 +1,3 @@
+ x
++x1
++x2
+
+- working to branch: --rev 2
+M a
+A y/x
+ x/x
+R x/x
+R x/y
+
+diff --git a/a b/a
+--- a/a
++++ b/a
+@@ -1,3 +1,2 @@
+ a
+-m1
+-m2
++7
+diff --git a/x/y b/x/y
+deleted file mode 100644
+--- a/x/y
++++ /dev/null
+@@ -1,1 +0,0 @@
+-y1
+diff --git a/x/x b/y/x
+rename from x/x
+rename to y/x
+--- a/x/x
++++ b/y/x
+@@ -1,1 +1,3 @@
+ x
++x1
++x2
+
+- root to parent: --rev 0 --rev .
+M a
+A y/x
+ x/x
+R x/x
+
+diff --git a/a b/a
+--- a/a
++++ b/a
+@@ -1,1 +1,2 @@
+ a
++7
+diff --git a/x/x b/y/x
+rename from x/x
+rename to y/x
+--- a/x/x
++++ b/y/x
+@@ -1,1 +1,2 @@
+ x
++x1
+
+- parent to root: --rev . --rev 0
+M a
+A x/x
+ y/x
+R y/x
+
+diff --git a/a b/a
+--- a/a
++++ b/a
+@@ -1,2 +1,1 @@
+ a
+-7
+diff --git a/y/x b/x/x
+rename from y/x
+rename to x/x
+--- a/y/x
++++ b/x/x
+@@ -1,2 +1,1 @@
+ x
+-x1
+
+- branch to parent: --rev 2 --rev .
+M a
+A y/x
+ x/x
+R x/x
+R x/y
+
+diff --git a/a b/a
+--- a/a
++++ b/a
+@@ -1,3 +1,2 @@
+ a
+-m1
+-m2
++7
+diff --git a/x/y b/x/y
+deleted file mode 100644
+--- a/x/y
++++ /dev/null
+@@ -1,1 +0,0 @@
+-y1
+diff --git a/x/x b/y/x
+rename from x/x
+rename to y/x
+--- a/x/x
++++ b/y/x
+@@ -1,1 +1,2 @@
+ x
++x1
+
+- parent to branch: --rev . --rev 2
+M a
+A x/x
+ y/x
+A x/y
+R y/x
+
+diff --git a/a b/a
+--- a/a
++++ b/a
+@@ -1,2 +1,3 @@
+ a
+-7
++m1
++m2
+diff --git a/y/x b/x/x
+rename from y/x
+rename to x/x
+--- a/y/x
++++ b/x/x
+@@ -1,2 +1,1 @@
+ x
+-x1
+diff --git a/x/y b/x/y
+new file mode 100644
+--- /dev/null
++++ b/x/y
+@@ -0,0 +1,1 @@
++y1
+
+