Mercurial > hg > mercurial-crew-with-dirclash
annotate mercurial/repair.py @ 5192:33015dac5df5
convert: fix mercurial_sink.putcommit
Changeset 4ebc8693ce72 added some code to putcommit to avoid creating a
revision that touches no files, but this can break regular conversions
from some repositories:
- conceptually, since we're converting a repo, we should try to make
the new hg repo as similar as possible to the original repo - we
should create a new changeset, even if the original revision didn't
touch any files (maybe the commit message had some important bit);
- even if a "regular" revision that doesn't touch any file may seem
weird (and maybe even broken), it's completely legitimate for a merge
revision to not touch any file, and, if we just skip it, the
converted repo will end up with wrong history and possibly an extra
head.
As an example, say the crew and main hg repos are sync'ed. Somebody
sends an important patch to the mailing list. Matt quickly applies
and pushes it. But at the same time somebody also applies it to crew
and pushes it. Suppose the commit message ended up being a bit
different (say, there was a typo and somebody didn't fix it) or that
the date ended up being different (because of different patch-applying
scripts): the changeset hashes will be different, but the manifests
will be the same.
Since both changesets were pushed to public repos, it's hard to recall
them. If both are merged, the manifest from the resulting merge
revision will have the exact same contents as its parents - i.e. the
merge revision really doesn't touch any file at all.
To keep the file filtering stuff "working", the generic code was changed
to skip empty revisions if we're filtering the repo, fixing a bug in the
process (we want parents[0] instead of tip).
author | Alexis S. L. Carvalho <alexis@cecm.usp.br> |
---|---|
date | Fri, 17 Aug 2007 20:18:05 -0300 |
parents | 18e91c9def0c |
children |
rev | line source |
---|---|
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 |