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