##// END OF EJS Templates
verify: tolerate repeated slashes in a converted repo (issue3665)...
Bryan O'Sullivan -
r17851:7aa73806 default
parent child Browse files
Show More
@@ -1,310 +1,315 b''
1 1 # verify.py - repository integrity checking for Mercurial
2 2 #
3 3 # Copyright 2006, 2007 Matt Mackall <mpm@selenic.com>
4 4 #
5 5 # This software may be used and distributed according to the terms of the
6 6 # GNU General Public License version 2 or any later version.
7 7
8 8 from node import nullid, short
9 9 from i18n import _
10 import os
10 import os, posixpath
11 11 import revlog, util, error
12 12
13 13 def verify(repo):
14 14 lock = repo.lock()
15 15 try:
16 16 return _verify(repo)
17 17 finally:
18 18 lock.release()
19 19
20 20 def _verify(repo):
21 21 mflinkrevs = {}
22 22 filelinkrevs = {}
23 23 filenodes = {}
24 24 revisions = 0
25 25 badrevs = set()
26 26 errors = [0]
27 27 warnings = [0]
28 28 ui = repo.ui
29 29 cl = repo.changelog
30 30 mf = repo.manifest
31 31 lrugetctx = util.lrucachefunc(repo.changectx)
32 32
33 33 if not repo.cancopy():
34 34 raise util.Abort(_("cannot verify bundle or remote repos"))
35 35
36 36 def err(linkrev, msg, filename=None):
37 37 if linkrev is not None:
38 38 badrevs.add(linkrev)
39 39 else:
40 40 linkrev = '?'
41 41 msg = "%s: %s" % (linkrev, msg)
42 42 if filename:
43 43 msg = "%s@%s" % (filename, msg)
44 44 ui.warn(" " + msg + "\n")
45 45 errors[0] += 1
46 46
47 47 def exc(linkrev, msg, inst, filename=None):
48 48 if isinstance(inst, KeyboardInterrupt):
49 49 ui.warn(_("interrupted"))
50 50 raise
51 51 if not str(inst):
52 52 inst = repr(inst)
53 53 err(linkrev, "%s: %s" % (msg, inst), filename)
54 54
55 55 def warn(msg):
56 56 ui.warn(msg + "\n")
57 57 warnings[0] += 1
58 58
59 59 def checklog(obj, name, linkrev):
60 60 if not len(obj) and (havecl or havemf):
61 61 err(linkrev, _("empty or missing %s") % name)
62 62 return
63 63
64 64 d = obj.checksize()
65 65 if d[0]:
66 66 err(None, _("data length off by %d bytes") % d[0], name)
67 67 if d[1]:
68 68 err(None, _("index contains %d extra bytes") % d[1], name)
69 69
70 70 if obj.version != revlog.REVLOGV0:
71 71 if not revlogv1:
72 72 warn(_("warning: `%s' uses revlog format 1") % name)
73 73 elif revlogv1:
74 74 warn(_("warning: `%s' uses revlog format 0") % name)
75 75
76 76 def checkentry(obj, i, node, seen, linkrevs, f):
77 77 lr = obj.linkrev(obj.rev(node))
78 78 if lr < 0 or (havecl and lr not in linkrevs):
79 79 if lr < 0 or lr >= len(cl):
80 80 msg = _("rev %d points to nonexistent changeset %d")
81 81 else:
82 82 msg = _("rev %d points to unexpected changeset %d")
83 83 err(None, msg % (i, lr), f)
84 84 if linkrevs:
85 85 if f and len(linkrevs) > 1:
86 86 try:
87 87 # attempt to filter down to real linkrevs
88 88 linkrevs = [l for l in linkrevs
89 89 if lrugetctx(l)[f].filenode() == node]
90 90 except Exception:
91 91 pass
92 92 warn(_(" (expected %s)") % " ".join(map(str, linkrevs)))
93 93 lr = None # can't be trusted
94 94
95 95 try:
96 96 p1, p2 = obj.parents(node)
97 97 if p1 not in seen and p1 != nullid:
98 98 err(lr, _("unknown parent 1 %s of %s") %
99 99 (short(p1), short(node)), f)
100 100 if p2 not in seen and p2 != nullid:
101 101 err(lr, _("unknown parent 2 %s of %s") %
102 102 (short(p2), short(node)), f)
103 103 except Exception, inst:
104 104 exc(lr, _("checking parents of %s") % short(node), inst, f)
105 105
106 106 if node in seen:
107 107 err(lr, _("duplicate revision %d (%d)") % (i, seen[node]), f)
108 108 seen[node] = i
109 109 return lr
110 110
111 111 if os.path.exists(repo.sjoin("journal")):
112 112 ui.warn(_("abandoned transaction found - run hg recover\n"))
113 113
114 114 revlogv1 = cl.version != revlog.REVLOGV0
115 115 if ui.verbose or not revlogv1:
116 116 ui.status(_("repository uses revlog format %d\n") %
117 117 (revlogv1 and 1 or 0))
118 118
119 119 havecl = len(cl) > 0
120 120 havemf = len(mf) > 0
121 121
122 122 ui.status(_("checking changesets\n"))
123 123 refersmf = False
124 124 seen = {}
125 125 checklog(cl, "changelog", 0)
126 126 total = len(repo)
127 127 for i in repo:
128 128 ui.progress(_('checking'), i, total=total, unit=_('changesets'))
129 129 n = cl.node(i)
130 130 checkentry(cl, i, n, seen, [i], "changelog")
131 131
132 132 try:
133 133 changes = cl.read(n)
134 134 if changes[0] != nullid:
135 135 mflinkrevs.setdefault(changes[0], []).append(i)
136 136 refersmf = True
137 137 for f in changes[3]:
138 138 filelinkrevs.setdefault(f, []).append(i)
139 139 except Exception, inst:
140 140 refersmf = True
141 141 exc(i, _("unpacking changeset %s") % short(n), inst)
142 142 ui.progress(_('checking'), None)
143 143
144 144 ui.status(_("checking manifests\n"))
145 145 seen = {}
146 146 if refersmf:
147 147 # Do not check manifest if there are only changelog entries with
148 148 # null manifests.
149 149 checklog(mf, "manifest", 0)
150 150 total = len(mf)
151 151 for i in mf:
152 152 ui.progress(_('checking'), i, total=total, unit=_('manifests'))
153 153 n = mf.node(i)
154 154 lr = checkentry(mf, i, n, seen, mflinkrevs.get(n, []), "manifest")
155 155 if n in mflinkrevs:
156 156 del mflinkrevs[n]
157 157 else:
158 158 err(lr, _("%s not in changesets") % short(n), "manifest")
159 159
160 160 try:
161 161 for f, fn in mf.readdelta(n).iteritems():
162 162 if not f:
163 163 err(lr, _("file without name in manifest"))
164 164 elif f != "/dev/null":
165 165 filenodes.setdefault(f, {}).setdefault(fn, lr)
166 166 except Exception, inst:
167 167 exc(lr, _("reading manifest delta %s") % short(n), inst)
168 168 ui.progress(_('checking'), None)
169 169
170 170 ui.status(_("crosschecking files in changesets and manifests\n"))
171 171
172 172 total = len(mflinkrevs) + len(filelinkrevs) + len(filenodes)
173 173 count = 0
174 174 if havemf:
175 175 for c, m in sorted([(c, m) for m in mflinkrevs
176 176 for c in mflinkrevs[m]]):
177 177 count += 1
178 178 if m == nullid:
179 179 continue
180 180 ui.progress(_('crosschecking'), count, total=total)
181 181 err(c, _("changeset refers to unknown manifest %s") % short(m))
182 182 mflinkrevs = None # del is bad here due to scope issues
183 183
184 184 for f in sorted(filelinkrevs):
185 185 count += 1
186 186 ui.progress(_('crosschecking'), count, total=total)
187 187 if f not in filenodes:
188 188 lr = filelinkrevs[f][0]
189 189 err(lr, _("in changeset but not in manifest"), f)
190 190
191 191 if havecl:
192 192 for f in sorted(filenodes):
193 193 count += 1
194 194 ui.progress(_('crosschecking'), count, total=total)
195 195 if f not in filelinkrevs:
196 196 try:
197 197 fl = repo.file(f)
198 198 lr = min([fl.linkrev(fl.rev(n)) for n in filenodes[f]])
199 199 except Exception:
200 200 lr = None
201 201 err(lr, _("in manifest but not in changeset"), f)
202 202
203 203 ui.progress(_('crosschecking'), None)
204 204
205 205 ui.status(_("checking files\n"))
206 206
207 207 storefiles = set()
208 208 for f, f2, size in repo.store.datafiles():
209 209 if not f:
210 210 err(None, _("cannot decode filename '%s'") % f2)
211 211 elif size > 0 or not revlogv1:
212 212 storefiles.add(f)
213 213
214 214 files = sorted(set(filenodes) | set(filelinkrevs))
215 215 total = len(files)
216 216 for i, f in enumerate(files):
217 217 ui.progress(_('checking'), i, item=f, total=total)
218 218 try:
219 219 linkrevs = filelinkrevs[f]
220 220 except KeyError:
221 221 # in manifest but not in changelog
222 222 linkrevs = []
223 223
224 224 if linkrevs:
225 225 lr = linkrevs[0]
226 226 else:
227 227 lr = None
228 228
229 229 try:
230 230 fl = repo.file(f)
231 231 except error.RevlogError, e:
232 232 err(lr, _("broken revlog! (%s)") % e, f)
233 233 continue
234 234
235 235 for ff in fl.files():
236 236 try:
237 237 storefiles.remove(ff)
238 238 except KeyError:
239 err(lr, _("missing revlog!"), ff)
239 # under hg < 2.4, convert didn't sanitize paths properly,
240 # so a converted repo may contain repeated slashes
241 try:
242 storefiles.remove(posixpath.normpath(ff))
243 except KeyError:
244 err(lr, _("missing revlog!"), ff)
240 245
241 246 checklog(fl, f, lr)
242 247 seen = {}
243 248 rp = None
244 249 for i in fl:
245 250 revisions += 1
246 251 n = fl.node(i)
247 252 lr = checkentry(fl, i, n, seen, linkrevs, f)
248 253 if f in filenodes:
249 254 if havemf and n not in filenodes[f]:
250 255 err(lr, _("%s not in manifests") % (short(n)), f)
251 256 else:
252 257 del filenodes[f][n]
253 258
254 259 # verify contents
255 260 try:
256 261 l = len(fl.read(n))
257 262 rp = fl.renamed(n)
258 263 if l != fl.size(i):
259 264 if len(fl.revision(n)) != fl.size(i):
260 265 err(lr, _("unpacked size is %s, %s expected") %
261 266 (l, fl.size(i)), f)
262 267 except Exception, inst:
263 268 exc(lr, _("unpacking %s") % short(n), inst, f)
264 269
265 270 # check renames
266 271 try:
267 272 if rp:
268 273 if lr is not None and ui.verbose:
269 274 ctx = lrugetctx(lr)
270 275 found = False
271 276 for pctx in ctx.parents():
272 277 if rp[0] in pctx:
273 278 found = True
274 279 break
275 280 if not found:
276 281 warn(_("warning: copy source of '%s' not"
277 282 " in parents of %s") % (f, ctx))
278 283 fl2 = repo.file(rp[0])
279 284 if not len(fl2):
280 285 err(lr, _("empty or missing copy source revlog %s:%s")
281 286 % (rp[0], short(rp[1])), f)
282 287 elif rp[1] == nullid:
283 288 ui.note(_("warning: %s@%s: copy source"
284 289 " revision is nullid %s:%s\n")
285 290 % (f, lr, rp[0], short(rp[1])))
286 291 else:
287 292 fl2.rev(rp[1])
288 293 except Exception, inst:
289 294 exc(lr, _("checking rename of %s") % short(n), inst, f)
290 295
291 296 # cross-check
292 297 if f in filenodes:
293 298 fns = [(lr, n) for n, lr in filenodes[f].iteritems()]
294 299 for lr, node in sorted(fns):
295 300 err(lr, _("%s in manifests not found") % short(node), f)
296 301 ui.progress(_('checking'), None)
297 302
298 303 for f in storefiles:
299 304 warn(_("warning: orphan revlog '%s'") % f)
300 305
301 306 ui.status(_("%d files, %d changesets, %d total revisions\n") %
302 307 (len(files), len(cl), revisions))
303 308 if warnings[0]:
304 309 ui.warn(_("%d warnings encountered!\n") % warnings[0])
305 310 if errors[0]:
306 311 ui.warn(_("%d integrity errors encountered!\n") % errors[0])
307 312 if badrevs:
308 313 ui.warn(_("(first damaged changeset appears to be %d)\n")
309 314 % min(badrevs))
310 315 return 1
@@ -1,596 +1,606 b''
1 1
2 2 $ HGMERGE=true; export HGMERGE
3 3 $ echo '[extensions]' >> $HGRCPATH
4 4 $ echo 'graphlog =' >> $HGRCPATH
5 5 $ echo 'convert =' >> $HGRCPATH
6 6 $ glog()
7 7 > {
8 8 > hg glog --template '{rev} "{desc}" files: {files}\n' "$@"
9 9 > }
10 10 $ hg init source
11 11 $ cd source
12 12 $ echo foo > foo
13 13 $ echo baz > baz
14 14 $ mkdir -p dir/subdir
15 15 $ echo dir/file >> dir/file
16 16 $ echo dir/file2 >> dir/file2
17 17 $ echo dir/file3 >> dir/file3 # to be corrupted in rev 0
18 18 $ echo dir/subdir/file3 >> dir/subdir/file3
19 19 $ echo dir/subdir/file4 >> dir/subdir/file4
20 20 $ hg ci -d '0 0' -qAm '0: add foo baz dir/'
21 21 $ echo bar > bar
22 22 $ echo quux > quux
23 23 $ echo dir/file4 >> dir/file4 # to be corrupted in rev 1
24 24 $ hg copy foo copied
25 25 $ hg ci -d '1 0' -qAm '1: add bar quux; copy foo to copied'
26 26 $ echo >> foo
27 27 $ hg ci -d '2 0' -m '2: change foo'
28 28 $ hg up -qC 1
29 29 $ echo >> bar
30 30 $ echo >> quux
31 31 $ hg ci -d '3 0' -m '3: change bar quux'
32 32 created new head
33 33 $ hg up -qC 2
34 34 $ hg merge -qr 3
35 35 $ echo >> bar
36 36 $ echo >> baz
37 37 $ hg ci -d '4 0' -m '4: first merge; change bar baz'
38 38 $ echo >> bar
39 39 $ echo 1 >> baz
40 40 $ echo >> quux
41 41 $ hg ci -d '5 0' -m '5: change bar baz quux'
42 42 $ hg up -qC 4
43 43 $ echo >> foo
44 44 $ echo 2 >> baz
45 45 $ hg ci -d '6 0' -m '6: change foo baz'
46 46 created new head
47 47 $ hg up -qC 5
48 48 $ hg merge -qr 6
49 49 $ echo >> bar
50 50 $ hg ci -d '7 0' -m '7: second merge; change bar'
51 51 $ echo >> foo
52 52 $ hg ci -m '8: change foo'
53 53 $ glog
54 54 @ 8 "8: change foo" files: foo
55 55 |
56 56 o 7 "7: second merge; change bar" files: bar baz
57 57 |\
58 58 | o 6 "6: change foo baz" files: baz foo
59 59 | |
60 60 o | 5 "5: change bar baz quux" files: bar baz quux
61 61 |/
62 62 o 4 "4: first merge; change bar baz" files: bar baz
63 63 |\
64 64 | o 3 "3: change bar quux" files: bar quux
65 65 | |
66 66 o | 2 "2: change foo" files: foo
67 67 |/
68 68 o 1 "1: add bar quux; copy foo to copied" files: bar copied dir/file4 quux
69 69 |
70 70 o 0 "0: add foo baz dir/" files: baz dir/file dir/file2 dir/file3 dir/subdir/file3 dir/subdir/file4 foo
71 71
72 72
73 73 final file versions in this repo:
74 74
75 75 $ hg manifest --debug
76 76 9463f52fe115e377cf2878d4fc548117211063f2 644 bar
77 77 94c1be4dfde2ee8d78db8bbfcf81210813307c3d 644 baz
78 78 7711d36246cc83e61fb29cd6d4ef394c63f1ceaf 644 copied
79 79 3e20847584beff41d7cd16136b7331ab3d754be0 644 dir/file
80 80 75e6d3f8328f5f6ace6bf10b98df793416a09dca 644 dir/file2
81 81 e96dce0bc6a217656a3a410e5e6bec2c4f42bf7c 644 dir/file3
82 82 6edd55f559cdce67132b12ca09e09cee08b60442 644 dir/file4
83 83 5fe139720576e18e34bcc9f79174db8897c8afe9 644 dir/subdir/file3
84 84 57a1c1511590f3de52874adfa04effe8a77d64af 644 dir/subdir/file4
85 85 9a7b52012991e4873687192c3e17e61ba3e837a3 644 foo
86 86 bc3eca3f47023a3e70ca0d8cc95a22a6827db19d 644 quux
87 87 $ hg debugrename copied
88 88 copied renamed from foo:2ed2a3912a0b24502043eae84ee4b279c18b90dd
89 89
90 90 $ cd ..
91 91 $ splitrepo()
92 92 > {
93 93 > msg="$1"
94 94 > files="$2"
95 95 > opts=$3
96 96 > echo "% $files: $msg"
97 97 > prefix=`echo "$files" | sed -e 's/ /-/g'`
98 98 > fmap="$prefix.fmap"
99 99 > repo="$prefix.repo"
100 100 > for i in $files; do
101 101 > echo "include $i" >> "$fmap"
102 102 > done
103 103 > hg -q convert $opts --filemap "$fmap" --datesort source "$repo"
104 104 > hg up -q -R "$repo"
105 105 > glog -R "$repo"
106 106 > hg -R "$repo" manifest --debug
107 107 > }
108 108 $ splitrepo 'skip unwanted merges; use 1st parent in 1st merge, 2nd in 2nd' foo
109 109 % foo: skip unwanted merges; use 1st parent in 1st merge, 2nd in 2nd
110 110 @ 3 "8: change foo" files: foo
111 111 |
112 112 o 2 "6: change foo baz" files: foo
113 113 |
114 114 o 1 "2: change foo" files: foo
115 115 |
116 116 o 0 "0: add foo baz dir/" files: foo
117 117
118 118 9a7b52012991e4873687192c3e17e61ba3e837a3 644 foo
119 119 $ splitrepo 'merges are not merges anymore' bar
120 120 % bar: merges are not merges anymore
121 121 @ 4 "7: second merge; change bar" files: bar
122 122 |
123 123 o 3 "5: change bar baz quux" files: bar
124 124 |
125 125 o 2 "4: first merge; change bar baz" files: bar
126 126 |
127 127 o 1 "3: change bar quux" files: bar
128 128 |
129 129 o 0 "1: add bar quux; copy foo to copied" files: bar
130 130
131 131 9463f52fe115e377cf2878d4fc548117211063f2 644 bar
132 132 $ splitrepo '1st merge is not a merge anymore; 2nd still is' baz
133 133 % baz: 1st merge is not a merge anymore; 2nd still is
134 134 @ 4 "7: second merge; change bar" files: baz
135 135 |\
136 136 | o 3 "6: change foo baz" files: baz
137 137 | |
138 138 o | 2 "5: change bar baz quux" files: baz
139 139 |/
140 140 o 1 "4: first merge; change bar baz" files: baz
141 141 |
142 142 o 0 "0: add foo baz dir/" files: baz
143 143
144 144 94c1be4dfde2ee8d78db8bbfcf81210813307c3d 644 baz
145 145 $ splitrepo 'we add additional merges when they are interesting' 'foo quux'
146 146 % foo quux: we add additional merges when they are interesting
147 147 @ 8 "8: change foo" files: foo
148 148 |
149 149 o 7 "7: second merge; change bar" files:
150 150 |\
151 151 | o 6 "6: change foo baz" files: foo
152 152 | |
153 153 o | 5 "5: change bar baz quux" files: quux
154 154 |/
155 155 o 4 "4: first merge; change bar baz" files:
156 156 |\
157 157 | o 3 "3: change bar quux" files: quux
158 158 | |
159 159 o | 2 "2: change foo" files: foo
160 160 |/
161 161 o 1 "1: add bar quux; copy foo to copied" files: quux
162 162 |
163 163 o 0 "0: add foo baz dir/" files: foo
164 164
165 165 9a7b52012991e4873687192c3e17e61ba3e837a3 644 foo
166 166 bc3eca3f47023a3e70ca0d8cc95a22a6827db19d 644 quux
167 167 $ splitrepo 'partial conversion' 'bar quux' '-r 3'
168 168 % bar quux: partial conversion
169 169 @ 1 "3: change bar quux" files: bar quux
170 170 |
171 171 o 0 "1: add bar quux; copy foo to copied" files: bar quux
172 172
173 173 b79105bedc55102f394e90a789c9c380117c1b4a 644 bar
174 174 db0421cc6b685a458c8d86c7d5c004f94429ea23 644 quux
175 175 $ splitrepo 'complete the partial conversion' 'bar quux'
176 176 % bar quux: complete the partial conversion
177 177 @ 4 "7: second merge; change bar" files: bar
178 178 |
179 179 o 3 "5: change bar baz quux" files: bar quux
180 180 |
181 181 o 2 "4: first merge; change bar baz" files: bar
182 182 |
183 183 o 1 "3: change bar quux" files: bar quux
184 184 |
185 185 o 0 "1: add bar quux; copy foo to copied" files: bar quux
186 186
187 187 9463f52fe115e377cf2878d4fc548117211063f2 644 bar
188 188 bc3eca3f47023a3e70ca0d8cc95a22a6827db19d 644 quux
189 189 $ rm -r foo.repo
190 190 $ splitrepo 'partial conversion' 'foo' '-r 3'
191 191 % foo: partial conversion
192 192 @ 0 "0: add foo baz dir/" files: foo
193 193
194 194 2ed2a3912a0b24502043eae84ee4b279c18b90dd 644 foo
195 195 $ splitrepo 'complete the partial conversion' 'foo'
196 196 % foo: complete the partial conversion
197 197 @ 3 "8: change foo" files: foo
198 198 |
199 199 o 2 "6: change foo baz" files: foo
200 200 |
201 201 o 1 "2: change foo" files: foo
202 202 |
203 203 o 0 "0: add foo baz dir/" files: foo
204 204
205 205 9a7b52012991e4873687192c3e17e61ba3e837a3 644 foo
206 206 $ splitrepo 'copied file; source not included in new repo' copied
207 207 % copied: copied file; source not included in new repo
208 208 @ 0 "1: add bar quux; copy foo to copied" files: copied
209 209
210 210 2ed2a3912a0b24502043eae84ee4b279c18b90dd 644 copied
211 211 $ hg --cwd copied.repo debugrename copied
212 212 copied not renamed
213 213 $ splitrepo 'copied file; source included in new repo' 'foo copied'
214 214 % foo copied: copied file; source included in new repo
215 215 @ 4 "8: change foo" files: foo
216 216 |
217 217 o 3 "6: change foo baz" files: foo
218 218 |
219 219 o 2 "2: change foo" files: foo
220 220 |
221 221 o 1 "1: add bar quux; copy foo to copied" files: copied
222 222 |
223 223 o 0 "0: add foo baz dir/" files: foo
224 224
225 225 7711d36246cc83e61fb29cd6d4ef394c63f1ceaf 644 copied
226 226 9a7b52012991e4873687192c3e17e61ba3e837a3 644 foo
227 227 $ hg --cwd foo-copied.repo debugrename copied
228 228 copied renamed from foo:2ed2a3912a0b24502043eae84ee4b279c18b90dd
229
230 ensure that the filemap contains duplicated slashes (issue3612)
231
229 232 $ cat > renames.fmap <<EOF
230 233 > include dir
231 234 > exclude dir/file2
232 > rename dir dir2
235 > rename dir dir2//dir3
233 236 > include foo
234 237 > include copied
235 238 > rename foo foo2
236 239 > rename copied copied2
237 240 > exclude dir/subdir
238 241 > include dir/subdir/file3
239 242 > EOF
240 243 $ rm source/.hg/store/data/dir/file3.i
241 244 $ rm source/.hg/store/data/dir/file4.i
242 245 $ hg -q convert --filemap renames.fmap --datesort source dummydest
243 246 abort: data/dir/file3.i@e96dce0bc6a2: no match found!
244 247 [255]
245 248 $ hg -q convert --filemap renames.fmap --datesort --config convert.hg.ignoreerrors=1 source renames.repo
246 249 ignoring: data/dir/file3.i@e96dce0bc6a2: no match found
247 250 ignoring: data/dir/file4.i@6edd55f559cd: no match found
248 251 $ hg up -q -R renames.repo
249 252 $ glog -R renames.repo
250 253 @ 4 "8: change foo" files: foo2
251 254 |
252 255 o 3 "6: change foo baz" files: foo2
253 256 |
254 257 o 2 "2: change foo" files: foo2
255 258 |
256 259 o 1 "1: add bar quux; copy foo to copied" files: copied2
257 260 |
258 o 0 "0: add foo baz dir/" files: dir2/file dir2/subdir/file3 foo2
261 o 0 "0: add foo baz dir/" files: dir2//dir3/file dir2//dir3/subdir/file3 foo2
259 262
263 $ hg -R renames.repo verify
264 checking changesets
265 checking manifests
266 crosschecking files in changesets and manifests
267 checking files
268 4 files, 5 changesets, 7 total revisions
269
260 270 $ hg -R renames.repo manifest --debug
261 271 d43feacba7a4f1f2080dde4a4b985bd8a0236d46 644 copied2
262 3e20847584beff41d7cd16136b7331ab3d754be0 644 dir2/file
263 5fe139720576e18e34bcc9f79174db8897c8afe9 644 dir2/subdir/file3
272 3e20847584beff41d7cd16136b7331ab3d754be0 644 dir2//dir3/file
273 5fe139720576e18e34bcc9f79174db8897c8afe9 644 dir2//dir3/subdir/file3
264 274 9a7b52012991e4873687192c3e17e61ba3e837a3 644 foo2
265 275 $ hg --cwd renames.repo debugrename copied2
266 276 copied2 renamed from foo2:2ed2a3912a0b24502043eae84ee4b279c18b90dd
267 277
268 278 copied:
269 279
270 280 $ hg --cwd source cat copied
271 281 foo
272 282
273 283 copied2:
274 284
275 285 $ hg --cwd renames.repo cat copied2
276 286 foo
277 287
278 288 filemap errors
279 289
280 290 $ cat > errors.fmap <<EOF
281 291 > include dir/ # beware that comments changes error line numbers!
282 292 > exclude /dir
283 293 > rename dir//dir /dir//dir/ "out of sync"
284 294 > include
285 295 > EOF
286 296 $ hg -q convert --filemap errors.fmap source errors.repo
287 297 errors.fmap:1: superfluous / in exclude 'dir/'
288 298 errors.fmap:3: superfluous / in include '/dir'
289 299 errors.fmap:3: superfluous / in rename '/dir'
290 300 errors.fmap:3: superfluous / in exclude 'dir//dir'
291 301 errors.fmap:4: unknown directive 'out of sync'
292 302 errors.fmap:5: path to exclude is missing
293 303 abort: errors in filemap
294 304 [255]
295 305
296 306 test branch closing revision pruning if branch is pruned
297 307
298 308 $ hg init branchpruning
299 309 $ cd branchpruning
300 310 $ hg branch foo
301 311 marked working directory as branch foo
302 312 (branches are permanent and global, did you want a bookmark?)
303 313 $ echo a > a
304 314 $ hg ci -Am adda
305 315 adding a
306 316 $ hg ci --close-branch -m closefoo
307 317 $ hg up 0
308 318 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
309 319 $ hg branch empty
310 320 marked working directory as branch empty
311 321 (branches are permanent and global, did you want a bookmark?)
312 322 $ hg ci -m emptybranch
313 323 $ hg ci --close-branch -m closeempty
314 324 $ hg up 0
315 325 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
316 326 $ hg branch default
317 327 marked working directory as branch default
318 328 (branches are permanent and global, did you want a bookmark?)
319 329 $ echo b > b
320 330 $ hg ci -Am addb
321 331 adding b
322 332 $ hg ci --close-branch -m closedefault
323 333 $ cat > filemap <<EOF
324 334 > include b
325 335 > EOF
326 336 $ cd ..
327 337 $ hg convert branchpruning branchpruning-hg1
328 338 initializing destination branchpruning-hg1 repository
329 339 scanning source...
330 340 sorting...
331 341 converting...
332 342 5 adda
333 343 4 closefoo
334 344 3 emptybranch
335 345 2 closeempty
336 346 1 addb
337 347 0 closedefault
338 348 $ glog -R branchpruning-hg1
339 349 o 5 "closedefault" files:
340 350 |
341 351 o 4 "addb" files: b
342 352 |
343 353 | o 3 "closeempty" files:
344 354 | |
345 355 | o 2 "emptybranch" files:
346 356 |/
347 357 | o 1 "closefoo" files:
348 358 |/
349 359 o 0 "adda" files: a
350 360
351 361
352 362 exercise incremental conversion at the same time
353 363
354 364 $ hg convert -r0 --filemap branchpruning/filemap branchpruning branchpruning-hg2
355 365 initializing destination branchpruning-hg2 repository
356 366 scanning source...
357 367 sorting...
358 368 converting...
359 369 0 adda
360 370 $ hg convert -r4 --filemap branchpruning/filemap branchpruning branchpruning-hg2
361 371 scanning source...
362 372 sorting...
363 373 converting...
364 374 0 addb
365 375 $ hg convert --filemap branchpruning/filemap branchpruning branchpruning-hg2
366 376 scanning source...
367 377 sorting...
368 378 converting...
369 379 3 closefoo
370 380 2 emptybranch
371 381 1 closeempty
372 382 0 closedefault
373 383 $ glog -R branchpruning-hg2
374 384 o 1 "closedefault" files:
375 385 |
376 386 o 0 "addb" files: b
377 387
378 388
379 389 filemap rename undoing revision rename
380 390
381 391 $ hg init renameundo
382 392 $ cd renameundo
383 393 $ echo 1 > a
384 394 $ echo 1 > c
385 395 $ hg ci -qAm add
386 396 $ hg mv -q a b/a
387 397 $ hg mv -q c b/c
388 398 $ hg ci -qm rename
389 399 $ echo 2 > b/a
390 400 $ echo 2 > b/c
391 401 $ hg ci -qm modify
392 402 $ cd ..
393 403
394 404 $ echo "rename b ." > renameundo.fmap
395 405 $ hg convert --filemap renameundo.fmap renameundo renameundo2
396 406 initializing destination renameundo2 repository
397 407 scanning source...
398 408 sorting...
399 409 converting...
400 410 2 add
401 411 1 rename
402 412 filtering out empty revision
403 413 repository tip rolled back to revision 0 (undo commit)
404 414 0 modify
405 415 $ glog -R renameundo2
406 416 o 1 "modify" files: a c
407 417 |
408 418 o 0 "add" files: a c
409 419
410 420
411 421
412 422 test merge parents/empty merges pruning
413 423
414 424 $ glog()
415 425 > {
416 426 > hg glog --template '{rev}:{node|short}@{branch} "{desc}" files: {files}\n' "$@"
417 427 > }
418 428
419 429 test anonymous branch pruning
420 430
421 431 $ hg init anonymousbranch
422 432 $ cd anonymousbranch
423 433 $ echo a > a
424 434 $ echo b > b
425 435 $ hg ci -Am add
426 436 adding a
427 437 adding b
428 438 $ echo a >> a
429 439 $ hg ci -m changea
430 440 $ hg up 0
431 441 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
432 442 $ echo b >> b
433 443 $ hg ci -m changeb
434 444 created new head
435 445 $ hg up 1
436 446 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
437 447 $ hg merge
438 448 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
439 449 (branch merge, don't forget to commit)
440 450 $ hg ci -m merge
441 451 $ cd ..
442 452
443 453 $ cat > filemap <<EOF
444 454 > include a
445 455 > EOF
446 456 $ hg convert --filemap filemap anonymousbranch anonymousbranch-hg
447 457 initializing destination anonymousbranch-hg repository
448 458 scanning source...
449 459 sorting...
450 460 converting...
451 461 3 add
452 462 2 changea
453 463 1 changeb
454 464 0 merge
455 465 $ glog -R anonymousbranch
456 466 @ 3:c71d5201a498@default "merge" files:
457 467 |\
458 468 | o 2:607eb44b17f9@default "changeb" files: b
459 469 | |
460 470 o | 1:1f60ea617824@default "changea" files: a
461 471 |/
462 472 o 0:0146e6129113@default "add" files: a b
463 473
464 474 $ glog -R anonymousbranch-hg
465 475 o 1:cda818e7219b@default "changea" files: a
466 476 |
467 477 o 0:c334dc3be0da@default "add" files: a
468 478
469 479 $ cat anonymousbranch-hg/.hg/shamap
470 480 0146e6129113dba9ac90207cfdf2d7ed35257ae5 c334dc3be0daa2a4e9ce4d2e2bdcba40c09d4916
471 481 1f60ea61782421edf8d051ff4fcb61b330f26a4a cda818e7219b5f7f3fb9f49780054ed6a1905ec3
472 482 607eb44b17f9348cd5cbd26e16af87ba77b0b037 c334dc3be0daa2a4e9ce4d2e2bdcba40c09d4916
473 483 c71d5201a498b2658d105a6bf69d7a0df2649aea cda818e7219b5f7f3fb9f49780054ed6a1905ec3
474 484
475 485 $ cat > filemap <<EOF
476 486 > include b
477 487 > EOF
478 488 $ hg convert --filemap filemap anonymousbranch anonymousbranch-hg2
479 489 initializing destination anonymousbranch-hg2 repository
480 490 scanning source...
481 491 sorting...
482 492 converting...
483 493 3 add
484 494 2 changea
485 495 1 changeb
486 496 0 merge
487 497 $ glog -R anonymousbranch
488 498 @ 3:c71d5201a498@default "merge" files:
489 499 |\
490 500 | o 2:607eb44b17f9@default "changeb" files: b
491 501 | |
492 502 o | 1:1f60ea617824@default "changea" files: a
493 503 |/
494 504 o 0:0146e6129113@default "add" files: a b
495 505
496 506 $ glog -R anonymousbranch-hg2
497 507 o 1:62dd350b0df6@default "changeb" files: b
498 508 |
499 509 o 0:4b9ced861657@default "add" files: b
500 510
501 511 $ cat anonymousbranch-hg2/.hg/shamap
502 512 0146e6129113dba9ac90207cfdf2d7ed35257ae5 4b9ced86165703791653059a1db6ed864630a523
503 513 1f60ea61782421edf8d051ff4fcb61b330f26a4a 4b9ced86165703791653059a1db6ed864630a523
504 514 607eb44b17f9348cd5cbd26e16af87ba77b0b037 62dd350b0df695f7d2c82a02e0499b16fd790f22
505 515 c71d5201a498b2658d105a6bf69d7a0df2649aea 62dd350b0df695f7d2c82a02e0499b16fd790f22
506 516
507 517 test named branch pruning
508 518
509 519 $ hg init namedbranch
510 520 $ cd namedbranch
511 521 $ echo a > a
512 522 $ echo b > b
513 523 $ hg ci -Am add
514 524 adding a
515 525 adding b
516 526 $ echo a >> a
517 527 $ hg ci -m changea
518 528 $ hg up 0
519 529 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
520 530 $ hg branch foo
521 531 marked working directory as branch foo
522 532 (branches are permanent and global, did you want a bookmark?)
523 533 $ echo b >> b
524 534 $ hg ci -m changeb
525 535 $ hg up default
526 536 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
527 537 $ hg merge foo
528 538 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
529 539 (branch merge, don't forget to commit)
530 540 $ hg ci -m merge
531 541 $ cd ..
532 542
533 543 $ cat > filemap <<EOF
534 544 > include a
535 545 > EOF
536 546 $ hg convert --filemap filemap namedbranch namedbranch-hg
537 547 initializing destination namedbranch-hg repository
538 548 scanning source...
539 549 sorting...
540 550 converting...
541 551 3 add
542 552 2 changea
543 553 1 changeb
544 554 0 merge
545 555 $ glog -R namedbranch
546 556 @ 3:73899bcbe45c@default "merge" files:
547 557 |\
548 558 | o 2:8097982d19fc@foo "changeb" files: b
549 559 | |
550 560 o | 1:1f60ea617824@default "changea" files: a
551 561 |/
552 562 o 0:0146e6129113@default "add" files: a b
553 563
554 564 $ glog -R namedbranch-hg
555 565 o 1:cda818e7219b@default "changea" files: a
556 566 |
557 567 o 0:c334dc3be0da@default "add" files: a
558 568
559 569
560 570 $ cd namedbranch
561 571 $ hg --config extensions.mq= strip tip
562 572 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
563 573 saved backup bundle to $TESTTMP/namedbranch/.hg/strip-backup/73899bcbe45c-backup.hg (glob)
564 574 $ hg up foo
565 575 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
566 576 $ hg merge default
567 577 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
568 578 (branch merge, don't forget to commit)
569 579 $ hg ci -m merge
570 580 $ cd ..
571 581
572 582 $ hg convert --filemap filemap namedbranch namedbranch-hg2
573 583 initializing destination namedbranch-hg2 repository
574 584 scanning source...
575 585 sorting...
576 586 converting...
577 587 3 add
578 588 2 changea
579 589 1 changeb
580 590 0 merge
581 591 $ glog -R namedbranch
582 592 @ 3:e1959de76e1b@foo "merge" files:
583 593 |\
584 594 | o 2:8097982d19fc@foo "changeb" files: b
585 595 | |
586 596 o | 1:1f60ea617824@default "changea" files: a
587 597 |/
588 598 o 0:0146e6129113@default "add" files: a b
589 599
590 600 $ glog -R namedbranch-hg2
591 601 o 2:dcf314454667@foo "merge" files:
592 602 |\
593 603 | o 1:cda818e7219b@default "changea" files: a
594 604 |/
595 605 o 0:c334dc3be0da@default "add" files: a
596 606
General Comments 0
You need to be logged in to leave comments. Login now