Merge with stable

This commit is contained in:
Matt Mackall 2008-03-31 21:49:26 -05:00
commit 74e8b50e35
10 changed files with 454 additions and 82 deletions

View File

@ -155,7 +155,7 @@ def churn(ui, repo, **opts):
for l in f.readlines():
l = l.strip()
alias, actual = l.split(" ")
alias, actual = l.split()
aliases[alias] = actual
return aliases

View File

@ -81,54 +81,3 @@ def ancestor(a, b, pfunc):
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

View File

@ -227,7 +227,10 @@ def backout(ui, repo, node=None, rev=None, **opts):
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

View File

@ -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 @@ def _findoldnames(fctx, limit):
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 copies(repo, c1, c2, ca):
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
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 @@ def copies(repo, c1, c2, ca):
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 @@ def copies(repo, c1, c2, ca):
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 @@ def copies(repo, c1, c2, ca):
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

View File

@ -101,7 +101,9 @@ def manifestmerge(repo, p1, p2, pa, overwrite, partial):
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)

View File

@ -74,7 +74,7 @@ marked working directory as branch branch2
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 @@ C file2
% 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

View File

@ -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

View File

@ -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

View File

@ -11,12 +11,17 @@ cd t
# 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 @@ tb()
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 cp a b" "add b b1" "add a w" "single copy"
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"

View File

@ -30,6 +30,7 @@ rename to b
A b
a
R a
R x/y
diff --git a/a b/b
rename from a
@ -43,6 +44,12 @@ rename to b
+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 @@ diff --git a/a b/a
- branch to parent: --rev 2 --rev .
M a
R x/y
diff --git a/a b/a
--- a/a
@ -81,9 +89,16 @@ diff --git a/a b/a
+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 @@ diff --git a/a b/a
-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 @@ copy to b
M a
A b
a
R x/y
diff --git a/a b/a
--- a/a
@ -159,6 +181,12 @@ copy to b
+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 @@ diff --git a/a b/a
- branch to parent: --rev 2 --rev .
M a
R x/y
diff --git a/a b/a
--- a/a
@ -197,9 +226,16 @@ diff --git a/a b/a
+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 @@ diff --git a/a b/a
-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 @@ rename to b
A b
a
R a
R x/y
diff --git a/a b/b
rename from a
@ -261,6 +304,12 @@ rename to b
+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 @@ rename to a
A b
a
R a
R x/y
diff --git a/a b/b
rename from a
@ -308,10 +358,17 @@ rename to b
-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 @@ rename to a
-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 @@ copy to b
M a
A b
a
R x/y
diff --git a/a b/a
--- a/a
@ -388,6 +452,12 @@ copy to b
-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 @@ deleted file mode 100644
M a
A b
a
R x/y
diff --git a/a b/a
--- a/a
@ -453,9 +524,16 @@ copy to b
-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 @@ deleted file mode 100644
-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 @@ rename to d
A d
a
R a
R x/y
diff --git a/a b/d
rename from a
@ -517,6 +602,12 @@ rename to d
-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 @@ rename to a
A c
a
R a
R x/y
diff --git a/a b/c
rename from a
@ -561,10 +653,17 @@ rename to c
-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 @@ rename to a
-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 c
a
A d
a
R x/y
diff --git a/a b/a
--- a/a
@ -677,6 +783,12 @@ copy to d
-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 b
a
A c
a
R x/y
diff --git a/a b/a
--- a/a
@ -769,9 +882,16 @@ copy to c
-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 @@ deleted file mode 100644
@@ -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 @@ diff --git a/a b/a
- working to branch: --rev 2
M a
R x/y
diff --git a/a b/a
--- a/a
@ -834,6 +961,12 @@ diff --git a/a b/a
-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 @@ rename to a
A b
a
R a
R x/y
diff --git a/a b/b
rename from a
@ -881,10 +1015,17 @@ rename to b
-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 @@ rename to a
-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