author | Matt Mackall <mpm@selenic.com> |
Mon, 23 Jul 2007 20:44:08 -0500 | |
changeset 4977 | 6cb30bc4ca32 |
parent 4702 | 18e91c9def0c |
permissions | -rw-r--r-- |
4702
18e91c9def0c
strip: move strip code to a new repair module
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1 |
# repair.py - functions for repository repair for mercurial |
18e91c9def0c
strip: move strip code to a new repair module
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
2 |
# |
18e91c9def0c
strip: move strip code to a new repair module
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
3 |
# Copyright 2005, 2006 Chris Mason <mason@suse.com> |
18e91c9def0c
strip: move strip code to a new repair module
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
4 |
# Copyright 2007 Matt Mackall |
18e91c9def0c
strip: move strip code to a new repair module
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
5 |
# |
18e91c9def0c
strip: move strip code to a new repair module
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
6 |
# This software may be used and distributed according to the terms |
18e91c9def0c
strip: move strip code to a new repair module
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
7 |
# of the GNU General Public License, incorporated herein by reference. |
18e91c9def0c
strip: move strip code to a new repair module
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
8 |
|
18e91c9def0c
strip: move strip code to a new repair module
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
9 |
import changegroup, revlog, os, commands |
18e91c9def0c
strip: move strip code to a new repair module
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
10 |
|
18e91c9def0c
strip: move strip code to a new repair module
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
11 |
def strip(ui, repo, rev, backup="all"): |
18e91c9def0c
strip: move strip code to a new repair module
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
12 |
def limitheads(chlog, stop): |
18e91c9def0c
strip: move strip code to a new repair module
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
13 |
"""return the list of all nodes that have no children""" |
18e91c9def0c
strip: move strip code to a new repair module
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
14 |
p = {} |
18e91c9def0c
strip: move strip code to a new repair module
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
15 |
h = [] |
18e91c9def0c
strip: move strip code to a new repair module
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
16 |
stoprev = 0 |
18e91c9def0c
strip: move strip code to a new repair module
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
17 |
if stop in chlog.nodemap: |
18e91c9def0c
strip: move strip code to a new repair module
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
18 |
stoprev = chlog.rev(stop) |
18e91c9def0c
strip: move strip code to a new repair module
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
19 |
|
18e91c9def0c
strip: move strip code to a new repair module
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
20 |
for r in xrange(chlog.count() - 1, -1, -1): |
18e91c9def0c
strip: move strip code to a new repair module
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
21 |
n = chlog.node(r) |
18e91c9def0c
strip: move strip code to a new repair module
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
22 |
if n not in p: |
18e91c9def0c
strip: move strip code to a new repair module
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
23 |
h.append(n) |
18e91c9def0c
strip: move strip code to a new repair module
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
24 |
if n == stop: |
18e91c9def0c
strip: move strip code to a new repair module
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
25 |
break |
18e91c9def0c
strip: move strip code to a new repair module
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
26 |
if r < stoprev: |
18e91c9def0c
strip: move strip code to a new repair module
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
27 |
break |
18e91c9def0c
strip: move strip code to a new repair module
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
28 |
for pn in chlog.parents(n): |
18e91c9def0c
strip: move strip code to a new repair module
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
29 |
p[pn] = 1 |
18e91c9def0c
strip: move strip code to a new repair module
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
30 |
return h |
18e91c9def0c
strip: move strip code to a new repair module
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
31 |
|
18e91c9def0c
strip: move strip code to a new repair module
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
32 |
def bundle(repo, bases, heads, rev, suffix): |
18e91c9def0c
strip: move strip code to a new repair module
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
33 |
cg = repo.changegroupsubset(bases, heads, 'strip') |
18e91c9def0c
strip: move strip code to a new repair module
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
34 |
backupdir = repo.join("strip-backup") |
18e91c9def0c
strip: move strip code to a new repair module
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
35 |
if not os.path.isdir(backupdir): |
18e91c9def0c
strip: move strip code to a new repair module
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
36 |
os.mkdir(backupdir) |
18e91c9def0c
strip: move strip code to a new repair module
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
37 |
name = os.path.join(backupdir, "%s-%s" % (revlog.short(rev), suffix)) |
18e91c9def0c
strip: move strip code to a new repair module
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
38 |
ui.warn("saving bundle to %s\n" % name) |
18e91c9def0c
strip: move strip code to a new repair module
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
39 |
return changegroup.writebundle(cg, name, "HG10BZ") |
18e91c9def0c
strip: move strip code to a new repair module
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
40 |
|
18e91c9def0c
strip: move strip code to a new repair module
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
41 |
def stripall(revnum): |
18e91c9def0c
strip: move strip code to a new repair module
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
42 |
mm = repo.changectx(rev).manifest() |
18e91c9def0c
strip: move strip code to a new repair module
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
43 |
seen = {} |
18e91c9def0c
strip: move strip code to a new repair module
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
44 |
|
18e91c9def0c
strip: move strip code to a new repair module
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
45 |
for x in xrange(revnum, repo.changelog.count()): |
18e91c9def0c
strip: move strip code to a new repair module
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
46 |
for f in repo.changectx(x).files(): |
18e91c9def0c
strip: move strip code to a new repair module
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
47 |
if f in seen: |
18e91c9def0c
strip: move strip code to a new repair module
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
48 |
continue |
18e91c9def0c
strip: move strip code to a new repair module
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
49 |
seen[f] = 1 |
18e91c9def0c
strip: move strip code to a new repair module
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
50 |
if f in mm: |
18e91c9def0c
strip: move strip code to a new repair module
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
51 |
filerev = mm[f] |
18e91c9def0c
strip: move strip code to a new repair module
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
52 |
else: |
18e91c9def0c
strip: move strip code to a new repair module
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
53 |
filerev = 0 |
18e91c9def0c
strip: move strip code to a new repair module
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
54 |
seen[f] = filerev |
18e91c9def0c
strip: move strip code to a new repair module
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
55 |
# we go in two steps here so the strip loop happens in a |
18e91c9def0c
strip: move strip code to a new repair module
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
56 |
# sensible order. When stripping many files, this helps keep |
18e91c9def0c
strip: move strip code to a new repair module
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
57 |
# our disk access patterns under control. |
18e91c9def0c
strip: move strip code to a new repair module
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
58 |
seen_list = seen.keys() |
18e91c9def0c
strip: move strip code to a new repair module
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
59 |
seen_list.sort() |
18e91c9def0c
strip: move strip code to a new repair module
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
60 |
for f in seen_list: |
18e91c9def0c
strip: move strip code to a new repair module
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
61 |
ff = repo.file(f) |
18e91c9def0c
strip: move strip code to a new repair module
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
62 |
filerev = seen[f] |
18e91c9def0c
strip: move strip code to a new repair module
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
63 |
if filerev != 0: |
18e91c9def0c
strip: move strip code to a new repair module
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
64 |
if filerev in ff.nodemap: |
18e91c9def0c
strip: move strip code to a new repair module
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
65 |
filerev = ff.rev(filerev) |
18e91c9def0c
strip: move strip code to a new repair module
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
66 |
else: |
18e91c9def0c
strip: move strip code to a new repair module
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
67 |
filerev = 0 |
18e91c9def0c
strip: move strip code to a new repair module
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
68 |
ff.strip(filerev, revnum) |
18e91c9def0c
strip: move strip code to a new repair module
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
69 |
|
18e91c9def0c
strip: move strip code to a new repair module
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
70 |
chlog = repo.changelog |
18e91c9def0c
strip: move strip code to a new repair module
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
71 |
# TODO delete the undo files, and handle undo of merge sets |
18e91c9def0c
strip: move strip code to a new repair module
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
72 |
pp = chlog.parents(rev) |
18e91c9def0c
strip: move strip code to a new repair module
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
73 |
revnum = chlog.rev(rev) |
18e91c9def0c
strip: move strip code to a new repair module
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
74 |
|
18e91c9def0c
strip: move strip code to a new repair module
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
75 |
# save is a list of all the branches we are truncating away |
18e91c9def0c
strip: move strip code to a new repair module
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
76 |
# that we actually want to keep. changegroup will be used |
18e91c9def0c
strip: move strip code to a new repair module
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
77 |
# to preserve them and add them back after the truncate |
18e91c9def0c
strip: move strip code to a new repair module
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
78 |
saveheads = [] |
18e91c9def0c
strip: move strip code to a new repair module
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
79 |
savebases = {} |
18e91c9def0c
strip: move strip code to a new repair module
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
80 |
|
18e91c9def0c
strip: move strip code to a new repair module
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
81 |
heads = limitheads(chlog, rev) |
18e91c9def0c
strip: move strip code to a new repair module
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
82 |
seen = {} |
18e91c9def0c
strip: move strip code to a new repair module
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
83 |
|
18e91c9def0c
strip: move strip code to a new repair module
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
84 |
# search through all the heads, finding those where the revision |
18e91c9def0c
strip: move strip code to a new repair module
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
85 |
# we want to strip away is an ancestor. Also look for merges |
18e91c9def0c
strip: move strip code to a new repair module
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
86 |
# that might be turned into new heads by the strip. |
18e91c9def0c
strip: move strip code to a new repair module
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
87 |
while heads: |
18e91c9def0c
strip: move strip code to a new repair module
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
88 |
h = heads.pop() |
18e91c9def0c
strip: move strip code to a new repair module
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
89 |
n = h |
18e91c9def0c
strip: move strip code to a new repair module
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
90 |
while True: |
18e91c9def0c
strip: move strip code to a new repair module
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
91 |
seen[n] = 1 |
18e91c9def0c
strip: move strip code to a new repair module
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
92 |
pp = chlog.parents(n) |
18e91c9def0c
strip: move strip code to a new repair module
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
93 |
if pp[1] != revlog.nullid: |
18e91c9def0c
strip: move strip code to a new repair module
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
94 |
for p in pp: |
18e91c9def0c
strip: move strip code to a new repair module
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
95 |
if chlog.rev(p) > revnum and p not in seen: |
18e91c9def0c
strip: move strip code to a new repair module
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
96 |
heads.append(p) |
18e91c9def0c
strip: move strip code to a new repair module
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
97 |
if pp[0] == revlog.nullid: |
18e91c9def0c
strip: move strip code to a new repair module
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
98 |
break |
18e91c9def0c
strip: move strip code to a new repair module
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
99 |
if chlog.rev(pp[0]) < revnum: |
18e91c9def0c
strip: move strip code to a new repair module
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
100 |
break |
18e91c9def0c
strip: move strip code to a new repair module
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
101 |
n = pp[0] |
18e91c9def0c
strip: move strip code to a new repair module
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
102 |
if n == rev: |
18e91c9def0c
strip: move strip code to a new repair module
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
103 |
break |
18e91c9def0c
strip: move strip code to a new repair module
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
104 |
r = chlog.reachable(h, rev) |
18e91c9def0c
strip: move strip code to a new repair module
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
105 |
if rev not in r: |
18e91c9def0c
strip: move strip code to a new repair module
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
106 |
saveheads.append(h) |
18e91c9def0c
strip: move strip code to a new repair module
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
107 |
for x in r: |
18e91c9def0c
strip: move strip code to a new repair module
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
108 |
if chlog.rev(x) > revnum: |
18e91c9def0c
strip: move strip code to a new repair module
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
109 |
savebases[x] = 1 |
18e91c9def0c
strip: move strip code to a new repair module
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
110 |
|
18e91c9def0c
strip: move strip code to a new repair module
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
111 |
# create a changegroup for all the branches we need to keep |
18e91c9def0c
strip: move strip code to a new repair module
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
112 |
if backup == "all": |
18e91c9def0c
strip: move strip code to a new repair module
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
113 |
bundle(repo, [rev], chlog.heads(), rev, 'backup') |
18e91c9def0c
strip: move strip code to a new repair module
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
114 |
if saveheads: |
18e91c9def0c
strip: move strip code to a new repair module
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
115 |
chgrpfile = bundle(repo, savebases.keys(), saveheads, rev, 'temp') |
18e91c9def0c
strip: move strip code to a new repair module
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
116 |
|
18e91c9def0c
strip: move strip code to a new repair module
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
117 |
stripall(revnum) |
18e91c9def0c
strip: move strip code to a new repair module
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
118 |
|
18e91c9def0c
strip: move strip code to a new repair module
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
119 |
change = chlog.read(rev) |
18e91c9def0c
strip: move strip code to a new repair module
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
120 |
chlog.strip(revnum, revnum) |
18e91c9def0c
strip: move strip code to a new repair module
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
121 |
repo.manifest.strip(repo.manifest.rev(change[0]), revnum) |
18e91c9def0c
strip: move strip code to a new repair module
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
122 |
if saveheads: |
18e91c9def0c
strip: move strip code to a new repair module
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
123 |
ui.status("adding branch\n") |
18e91c9def0c
strip: move strip code to a new repair module
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
124 |
commands.unbundle(ui, repo, "file:%s" % chgrpfile, update=False) |
18e91c9def0c
strip: move strip code to a new repair module
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
125 |
if backup != "strip": |
18e91c9def0c
strip: move strip code to a new repair module
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
126 |
os.unlink(chgrpfile) |
18e91c9def0c
strip: move strip code to a new repair module
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
127 |