##// END OF EJS Templates
treemanifest: fix debugrebuildfncache...
Martin von Zweigbergk -
r28031:6f248ba8 default
parent child Browse files
Show More
@@ -1,314 +1,314
1 # repair.py - functions for repository repair for mercurial
1 # repair.py - functions for repository repair for mercurial
2 #
2 #
3 # Copyright 2005, 2006 Chris Mason <mason@suse.com>
3 # Copyright 2005, 2006 Chris Mason <mason@suse.com>
4 # Copyright 2007 Matt Mackall
4 # Copyright 2007 Matt Mackall
5 #
5 #
6 # This software may be used and distributed according to the terms of the
6 # This software may be used and distributed according to the terms of the
7 # GNU General Public License version 2 or any later version.
7 # GNU General Public License version 2 or any later version.
8
8
9 from __future__ import absolute_import
9 from __future__ import absolute_import
10
10
11 import errno
11 import errno
12
12
13 from .i18n import _
13 from .i18n import _
14 from .node import short
14 from .node import short
15 from . import (
15 from . import (
16 bundle2,
16 bundle2,
17 changegroup,
17 changegroup,
18 error,
18 error,
19 exchange,
19 exchange,
20 util,
20 util,
21 )
21 )
22
22
23 def _bundle(repo, bases, heads, node, suffix, compress=True):
23 def _bundle(repo, bases, heads, node, suffix, compress=True):
24 """create a bundle with the specified revisions as a backup"""
24 """create a bundle with the specified revisions as a backup"""
25 cgversion = changegroup.safeversion(repo)
25 cgversion = changegroup.safeversion(repo)
26
26
27 cg = changegroup.changegroupsubset(repo, bases, heads, 'strip',
27 cg = changegroup.changegroupsubset(repo, bases, heads, 'strip',
28 version=cgversion)
28 version=cgversion)
29 backupdir = "strip-backup"
29 backupdir = "strip-backup"
30 vfs = repo.vfs
30 vfs = repo.vfs
31 if not vfs.isdir(backupdir):
31 if not vfs.isdir(backupdir):
32 vfs.mkdir(backupdir)
32 vfs.mkdir(backupdir)
33
33
34 # Include a hash of all the nodes in the filename for uniqueness
34 # Include a hash of all the nodes in the filename for uniqueness
35 allcommits = repo.set('%ln::%ln', bases, heads)
35 allcommits = repo.set('%ln::%ln', bases, heads)
36 allhashes = sorted(c.hex() for c in allcommits)
36 allhashes = sorted(c.hex() for c in allcommits)
37 totalhash = util.sha1(''.join(allhashes)).hexdigest()
37 totalhash = util.sha1(''.join(allhashes)).hexdigest()
38 name = "%s/%s-%s-%s.hg" % (backupdir, short(node), totalhash[:8], suffix)
38 name = "%s/%s-%s-%s.hg" % (backupdir, short(node), totalhash[:8], suffix)
39
39
40 comp = None
40 comp = None
41 if cgversion != '01':
41 if cgversion != '01':
42 bundletype = "HG20"
42 bundletype = "HG20"
43 if compress:
43 if compress:
44 comp = 'BZ'
44 comp = 'BZ'
45 elif compress:
45 elif compress:
46 bundletype = "HG10BZ"
46 bundletype = "HG10BZ"
47 else:
47 else:
48 bundletype = "HG10UN"
48 bundletype = "HG10UN"
49 return changegroup.writebundle(repo.ui, cg, name, bundletype, vfs,
49 return changegroup.writebundle(repo.ui, cg, name, bundletype, vfs,
50 compression=comp)
50 compression=comp)
51
51
52 def _collectfiles(repo, striprev):
52 def _collectfiles(repo, striprev):
53 """find out the filelogs affected by the strip"""
53 """find out the filelogs affected by the strip"""
54 files = set()
54 files = set()
55
55
56 for x in xrange(striprev, len(repo)):
56 for x in xrange(striprev, len(repo)):
57 files.update(repo[x].files())
57 files.update(repo[x].files())
58
58
59 return sorted(files)
59 return sorted(files)
60
60
61 def _collectbrokencsets(repo, files, striprev):
61 def _collectbrokencsets(repo, files, striprev):
62 """return the changesets which will be broken by the truncation"""
62 """return the changesets which will be broken by the truncation"""
63 s = set()
63 s = set()
64 def collectone(revlog):
64 def collectone(revlog):
65 _, brokenset = revlog.getstrippoint(striprev)
65 _, brokenset = revlog.getstrippoint(striprev)
66 s.update([revlog.linkrev(r) for r in brokenset])
66 s.update([revlog.linkrev(r) for r in brokenset])
67
67
68 collectone(repo.manifest)
68 collectone(repo.manifest)
69 for fname in files:
69 for fname in files:
70 collectone(repo.file(fname))
70 collectone(repo.file(fname))
71
71
72 return s
72 return s
73
73
74 def strip(ui, repo, nodelist, backup=True, topic='backup'):
74 def strip(ui, repo, nodelist, backup=True, topic='backup'):
75 # This function operates within a transaction of its own, but does
75 # This function operates within a transaction of its own, but does
76 # not take any lock on the repo.
76 # not take any lock on the repo.
77 # Simple way to maintain backwards compatibility for this
77 # Simple way to maintain backwards compatibility for this
78 # argument.
78 # argument.
79 if backup in ['none', 'strip']:
79 if backup in ['none', 'strip']:
80 backup = False
80 backup = False
81
81
82 repo = repo.unfiltered()
82 repo = repo.unfiltered()
83 repo.destroying()
83 repo.destroying()
84
84
85 cl = repo.changelog
85 cl = repo.changelog
86 # TODO handle undo of merge sets
86 # TODO handle undo of merge sets
87 if isinstance(nodelist, str):
87 if isinstance(nodelist, str):
88 nodelist = [nodelist]
88 nodelist = [nodelist]
89 striplist = [cl.rev(node) for node in nodelist]
89 striplist = [cl.rev(node) for node in nodelist]
90 striprev = min(striplist)
90 striprev = min(striplist)
91
91
92 # Some revisions with rev > striprev may not be descendants of striprev.
92 # Some revisions with rev > striprev may not be descendants of striprev.
93 # We have to find these revisions and put them in a bundle, so that
93 # We have to find these revisions and put them in a bundle, so that
94 # we can restore them after the truncations.
94 # we can restore them after the truncations.
95 # To create the bundle we use repo.changegroupsubset which requires
95 # To create the bundle we use repo.changegroupsubset which requires
96 # the list of heads and bases of the set of interesting revisions.
96 # the list of heads and bases of the set of interesting revisions.
97 # (head = revision in the set that has no descendant in the set;
97 # (head = revision in the set that has no descendant in the set;
98 # base = revision in the set that has no ancestor in the set)
98 # base = revision in the set that has no ancestor in the set)
99 tostrip = set(striplist)
99 tostrip = set(striplist)
100 for rev in striplist:
100 for rev in striplist:
101 for desc in cl.descendants([rev]):
101 for desc in cl.descendants([rev]):
102 tostrip.add(desc)
102 tostrip.add(desc)
103
103
104 files = _collectfiles(repo, striprev)
104 files = _collectfiles(repo, striprev)
105 saverevs = _collectbrokencsets(repo, files, striprev)
105 saverevs = _collectbrokencsets(repo, files, striprev)
106
106
107 # compute heads
107 # compute heads
108 saveheads = set(saverevs)
108 saveheads = set(saverevs)
109 for r in xrange(striprev + 1, len(cl)):
109 for r in xrange(striprev + 1, len(cl)):
110 if r not in tostrip:
110 if r not in tostrip:
111 saverevs.add(r)
111 saverevs.add(r)
112 saveheads.difference_update(cl.parentrevs(r))
112 saveheads.difference_update(cl.parentrevs(r))
113 saveheads.add(r)
113 saveheads.add(r)
114 saveheads = [cl.node(r) for r in saveheads]
114 saveheads = [cl.node(r) for r in saveheads]
115
115
116 # compute base nodes
116 # compute base nodes
117 if saverevs:
117 if saverevs:
118 descendants = set(cl.descendants(saverevs))
118 descendants = set(cl.descendants(saverevs))
119 saverevs.difference_update(descendants)
119 saverevs.difference_update(descendants)
120 savebases = [cl.node(r) for r in saverevs]
120 savebases = [cl.node(r) for r in saverevs]
121 stripbases = [cl.node(r) for r in tostrip]
121 stripbases = [cl.node(r) for r in tostrip]
122
122
123 # For a set s, max(parents(s) - s) is the same as max(heads(::s - s)), but
123 # For a set s, max(parents(s) - s) is the same as max(heads(::s - s)), but
124 # is much faster
124 # is much faster
125 newbmtarget = repo.revs('max(parents(%ld) - (%ld))', tostrip, tostrip)
125 newbmtarget = repo.revs('max(parents(%ld) - (%ld))', tostrip, tostrip)
126 if newbmtarget:
126 if newbmtarget:
127 newbmtarget = repo[newbmtarget.first()].node()
127 newbmtarget = repo[newbmtarget.first()].node()
128 else:
128 else:
129 newbmtarget = '.'
129 newbmtarget = '.'
130
130
131 bm = repo._bookmarks
131 bm = repo._bookmarks
132 updatebm = []
132 updatebm = []
133 for m in bm:
133 for m in bm:
134 rev = repo[bm[m]].rev()
134 rev = repo[bm[m]].rev()
135 if rev in tostrip:
135 if rev in tostrip:
136 updatebm.append(m)
136 updatebm.append(m)
137
137
138 # create a changegroup for all the branches we need to keep
138 # create a changegroup for all the branches we need to keep
139 backupfile = None
139 backupfile = None
140 vfs = repo.vfs
140 vfs = repo.vfs
141 node = nodelist[-1]
141 node = nodelist[-1]
142 if backup:
142 if backup:
143 backupfile = _bundle(repo, stripbases, cl.heads(), node, topic)
143 backupfile = _bundle(repo, stripbases, cl.heads(), node, topic)
144 repo.ui.status(_("saved backup bundle to %s\n") %
144 repo.ui.status(_("saved backup bundle to %s\n") %
145 vfs.join(backupfile))
145 vfs.join(backupfile))
146 repo.ui.log("backupbundle", "saved backup bundle to %s\n",
146 repo.ui.log("backupbundle", "saved backup bundle to %s\n",
147 vfs.join(backupfile))
147 vfs.join(backupfile))
148 if saveheads or savebases:
148 if saveheads or savebases:
149 # do not compress partial bundle if we remove it from disk later
149 # do not compress partial bundle if we remove it from disk later
150 chgrpfile = _bundle(repo, savebases, saveheads, node, 'temp',
150 chgrpfile = _bundle(repo, savebases, saveheads, node, 'temp',
151 compress=False)
151 compress=False)
152
152
153 mfst = repo.manifest
153 mfst = repo.manifest
154
154
155 curtr = repo.currenttransaction()
155 curtr = repo.currenttransaction()
156 if curtr is not None:
156 if curtr is not None:
157 del curtr # avoid carrying reference to transaction for nothing
157 del curtr # avoid carrying reference to transaction for nothing
158 msg = _('programming error: cannot strip from inside a transaction')
158 msg = _('programming error: cannot strip from inside a transaction')
159 raise error.Abort(msg, hint=_('contact your extension maintainer'))
159 raise error.Abort(msg, hint=_('contact your extension maintainer'))
160
160
161 try:
161 try:
162 with repo.transaction("strip") as tr:
162 with repo.transaction("strip") as tr:
163 offset = len(tr.entries)
163 offset = len(tr.entries)
164
164
165 tr.startgroup()
165 tr.startgroup()
166 cl.strip(striprev, tr)
166 cl.strip(striprev, tr)
167 mfst.strip(striprev, tr)
167 mfst.strip(striprev, tr)
168 for fn in files:
168 for fn in files:
169 repo.file(fn).strip(striprev, tr)
169 repo.file(fn).strip(striprev, tr)
170 tr.endgroup()
170 tr.endgroup()
171
171
172 for i in xrange(offset, len(tr.entries)):
172 for i in xrange(offset, len(tr.entries)):
173 file, troffset, ignore = tr.entries[i]
173 file, troffset, ignore = tr.entries[i]
174 repo.svfs(file, 'a').truncate(troffset)
174 repo.svfs(file, 'a').truncate(troffset)
175 if troffset == 0:
175 if troffset == 0:
176 repo.store.markremoved(file)
176 repo.store.markremoved(file)
177
177
178 if saveheads or savebases:
178 if saveheads or savebases:
179 ui.note(_("adding branch\n"))
179 ui.note(_("adding branch\n"))
180 f = vfs.open(chgrpfile, "rb")
180 f = vfs.open(chgrpfile, "rb")
181 gen = exchange.readbundle(ui, f, chgrpfile, vfs)
181 gen = exchange.readbundle(ui, f, chgrpfile, vfs)
182 if not repo.ui.verbose:
182 if not repo.ui.verbose:
183 # silence internal shuffling chatter
183 # silence internal shuffling chatter
184 repo.ui.pushbuffer()
184 repo.ui.pushbuffer()
185 if isinstance(gen, bundle2.unbundle20):
185 if isinstance(gen, bundle2.unbundle20):
186 with repo.transaction('strip') as tr:
186 with repo.transaction('strip') as tr:
187 tr.hookargs = {'source': 'strip',
187 tr.hookargs = {'source': 'strip',
188 'url': 'bundle:' + vfs.join(chgrpfile)}
188 'url': 'bundle:' + vfs.join(chgrpfile)}
189 bundle2.applybundle(repo, gen, tr, source='strip',
189 bundle2.applybundle(repo, gen, tr, source='strip',
190 url='bundle:' + vfs.join(chgrpfile))
190 url='bundle:' + vfs.join(chgrpfile))
191 else:
191 else:
192 gen.apply(repo, 'strip', 'bundle:' + vfs.join(chgrpfile), True)
192 gen.apply(repo, 'strip', 'bundle:' + vfs.join(chgrpfile), True)
193 if not repo.ui.verbose:
193 if not repo.ui.verbose:
194 repo.ui.popbuffer()
194 repo.ui.popbuffer()
195 f.close()
195 f.close()
196
196
197 for m in updatebm:
197 for m in updatebm:
198 bm[m] = repo[newbmtarget].node()
198 bm[m] = repo[newbmtarget].node()
199 lock = tr = None
199 lock = tr = None
200 try:
200 try:
201 lock = repo.lock()
201 lock = repo.lock()
202 tr = repo.transaction('repair')
202 tr = repo.transaction('repair')
203 bm.recordchange(tr)
203 bm.recordchange(tr)
204 tr.close()
204 tr.close()
205 finally:
205 finally:
206 tr.release()
206 tr.release()
207 lock.release()
207 lock.release()
208
208
209 # remove undo files
209 # remove undo files
210 for undovfs, undofile in repo.undofiles():
210 for undovfs, undofile in repo.undofiles():
211 try:
211 try:
212 undovfs.unlink(undofile)
212 undovfs.unlink(undofile)
213 except OSError as e:
213 except OSError as e:
214 if e.errno != errno.ENOENT:
214 if e.errno != errno.ENOENT:
215 ui.warn(_('error removing %s: %s\n') %
215 ui.warn(_('error removing %s: %s\n') %
216 (undovfs.join(undofile), str(e)))
216 (undovfs.join(undofile), str(e)))
217
217
218 except: # re-raises
218 except: # re-raises
219 if backupfile:
219 if backupfile:
220 ui.warn(_("strip failed, full bundle stored in '%s'\n")
220 ui.warn(_("strip failed, full bundle stored in '%s'\n")
221 % vfs.join(backupfile))
221 % vfs.join(backupfile))
222 elif saveheads:
222 elif saveheads:
223 ui.warn(_("strip failed, partial bundle stored in '%s'\n")
223 ui.warn(_("strip failed, partial bundle stored in '%s'\n")
224 % vfs.join(chgrpfile))
224 % vfs.join(chgrpfile))
225 raise
225 raise
226 else:
226 else:
227 if saveheads or savebases:
227 if saveheads or savebases:
228 # Remove partial backup only if there were no exceptions
228 # Remove partial backup only if there were no exceptions
229 vfs.unlink(chgrpfile)
229 vfs.unlink(chgrpfile)
230
230
231 repo.destroyed()
231 repo.destroyed()
232
232
233 def rebuildfncache(ui, repo):
233 def rebuildfncache(ui, repo):
234 """Rebuilds the fncache file from repo history.
234 """Rebuilds the fncache file from repo history.
235
235
236 Missing entries will be added. Extra entries will be removed.
236 Missing entries will be added. Extra entries will be removed.
237 """
237 """
238 repo = repo.unfiltered()
238 repo = repo.unfiltered()
239
239
240 if 'fncache' not in repo.requirements:
240 if 'fncache' not in repo.requirements:
241 ui.warn(_('(not rebuilding fncache because repository does not '
241 ui.warn(_('(not rebuilding fncache because repository does not '
242 'support fncache)\n'))
242 'support fncache)\n'))
243 return
243 return
244
244
245 with repo.lock():
245 with repo.lock():
246 fnc = repo.store.fncache
246 fnc = repo.store.fncache
247 # Trigger load of fncache.
247 # Trigger load of fncache.
248 if 'irrelevant' in fnc:
248 if 'irrelevant' in fnc:
249 pass
249 pass
250
250
251 oldentries = set(fnc.entries)
251 oldentries = set(fnc.entries)
252 newentries = set()
252 newentries = set()
253 seenfiles = set()
253 seenfiles = set()
254
254
255 repolen = len(repo)
255 repolen = len(repo)
256 for rev in repo:
256 for rev in repo:
257 ui.progress(_('changeset'), rev, total=repolen)
257 ui.progress(_('changeset'), rev, total=repolen)
258
258
259 ctx = repo[rev]
259 ctx = repo[rev]
260 for f in ctx.files():
260 for f in ctx.files():
261 # This is to minimize I/O.
261 # This is to minimize I/O.
262 if f in seenfiles:
262 if f in seenfiles:
263 continue
263 continue
264 seenfiles.add(f)
264 seenfiles.add(f)
265
265
266 i = 'data/%s.i' % f
266 i = 'data/%s.i' % f
267 d = 'data/%s.d' % f
267 d = 'data/%s.d' % f
268
268
269 if repo.store._exists(i):
269 if repo.store._exists(i):
270 newentries.add(i)
270 newentries.add(i)
271 if repo.store._exists(d):
271 if repo.store._exists(d):
272 newentries.add(d)
272 newentries.add(d)
273
273
274 ui.progress(_('changeset'), None)
274 ui.progress(_('changeset'), None)
275
275
276 if 'treemanifest' in repo: # safe but unnecessary otherwise
276 if 'treemanifest' in repo.requirements: # safe but unnecessary otherwise
277 for dir in util.dirs(seenfiles):
277 for dir in util.dirs(seenfiles):
278 i = 'meta/%s/00manifest.i' % dir
278 i = 'meta/%s/00manifest.i' % dir
279 d = 'meta/%s/00manifest.d' % dir
279 d = 'meta/%s/00manifest.d' % dir
280
280
281 if repo.store._exists(i):
281 if repo.store._exists(i):
282 newentries.add(i)
282 newentries.add(i)
283 if repo.store._exists(d):
283 if repo.store._exists(d):
284 newentries.add(d)
284 newentries.add(d)
285
285
286 addcount = len(newentries - oldentries)
286 addcount = len(newentries - oldentries)
287 removecount = len(oldentries - newentries)
287 removecount = len(oldentries - newentries)
288 for p in sorted(oldentries - newentries):
288 for p in sorted(oldentries - newentries):
289 ui.write(_('removing %s\n') % p)
289 ui.write(_('removing %s\n') % p)
290 for p in sorted(newentries - oldentries):
290 for p in sorted(newentries - oldentries):
291 ui.write(_('adding %s\n') % p)
291 ui.write(_('adding %s\n') % p)
292
292
293 if addcount or removecount:
293 if addcount or removecount:
294 ui.write(_('%d items added, %d removed from fncache\n') %
294 ui.write(_('%d items added, %d removed from fncache\n') %
295 (addcount, removecount))
295 (addcount, removecount))
296 fnc.entries = newentries
296 fnc.entries = newentries
297 fnc._dirty = True
297 fnc._dirty = True
298
298
299 with repo.transaction('fncache') as tr:
299 with repo.transaction('fncache') as tr:
300 fnc.write(tr)
300 fnc.write(tr)
301 else:
301 else:
302 ui.write(_('fncache already up to date\n'))
302 ui.write(_('fncache already up to date\n'))
303
303
304 def stripbmrevset(repo, mark):
304 def stripbmrevset(repo, mark):
305 """
305 """
306 The revset to strip when strip is called with -B mark
306 The revset to strip when strip is called with -B mark
307
307
308 Needs to live here so extensions can use it and wrap it even when strip is
308 Needs to live here so extensions can use it and wrap it even when strip is
309 not enabled or not present on a box.
309 not enabled or not present on a box.
310 """
310 """
311 return repo.revs("ancestors(bookmark(%s)) - "
311 return repo.revs("ancestors(bookmark(%s)) - "
312 "ancestors(head() and not bookmark(%s)) - "
312 "ancestors(head() and not bookmark(%s)) - "
313 "ancestors(bookmark() and not bookmark(%s))",
313 "ancestors(bookmark() and not bookmark(%s))",
314 mark, mark, mark)
314 mark, mark, mark)
@@ -1,628 +1,661
1 $ cat << EOF >> $HGRCPATH
1 $ cat << EOF >> $HGRCPATH
2 > [format]
2 > [format]
3 > usegeneraldelta=yes
3 > usegeneraldelta=yes
4 > [ui]
4 > [ui]
5 > ssh=python "$TESTDIR/dummyssh"
5 > ssh=python "$TESTDIR/dummyssh"
6 > EOF
6 > EOF
7
7
8 Set up repo
8 Set up repo
9
9
10 $ hg --config experimental.treemanifest=True init repo
10 $ hg --config experimental.treemanifest=True init repo
11 $ cd repo
11 $ cd repo
12
12
13 Requirements get set on init
13 Requirements get set on init
14
14
15 $ grep treemanifest .hg/requires
15 $ grep treemanifest .hg/requires
16 treemanifest
16 treemanifest
17
17
18 Without directories, looks like any other repo
18 Without directories, looks like any other repo
19
19
20 $ echo 0 > a
20 $ echo 0 > a
21 $ echo 0 > b
21 $ echo 0 > b
22 $ hg ci -Aqm initial
22 $ hg ci -Aqm initial
23 $ hg debugdata -m 0
23 $ hg debugdata -m 0
24 a\x00362fef284ce2ca02aecc8de6d5e8a1c3af0556fe (esc)
24 a\x00362fef284ce2ca02aecc8de6d5e8a1c3af0556fe (esc)
25 b\x00362fef284ce2ca02aecc8de6d5e8a1c3af0556fe (esc)
25 b\x00362fef284ce2ca02aecc8de6d5e8a1c3af0556fe (esc)
26
26
27 Submanifest is stored in separate revlog
27 Submanifest is stored in separate revlog
28
28
29 $ mkdir dir1
29 $ mkdir dir1
30 $ echo 1 > dir1/a
30 $ echo 1 > dir1/a
31 $ echo 1 > dir1/b
31 $ echo 1 > dir1/b
32 $ echo 1 > e
32 $ echo 1 > e
33 $ hg ci -Aqm 'add dir1'
33 $ hg ci -Aqm 'add dir1'
34 $ hg debugdata -m 1
34 $ hg debugdata -m 1
35 a\x00362fef284ce2ca02aecc8de6d5e8a1c3af0556fe (esc)
35 a\x00362fef284ce2ca02aecc8de6d5e8a1c3af0556fe (esc)
36 b\x00362fef284ce2ca02aecc8de6d5e8a1c3af0556fe (esc)
36 b\x00362fef284ce2ca02aecc8de6d5e8a1c3af0556fe (esc)
37 dir1\x008b3ffd73f901e83304c83d33132c8e774ceac44et (esc)
37 dir1\x008b3ffd73f901e83304c83d33132c8e774ceac44et (esc)
38 e\x00b8e02f6433738021a065f94175c7cd23db5f05be (esc)
38 e\x00b8e02f6433738021a065f94175c7cd23db5f05be (esc)
39 $ hg debugdata --dir dir1 0
39 $ hg debugdata --dir dir1 0
40 a\x00b8e02f6433738021a065f94175c7cd23db5f05be (esc)
40 a\x00b8e02f6433738021a065f94175c7cd23db5f05be (esc)
41 b\x00b8e02f6433738021a065f94175c7cd23db5f05be (esc)
41 b\x00b8e02f6433738021a065f94175c7cd23db5f05be (esc)
42
42
43 Can add nested directories
43 Can add nested directories
44
44
45 $ mkdir dir1/dir1
45 $ mkdir dir1/dir1
46 $ echo 2 > dir1/dir1/a
46 $ echo 2 > dir1/dir1/a
47 $ echo 2 > dir1/dir1/b
47 $ echo 2 > dir1/dir1/b
48 $ mkdir dir1/dir2
48 $ mkdir dir1/dir2
49 $ echo 2 > dir1/dir2/a
49 $ echo 2 > dir1/dir2/a
50 $ echo 2 > dir1/dir2/b
50 $ echo 2 > dir1/dir2/b
51 $ hg ci -Aqm 'add dir1/dir1'
51 $ hg ci -Aqm 'add dir1/dir1'
52 $ hg files -r .
52 $ hg files -r .
53 a
53 a
54 b
54 b
55 dir1/a (glob)
55 dir1/a (glob)
56 dir1/b (glob)
56 dir1/b (glob)
57 dir1/dir1/a (glob)
57 dir1/dir1/a (glob)
58 dir1/dir1/b (glob)
58 dir1/dir1/b (glob)
59 dir1/dir2/a (glob)
59 dir1/dir2/a (glob)
60 dir1/dir2/b (glob)
60 dir1/dir2/b (glob)
61 e
61 e
62
62
63 Revision is not created for unchanged directory
63 Revision is not created for unchanged directory
64
64
65 $ mkdir dir2
65 $ mkdir dir2
66 $ echo 3 > dir2/a
66 $ echo 3 > dir2/a
67 $ hg add dir2
67 $ hg add dir2
68 adding dir2/a (glob)
68 adding dir2/a (glob)
69 $ hg debugindex --dir dir1 > before
69 $ hg debugindex --dir dir1 > before
70 $ hg ci -qm 'add dir2'
70 $ hg ci -qm 'add dir2'
71 $ hg debugindex --dir dir1 > after
71 $ hg debugindex --dir dir1 > after
72 $ diff before after
72 $ diff before after
73 $ rm before after
73 $ rm before after
74
74
75 Removing directory does not create an revlog entry
75 Removing directory does not create an revlog entry
76
76
77 $ hg rm dir1/dir1
77 $ hg rm dir1/dir1
78 removing dir1/dir1/a (glob)
78 removing dir1/dir1/a (glob)
79 removing dir1/dir1/b (glob)
79 removing dir1/dir1/b (glob)
80 $ hg debugindex --dir dir1/dir1 > before
80 $ hg debugindex --dir dir1/dir1 > before
81 $ hg ci -qm 'remove dir1/dir1'
81 $ hg ci -qm 'remove dir1/dir1'
82 $ hg debugindex --dir dir1/dir1 > after
82 $ hg debugindex --dir dir1/dir1 > after
83 $ diff before after
83 $ diff before after
84 $ rm before after
84 $ rm before after
85
85
86 Check that hg files (calls treemanifest.walk()) works
86 Check that hg files (calls treemanifest.walk()) works
87 without loading all directory revlogs
87 without loading all directory revlogs
88
88
89 $ hg co 'desc("add dir2")'
89 $ hg co 'desc("add dir2")'
90 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
90 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
91 $ mv .hg/store/meta/dir2 .hg/store/meta/dir2-backup
91 $ mv .hg/store/meta/dir2 .hg/store/meta/dir2-backup
92 $ hg files -r . dir1
92 $ hg files -r . dir1
93 dir1/a (glob)
93 dir1/a (glob)
94 dir1/b (glob)
94 dir1/b (glob)
95 dir1/dir1/a (glob)
95 dir1/dir1/a (glob)
96 dir1/dir1/b (glob)
96 dir1/dir1/b (glob)
97 dir1/dir2/a (glob)
97 dir1/dir2/a (glob)
98 dir1/dir2/b (glob)
98 dir1/dir2/b (glob)
99
99
100 Check that status between revisions works (calls treemanifest.matches())
100 Check that status between revisions works (calls treemanifest.matches())
101 without loading all directory revlogs
101 without loading all directory revlogs
102
102
103 $ hg status --rev 'desc("add dir1")' --rev . dir1
103 $ hg status --rev 'desc("add dir1")' --rev . dir1
104 A dir1/dir1/a
104 A dir1/dir1/a
105 A dir1/dir1/b
105 A dir1/dir1/b
106 A dir1/dir2/a
106 A dir1/dir2/a
107 A dir1/dir2/b
107 A dir1/dir2/b
108 $ mv .hg/store/meta/dir2-backup .hg/store/meta/dir2
108 $ mv .hg/store/meta/dir2-backup .hg/store/meta/dir2
109
109
110 Merge creates 2-parent revision of directory revlog
110 Merge creates 2-parent revision of directory revlog
111
111
112 $ echo 5 > dir1/a
112 $ echo 5 > dir1/a
113 $ hg ci -Aqm 'modify dir1/a'
113 $ hg ci -Aqm 'modify dir1/a'
114 $ hg co '.^'
114 $ hg co '.^'
115 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
115 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
116 $ echo 6 > dir1/b
116 $ echo 6 > dir1/b
117 $ hg ci -Aqm 'modify dir1/b'
117 $ hg ci -Aqm 'modify dir1/b'
118 $ hg merge 'desc("modify dir1/a")'
118 $ hg merge 'desc("modify dir1/a")'
119 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
119 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
120 (branch merge, don't forget to commit)
120 (branch merge, don't forget to commit)
121 $ hg ci -m 'conflict-free merge involving dir1/'
121 $ hg ci -m 'conflict-free merge involving dir1/'
122 $ cat dir1/a
122 $ cat dir1/a
123 5
123 5
124 $ cat dir1/b
124 $ cat dir1/b
125 6
125 6
126 $ hg debugindex --dir dir1
126 $ hg debugindex --dir dir1
127 rev offset length delta linkrev nodeid p1 p2
127 rev offset length delta linkrev nodeid p1 p2
128 0 0 54 -1 1 8b3ffd73f901 000000000000 000000000000
128 0 0 54 -1 1 8b3ffd73f901 000000000000 000000000000
129 1 54 68 0 2 68e9d057c5a8 8b3ffd73f901 000000000000
129 1 54 68 0 2 68e9d057c5a8 8b3ffd73f901 000000000000
130 2 122 12 1 4 4698198d2624 68e9d057c5a8 000000000000
130 2 122 12 1 4 4698198d2624 68e9d057c5a8 000000000000
131 3 134 55 1 5 44844058ccce 68e9d057c5a8 000000000000
131 3 134 55 1 5 44844058ccce 68e9d057c5a8 000000000000
132 4 189 55 1 6 bf3d9b744927 68e9d057c5a8 000000000000
132 4 189 55 1 6 bf3d9b744927 68e9d057c5a8 000000000000
133 5 244 55 4 7 dde7c0af2a03 bf3d9b744927 44844058ccce
133 5 244 55 4 7 dde7c0af2a03 bf3d9b744927 44844058ccce
134
134
135 Merge keeping directory from parent 1 does not create revlog entry. (Note that
135 Merge keeping directory from parent 1 does not create revlog entry. (Note that
136 dir1's manifest does change, but only because dir1/a's filelog changes.)
136 dir1's manifest does change, but only because dir1/a's filelog changes.)
137
137
138 $ hg co 'desc("add dir2")'
138 $ hg co 'desc("add dir2")'
139 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
139 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
140 $ echo 8 > dir2/a
140 $ echo 8 > dir2/a
141 $ hg ci -m 'modify dir2/a'
141 $ hg ci -m 'modify dir2/a'
142 created new head
142 created new head
143
143
144 $ hg debugindex --dir dir2 > before
144 $ hg debugindex --dir dir2 > before
145 $ hg merge 'desc("modify dir1/a")'
145 $ hg merge 'desc("modify dir1/a")'
146 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
146 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
147 (branch merge, don't forget to commit)
147 (branch merge, don't forget to commit)
148 $ hg revert -r 'desc("modify dir2/a")' .
148 $ hg revert -r 'desc("modify dir2/a")' .
149 reverting dir1/a (glob)
149 reverting dir1/a (glob)
150 $ hg ci -m 'merge, keeping parent 1'
150 $ hg ci -m 'merge, keeping parent 1'
151 $ hg debugindex --dir dir2 > after
151 $ hg debugindex --dir dir2 > after
152 $ diff before after
152 $ diff before after
153 $ rm before after
153 $ rm before after
154
154
155 Merge keeping directory from parent 2 does not create revlog entry. (Note that
155 Merge keeping directory from parent 2 does not create revlog entry. (Note that
156 dir2's manifest does change, but only because dir2/a's filelog changes.)
156 dir2's manifest does change, but only because dir2/a's filelog changes.)
157
157
158 $ hg co 'desc("modify dir2/a")'
158 $ hg co 'desc("modify dir2/a")'
159 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
159 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
160 $ hg debugindex --dir dir1 > before
160 $ hg debugindex --dir dir1 > before
161 $ hg merge 'desc("modify dir1/a")'
161 $ hg merge 'desc("modify dir1/a")'
162 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
162 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
163 (branch merge, don't forget to commit)
163 (branch merge, don't forget to commit)
164 $ hg revert -r 'desc("modify dir1/a")' .
164 $ hg revert -r 'desc("modify dir1/a")' .
165 reverting dir2/a (glob)
165 reverting dir2/a (glob)
166 $ hg ci -m 'merge, keeping parent 2'
166 $ hg ci -m 'merge, keeping parent 2'
167 created new head
167 created new head
168 $ hg debugindex --dir dir1 > after
168 $ hg debugindex --dir dir1 > after
169 $ diff before after
169 $ diff before after
170 $ rm before after
170 $ rm before after
171
171
172 Create flat source repo for tests with mixed flat/tree manifests
172 Create flat source repo for tests with mixed flat/tree manifests
173
173
174 $ cd ..
174 $ cd ..
175 $ hg init repo-flat
175 $ hg init repo-flat
176 $ cd repo-flat
176 $ cd repo-flat
177
177
178 Create a few commits with flat manifest
178 Create a few commits with flat manifest
179
179
180 $ echo 0 > a
180 $ echo 0 > a
181 $ echo 0 > b
181 $ echo 0 > b
182 $ echo 0 > e
182 $ echo 0 > e
183 $ for d in dir1 dir1/dir1 dir1/dir2 dir2
183 $ for d in dir1 dir1/dir1 dir1/dir2 dir2
184 > do
184 > do
185 > mkdir $d
185 > mkdir $d
186 > echo 0 > $d/a
186 > echo 0 > $d/a
187 > echo 0 > $d/b
187 > echo 0 > $d/b
188 > done
188 > done
189 $ hg ci -Aqm initial
189 $ hg ci -Aqm initial
190
190
191 $ echo 1 > a
191 $ echo 1 > a
192 $ echo 1 > dir1/a
192 $ echo 1 > dir1/a
193 $ echo 1 > dir1/dir1/a
193 $ echo 1 > dir1/dir1/a
194 $ hg ci -Aqm 'modify on branch 1'
194 $ hg ci -Aqm 'modify on branch 1'
195
195
196 $ hg co 0
196 $ hg co 0
197 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
197 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
198 $ echo 2 > b
198 $ echo 2 > b
199 $ echo 2 > dir1/b
199 $ echo 2 > dir1/b
200 $ echo 2 > dir1/dir1/b
200 $ echo 2 > dir1/dir1/b
201 $ hg ci -Aqm 'modify on branch 2'
201 $ hg ci -Aqm 'modify on branch 2'
202
202
203 $ hg merge 1
203 $ hg merge 1
204 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
204 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
205 (branch merge, don't forget to commit)
205 (branch merge, don't forget to commit)
206 $ hg ci -m 'merge of flat manifests to new flat manifest'
206 $ hg ci -m 'merge of flat manifests to new flat manifest'
207
207
208 $ hg serve -p $HGPORT -d --pid-file=hg.pid --errorlog=errors.log
208 $ hg serve -p $HGPORT -d --pid-file=hg.pid --errorlog=errors.log
209 $ cat hg.pid >> $DAEMON_PIDS
209 $ cat hg.pid >> $DAEMON_PIDS
210
210
211 Create clone with tree manifests enabled
211 Create clone with tree manifests enabled
212
212
213 $ cd ..
213 $ cd ..
214 $ hg clone --config experimental.treemanifest=1 \
214 $ hg clone --config experimental.treemanifest=1 \
215 > http://localhost:$HGPORT repo-mixed -r 1
215 > http://localhost:$HGPORT repo-mixed -r 1
216 adding changesets
216 adding changesets
217 adding manifests
217 adding manifests
218 adding file changes
218 adding file changes
219 added 2 changesets with 14 changes to 11 files
219 added 2 changesets with 14 changes to 11 files
220 updating to branch default
220 updating to branch default
221 11 files updated, 0 files merged, 0 files removed, 0 files unresolved
221 11 files updated, 0 files merged, 0 files removed, 0 files unresolved
222 $ cd repo-mixed
222 $ cd repo-mixed
223 $ test -d .hg/store/meta
223 $ test -d .hg/store/meta
224 [1]
224 [1]
225 $ grep treemanifest .hg/requires
225 $ grep treemanifest .hg/requires
226 treemanifest
226 treemanifest
227
227
228 Should be possible to push updates from flat to tree manifest repo
228 Should be possible to push updates from flat to tree manifest repo
229
229
230 $ hg -R ../repo-flat push ssh://user@dummy/repo-mixed
230 $ hg -R ../repo-flat push ssh://user@dummy/repo-mixed
231 pushing to ssh://user@dummy/repo-mixed
231 pushing to ssh://user@dummy/repo-mixed
232 searching for changes
232 searching for changes
233 remote: adding changesets
233 remote: adding changesets
234 remote: adding manifests
234 remote: adding manifests
235 remote: adding file changes
235 remote: adding file changes
236 remote: added 2 changesets with 3 changes to 3 files
236 remote: added 2 changesets with 3 changes to 3 files
237
237
238 Commit should store revlog per directory
238 Commit should store revlog per directory
239
239
240 $ hg co 1
240 $ hg co 1
241 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
241 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
242 $ echo 3 > a
242 $ echo 3 > a
243 $ echo 3 > dir1/a
243 $ echo 3 > dir1/a
244 $ echo 3 > dir1/dir1/a
244 $ echo 3 > dir1/dir1/a
245 $ hg ci -m 'first tree'
245 $ hg ci -m 'first tree'
246 created new head
246 created new head
247 $ find .hg/store/meta | sort
247 $ find .hg/store/meta | sort
248 .hg/store/meta
248 .hg/store/meta
249 .hg/store/meta/dir1
249 .hg/store/meta/dir1
250 .hg/store/meta/dir1/00manifest.i
250 .hg/store/meta/dir1/00manifest.i
251 .hg/store/meta/dir1/dir1
251 .hg/store/meta/dir1/dir1
252 .hg/store/meta/dir1/dir1/00manifest.i
252 .hg/store/meta/dir1/dir1/00manifest.i
253 .hg/store/meta/dir1/dir2
253 .hg/store/meta/dir1/dir2
254 .hg/store/meta/dir1/dir2/00manifest.i
254 .hg/store/meta/dir1/dir2/00manifest.i
255 .hg/store/meta/dir2
255 .hg/store/meta/dir2
256 .hg/store/meta/dir2/00manifest.i
256 .hg/store/meta/dir2/00manifest.i
257
257
258 Merge of two trees
258 Merge of two trees
259
259
260 $ hg co 2
260 $ hg co 2
261 6 files updated, 0 files merged, 0 files removed, 0 files unresolved
261 6 files updated, 0 files merged, 0 files removed, 0 files unresolved
262 $ hg merge 1
262 $ hg merge 1
263 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
263 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
264 (branch merge, don't forget to commit)
264 (branch merge, don't forget to commit)
265 $ hg ci -m 'merge of flat manifests to new tree manifest'
265 $ hg ci -m 'merge of flat manifests to new tree manifest'
266 created new head
266 created new head
267 $ hg diff -r 3
267 $ hg diff -r 3
268
268
269 Parent of tree root manifest should be flat manifest, and two for merge
269 Parent of tree root manifest should be flat manifest, and two for merge
270
270
271 $ hg debugindex -m
271 $ hg debugindex -m
272 rev offset length delta linkrev nodeid p1 p2
272 rev offset length delta linkrev nodeid p1 p2
273 0 0 80 -1 0 40536115ed9e 000000000000 000000000000
273 0 0 80 -1 0 40536115ed9e 000000000000 000000000000
274 1 80 83 0 1 f3376063c255 40536115ed9e 000000000000
274 1 80 83 0 1 f3376063c255 40536115ed9e 000000000000
275 2 163 89 0 2 5d9b9da231a2 40536115ed9e 000000000000
275 2 163 89 0 2 5d9b9da231a2 40536115ed9e 000000000000
276 3 252 83 2 3 d17d663cbd8a 5d9b9da231a2 f3376063c255
276 3 252 83 2 3 d17d663cbd8a 5d9b9da231a2 f3376063c255
277 4 335 124 1 4 51e32a8c60ee f3376063c255 000000000000
277 4 335 124 1 4 51e32a8c60ee f3376063c255 000000000000
278 5 459 126 2 5 cc5baa78b230 5d9b9da231a2 f3376063c255
278 5 459 126 2 5 cc5baa78b230 5d9b9da231a2 f3376063c255
279
279
280
280
281 Status across flat/tree boundary should work
281 Status across flat/tree boundary should work
282
282
283 $ hg status --rev '.^' --rev .
283 $ hg status --rev '.^' --rev .
284 M a
284 M a
285 M dir1/a
285 M dir1/a
286 M dir1/dir1/a
286 M dir1/dir1/a
287
287
288
288
289 Turning off treemanifest config has no effect
289 Turning off treemanifest config has no effect
290
290
291 $ hg debugindex --dir dir1
291 $ hg debugindex --dir dir1
292 rev offset length delta linkrev nodeid p1 p2
292 rev offset length delta linkrev nodeid p1 p2
293 0 0 127 -1 4 064927a0648a 000000000000 000000000000
293 0 0 127 -1 4 064927a0648a 000000000000 000000000000
294 1 127 111 0 5 25ecb8cb8618 000000000000 000000000000
294 1 127 111 0 5 25ecb8cb8618 000000000000 000000000000
295 $ echo 2 > dir1/a
295 $ echo 2 > dir1/a
296 $ hg --config experimental.treemanifest=False ci -qm 'modify dir1/a'
296 $ hg --config experimental.treemanifest=False ci -qm 'modify dir1/a'
297 $ hg debugindex --dir dir1
297 $ hg debugindex --dir dir1
298 rev offset length delta linkrev nodeid p1 p2
298 rev offset length delta linkrev nodeid p1 p2
299 0 0 127 -1 4 064927a0648a 000000000000 000000000000
299 0 0 127 -1 4 064927a0648a 000000000000 000000000000
300 1 127 111 0 5 25ecb8cb8618 000000000000 000000000000
300 1 127 111 0 5 25ecb8cb8618 000000000000 000000000000
301 2 238 55 1 6 5b16163a30c6 25ecb8cb8618 000000000000
301 2 238 55 1 6 5b16163a30c6 25ecb8cb8618 000000000000
302
302
303 Stripping and recovering changes should work
303 Stripping and recovering changes should work
304
304
305 $ hg st --change tip
305 $ hg st --change tip
306 M dir1/a
306 M dir1/a
307 $ hg --config extensions.strip= strip tip
307 $ hg --config extensions.strip= strip tip
308 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
308 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
309 saved backup bundle to $TESTTMP/repo-mixed/.hg/strip-backup/51cfd7b1e13b-78a2f3ed-backup.hg (glob)
309 saved backup bundle to $TESTTMP/repo-mixed/.hg/strip-backup/51cfd7b1e13b-78a2f3ed-backup.hg (glob)
310 $ hg unbundle -q .hg/strip-backup/*
310 $ hg unbundle -q .hg/strip-backup/*
311 $ hg st --change tip
311 $ hg st --change tip
312 M dir1/a
312 M dir1/a
313
313
314 Shelving and unshelving should work
314 Shelving and unshelving should work
315
315
316 $ echo foo >> dir1/a
316 $ echo foo >> dir1/a
317 $ hg --config extensions.shelve= shelve
317 $ hg --config extensions.shelve= shelve
318 shelved as default
318 shelved as default
319 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
319 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
320 $ hg --config extensions.shelve= unshelve
320 $ hg --config extensions.shelve= unshelve
321 unshelving change 'default'
321 unshelving change 'default'
322 $ hg diff --nodates
322 $ hg diff --nodates
323 diff -r 708a273da119 dir1/a
323 diff -r 708a273da119 dir1/a
324 --- a/dir1/a
324 --- a/dir1/a
325 +++ b/dir1/a
325 +++ b/dir1/a
326 @@ -1,1 +1,2 @@
326 @@ -1,1 +1,2 @@
327 1
327 1
328 +foo
328 +foo
329
329
330 Pushing from treemanifest repo to an empty repo makes that a treemanifest repo
330 Pushing from treemanifest repo to an empty repo makes that a treemanifest repo
331
331
332 $ cd ..
332 $ cd ..
333 $ hg init empty-repo
333 $ hg init empty-repo
334 $ cat << EOF >> empty-repo/.hg/hgrc
334 $ cat << EOF >> empty-repo/.hg/hgrc
335 > [experimental]
335 > [experimental]
336 > changegroup3=yes
336 > changegroup3=yes
337 > EOF
337 > EOF
338 $ grep treemanifest empty-repo/.hg/requires
338 $ grep treemanifest empty-repo/.hg/requires
339 [1]
339 [1]
340 $ hg push -R repo -r 0 empty-repo
340 $ hg push -R repo -r 0 empty-repo
341 pushing to empty-repo
341 pushing to empty-repo
342 searching for changes
342 searching for changes
343 adding changesets
343 adding changesets
344 adding manifests
344 adding manifests
345 adding file changes
345 adding file changes
346 added 1 changesets with 2 changes to 2 files
346 added 1 changesets with 2 changes to 2 files
347 $ grep treemanifest empty-repo/.hg/requires
347 $ grep treemanifest empty-repo/.hg/requires
348 treemanifest
348 treemanifest
349
349
350 Pushing to an empty repo works
350 Pushing to an empty repo works
351
351
352 $ hg --config experimental.treemanifest=1 init clone
352 $ hg --config experimental.treemanifest=1 init clone
353 $ grep treemanifest clone/.hg/requires
353 $ grep treemanifest clone/.hg/requires
354 treemanifest
354 treemanifest
355 $ hg push -R repo clone
355 $ hg push -R repo clone
356 pushing to clone
356 pushing to clone
357 searching for changes
357 searching for changes
358 adding changesets
358 adding changesets
359 adding manifests
359 adding manifests
360 adding file changes
360 adding file changes
361 added 11 changesets with 15 changes to 10 files (+3 heads)
361 added 11 changesets with 15 changes to 10 files (+3 heads)
362 $ grep treemanifest clone/.hg/requires
362 $ grep treemanifest clone/.hg/requires
363 treemanifest
363 treemanifest
364
364
365 Create deeper repo with tree manifests.
365 Create deeper repo with tree manifests.
366
366
367 $ hg --config experimental.treemanifest=True init deeprepo
367 $ hg --config experimental.treemanifest=True init deeprepo
368 $ cd deeprepo
368 $ cd deeprepo
369
369
370 $ mkdir .A
370 $ mkdir .A
371 $ mkdir b
371 $ mkdir b
372 $ mkdir b/bar
372 $ mkdir b/bar
373 $ mkdir b/bar/orange
373 $ mkdir b/bar/orange
374 $ mkdir b/bar/orange/fly
374 $ mkdir b/bar/orange/fly
375 $ mkdir b/foo
375 $ mkdir b/foo
376 $ mkdir b/foo/apple
376 $ mkdir b/foo/apple
377 $ mkdir b/foo/apple/bees
377 $ mkdir b/foo/apple/bees
378
378
379 $ touch .A/one.txt
379 $ touch .A/one.txt
380 $ touch .A/two.txt
380 $ touch .A/two.txt
381 $ touch b/bar/fruits.txt
381 $ touch b/bar/fruits.txt
382 $ touch b/bar/orange/fly/gnat.py
382 $ touch b/bar/orange/fly/gnat.py
383 $ touch b/bar/orange/fly/housefly.txt
383 $ touch b/bar/orange/fly/housefly.txt
384 $ touch b/foo/apple/bees/flower.py
384 $ touch b/foo/apple/bees/flower.py
385 $ touch c.txt
385 $ touch c.txt
386 $ touch d.py
386 $ touch d.py
387
387
388 $ hg ci -Aqm 'initial'
388 $ hg ci -Aqm 'initial'
389
389
390 We'll see that visitdir works by removing some treemanifest revlogs and running
390 We'll see that visitdir works by removing some treemanifest revlogs and running
391 the files command with various parameters.
391 the files command with various parameters.
392
392
393 Test files from the root.
393 Test files from the root.
394
394
395 $ hg files -r .
395 $ hg files -r .
396 .A/one.txt (glob)
396 .A/one.txt (glob)
397 .A/two.txt (glob)
397 .A/two.txt (glob)
398 b/bar/fruits.txt (glob)
398 b/bar/fruits.txt (glob)
399 b/bar/orange/fly/gnat.py (glob)
399 b/bar/orange/fly/gnat.py (glob)
400 b/bar/orange/fly/housefly.txt (glob)
400 b/bar/orange/fly/housefly.txt (glob)
401 b/foo/apple/bees/flower.py (glob)
401 b/foo/apple/bees/flower.py (glob)
402 c.txt
402 c.txt
403 d.py
403 d.py
404
404
405 Excludes with a glob should not exclude everything from the glob's root
405 Excludes with a glob should not exclude everything from the glob's root
406
406
407 $ hg files -r . -X 'b/fo?' b
407 $ hg files -r . -X 'b/fo?' b
408 b/bar/fruits.txt (glob)
408 b/bar/fruits.txt (glob)
409 b/bar/orange/fly/gnat.py (glob)
409 b/bar/orange/fly/gnat.py (glob)
410 b/bar/orange/fly/housefly.txt (glob)
410 b/bar/orange/fly/housefly.txt (glob)
411 $ cp -r .hg/store .hg/store-copy
411 $ cp -r .hg/store .hg/store-copy
412
412
413 Test files for a subdirectory.
413 Test files for a subdirectory.
414
414
415 $ rm -r .hg/store/meta/~2e_a
415 $ rm -r .hg/store/meta/~2e_a
416 $ hg files -r . b
416 $ hg files -r . b
417 b/bar/fruits.txt (glob)
417 b/bar/fruits.txt (glob)
418 b/bar/orange/fly/gnat.py (glob)
418 b/bar/orange/fly/gnat.py (glob)
419 b/bar/orange/fly/housefly.txt (glob)
419 b/bar/orange/fly/housefly.txt (glob)
420 b/foo/apple/bees/flower.py (glob)
420 b/foo/apple/bees/flower.py (glob)
421 $ cp -rT .hg/store-copy .hg/store
421 $ cp -rT .hg/store-copy .hg/store
422
422
423 Test files with just includes and excludes.
423 Test files with just includes and excludes.
424
424
425 $ rm -r .hg/store/meta/~2e_a
425 $ rm -r .hg/store/meta/~2e_a
426 $ rm -r .hg/store/meta/b/bar/orange/fly
426 $ rm -r .hg/store/meta/b/bar/orange/fly
427 $ rm -r .hg/store/meta/b/foo/apple/bees
427 $ rm -r .hg/store/meta/b/foo/apple/bees
428 $ hg files -r . -I path:b/bar -X path:b/bar/orange/fly -I path:b/foo -X path:b/foo/apple/bees
428 $ hg files -r . -I path:b/bar -X path:b/bar/orange/fly -I path:b/foo -X path:b/foo/apple/bees
429 b/bar/fruits.txt (glob)
429 b/bar/fruits.txt (glob)
430 $ cp -rT .hg/store-copy .hg/store
430 $ cp -rT .hg/store-copy .hg/store
431
431
432 Test files for a subdirectory, excluding a directory within it.
432 Test files for a subdirectory, excluding a directory within it.
433
433
434 $ rm -r .hg/store/meta/~2e_a
434 $ rm -r .hg/store/meta/~2e_a
435 $ rm -r .hg/store/meta/b/foo
435 $ rm -r .hg/store/meta/b/foo
436 $ hg files -r . -X path:b/foo b
436 $ hg files -r . -X path:b/foo b
437 b/bar/fruits.txt (glob)
437 b/bar/fruits.txt (glob)
438 b/bar/orange/fly/gnat.py (glob)
438 b/bar/orange/fly/gnat.py (glob)
439 b/bar/orange/fly/housefly.txt (glob)
439 b/bar/orange/fly/housefly.txt (glob)
440 $ cp -rT .hg/store-copy .hg/store
440 $ cp -rT .hg/store-copy .hg/store
441
441
442 Test files for a sub directory, including only a directory within it, and
442 Test files for a sub directory, including only a directory within it, and
443 including an unrelated directory.
443 including an unrelated directory.
444
444
445 $ rm -r .hg/store/meta/~2e_a
445 $ rm -r .hg/store/meta/~2e_a
446 $ rm -r .hg/store/meta/b/foo
446 $ rm -r .hg/store/meta/b/foo
447 $ hg files -r . -I path:b/bar/orange -I path:a b
447 $ hg files -r . -I path:b/bar/orange -I path:a b
448 b/bar/orange/fly/gnat.py (glob)
448 b/bar/orange/fly/gnat.py (glob)
449 b/bar/orange/fly/housefly.txt (glob)
449 b/bar/orange/fly/housefly.txt (glob)
450 $ cp -rT .hg/store-copy .hg/store
450 $ cp -rT .hg/store-copy .hg/store
451
451
452 Test files for a pattern, including a directory, and excluding a directory
452 Test files for a pattern, including a directory, and excluding a directory
453 within that.
453 within that.
454
454
455 $ rm -r .hg/store/meta/~2e_a
455 $ rm -r .hg/store/meta/~2e_a
456 $ rm -r .hg/store/meta/b/foo
456 $ rm -r .hg/store/meta/b/foo
457 $ rm -r .hg/store/meta/b/bar/orange
457 $ rm -r .hg/store/meta/b/bar/orange
458 $ hg files -r . glob:**.txt -I path:b/bar -X path:b/bar/orange
458 $ hg files -r . glob:**.txt -I path:b/bar -X path:b/bar/orange
459 b/bar/fruits.txt (glob)
459 b/bar/fruits.txt (glob)
460 $ cp -rT .hg/store-copy .hg/store
460 $ cp -rT .hg/store-copy .hg/store
461
461
462 Add some more changes to the deep repo
462 Add some more changes to the deep repo
463 $ echo narf >> b/bar/fruits.txt
463 $ echo narf >> b/bar/fruits.txt
464 $ hg ci -m narf
464 $ hg ci -m narf
465 $ echo troz >> b/bar/orange/fly/gnat.py
465 $ echo troz >> b/bar/orange/fly/gnat.py
466 $ hg ci -m troz
466 $ hg ci -m troz
467
467
468 Verify works
469 $ hg verify
470 checking changesets
471 checking manifests
472 crosschecking files in changesets and manifests
473 checking files
474 8 files, 3 changesets, 10 total revisions
475
476 Dirlogs are included in fncache
477 $ grep meta/.A/00manifest.i .hg/store/fncache
478 meta/.A/00manifest.i
479
480 Rebuilt fncache includes dirlogs
481 $ rm .hg/store/fncache
482 $ hg debugrebuildfncache
483 adding data/.A/one.txt.i
484 adding data/.A/two.txt.i
485 adding data/b/bar/fruits.txt.i
486 adding data/b/bar/orange/fly/gnat.py.i
487 adding data/b/bar/orange/fly/housefly.txt.i
488 adding data/b/foo/apple/bees/flower.py.i
489 adding data/c.txt.i
490 adding data/d.py.i
491 adding meta/.A/00manifest.i
492 adding meta/b/00manifest.i
493 adding meta/b/bar/00manifest.i
494 adding meta/b/bar/orange/00manifest.i
495 adding meta/b/bar/orange/fly/00manifest.i
496 adding meta/b/foo/00manifest.i
497 adding meta/b/foo/apple/00manifest.i
498 adding meta/b/foo/apple/bees/00manifest.i
499 16 items added, 0 removed from fncache
500
468 Test cloning a treemanifest repo over http.
501 Test cloning a treemanifest repo over http.
469 $ hg serve -p $HGPORT2 -d --pid-file=hg.pid --errorlog=errors.log
502 $ hg serve -p $HGPORT2 -d --pid-file=hg.pid --errorlog=errors.log
470 $ cat hg.pid >> $DAEMON_PIDS
503 $ cat hg.pid >> $DAEMON_PIDS
471 $ cd ..
504 $ cd ..
472 We can clone even with the knob turned off and we'll get a treemanifest repo.
505 We can clone even with the knob turned off and we'll get a treemanifest repo.
473 $ hg clone --config experimental.treemanifest=False \
506 $ hg clone --config experimental.treemanifest=False \
474 > --config experimental.changegroup3=True \
507 > --config experimental.changegroup3=True \
475 > http://localhost:$HGPORT2 deepclone
508 > http://localhost:$HGPORT2 deepclone
476 requesting all changes
509 requesting all changes
477 adding changesets
510 adding changesets
478 adding manifests
511 adding manifests
479 adding file changes
512 adding file changes
480 added 3 changesets with 10 changes to 8 files
513 added 3 changesets with 10 changes to 8 files
481 updating to branch default
514 updating to branch default
482 8 files updated, 0 files merged, 0 files removed, 0 files unresolved
515 8 files updated, 0 files merged, 0 files removed, 0 files unresolved
483 No server errors.
516 No server errors.
484 $ cat deeprepo/errors.log
517 $ cat deeprepo/errors.log
485 requires got updated to include treemanifest
518 requires got updated to include treemanifest
486 $ cat deepclone/.hg/requires | grep treemanifest
519 $ cat deepclone/.hg/requires | grep treemanifest
487 treemanifest
520 treemanifest
488 Tree manifest revlogs exist.
521 Tree manifest revlogs exist.
489 $ find deepclone/.hg/store/meta | sort
522 $ find deepclone/.hg/store/meta | sort
490 deepclone/.hg/store/meta
523 deepclone/.hg/store/meta
491 deepclone/.hg/store/meta/b
524 deepclone/.hg/store/meta/b
492 deepclone/.hg/store/meta/b/00manifest.i
525 deepclone/.hg/store/meta/b/00manifest.i
493 deepclone/.hg/store/meta/b/bar
526 deepclone/.hg/store/meta/b/bar
494 deepclone/.hg/store/meta/b/bar/00manifest.i
527 deepclone/.hg/store/meta/b/bar/00manifest.i
495 deepclone/.hg/store/meta/b/bar/orange
528 deepclone/.hg/store/meta/b/bar/orange
496 deepclone/.hg/store/meta/b/bar/orange/00manifest.i
529 deepclone/.hg/store/meta/b/bar/orange/00manifest.i
497 deepclone/.hg/store/meta/b/bar/orange/fly
530 deepclone/.hg/store/meta/b/bar/orange/fly
498 deepclone/.hg/store/meta/b/bar/orange/fly/00manifest.i
531 deepclone/.hg/store/meta/b/bar/orange/fly/00manifest.i
499 deepclone/.hg/store/meta/b/foo
532 deepclone/.hg/store/meta/b/foo
500 deepclone/.hg/store/meta/b/foo/00manifest.i
533 deepclone/.hg/store/meta/b/foo/00manifest.i
501 deepclone/.hg/store/meta/b/foo/apple
534 deepclone/.hg/store/meta/b/foo/apple
502 deepclone/.hg/store/meta/b/foo/apple/00manifest.i
535 deepclone/.hg/store/meta/b/foo/apple/00manifest.i
503 deepclone/.hg/store/meta/b/foo/apple/bees
536 deepclone/.hg/store/meta/b/foo/apple/bees
504 deepclone/.hg/store/meta/b/foo/apple/bees/00manifest.i
537 deepclone/.hg/store/meta/b/foo/apple/bees/00manifest.i
505 deepclone/.hg/store/meta/~2e_a
538 deepclone/.hg/store/meta/~2e_a
506 deepclone/.hg/store/meta/~2e_a/00manifest.i
539 deepclone/.hg/store/meta/~2e_a/00manifest.i
507 Verify passes.
540 Verify passes.
508 $ cd deepclone
541 $ cd deepclone
509 $ hg verify
542 $ hg verify
510 checking changesets
543 checking changesets
511 checking manifests
544 checking manifests
512 crosschecking files in changesets and manifests
545 crosschecking files in changesets and manifests
513 checking files
546 checking files
514 8 files, 3 changesets, 10 total revisions
547 8 files, 3 changesets, 10 total revisions
515 $ cd ..
548 $ cd ..
516
549
517 Create clones using old repo formats to use in later tests
550 Create clones using old repo formats to use in later tests
518 $ hg clone --config format.usestore=False \
551 $ hg clone --config format.usestore=False \
519 > --config experimental.changegroup3=True \
552 > --config experimental.changegroup3=True \
520 > http://localhost:$HGPORT2 deeprepo-basicstore
553 > http://localhost:$HGPORT2 deeprepo-basicstore
521 requesting all changes
554 requesting all changes
522 adding changesets
555 adding changesets
523 adding manifests
556 adding manifests
524 adding file changes
557 adding file changes
525 added 3 changesets with 10 changes to 8 files
558 added 3 changesets with 10 changes to 8 files
526 updating to branch default
559 updating to branch default
527 8 files updated, 0 files merged, 0 files removed, 0 files unresolved
560 8 files updated, 0 files merged, 0 files removed, 0 files unresolved
528 $ cd deeprepo-basicstore
561 $ cd deeprepo-basicstore
529 $ grep store .hg/requires
562 $ grep store .hg/requires
530 [1]
563 [1]
531 $ hg serve -p $HGPORT3 -d --pid-file=hg.pid --errorlog=errors.log
564 $ hg serve -p $HGPORT3 -d --pid-file=hg.pid --errorlog=errors.log
532 $ cat hg.pid >> $DAEMON_PIDS
565 $ cat hg.pid >> $DAEMON_PIDS
533 $ cd ..
566 $ cd ..
534 $ hg clone --config format.usefncache=False \
567 $ hg clone --config format.usefncache=False \
535 > --config experimental.changegroup3=True \
568 > --config experimental.changegroup3=True \
536 > http://localhost:$HGPORT2 deeprepo-encodedstore
569 > http://localhost:$HGPORT2 deeprepo-encodedstore
537 requesting all changes
570 requesting all changes
538 adding changesets
571 adding changesets
539 adding manifests
572 adding manifests
540 adding file changes
573 adding file changes
541 added 3 changesets with 10 changes to 8 files
574 added 3 changesets with 10 changes to 8 files
542 updating to branch default
575 updating to branch default
543 8 files updated, 0 files merged, 0 files removed, 0 files unresolved
576 8 files updated, 0 files merged, 0 files removed, 0 files unresolved
544 $ cd deeprepo-encodedstore
577 $ cd deeprepo-encodedstore
545 $ grep fncache .hg/requires
578 $ grep fncache .hg/requires
546 [1]
579 [1]
547 $ hg serve -p $HGPORT4 -d --pid-file=hg.pid --errorlog=errors.log
580 $ hg serve -p $HGPORT4 -d --pid-file=hg.pid --errorlog=errors.log
548 $ cat hg.pid >> $DAEMON_PIDS
581 $ cat hg.pid >> $DAEMON_PIDS
549 $ cd ..
582 $ cd ..
550
583
551 Local clone with basicstore
584 Local clone with basicstore
552 $ hg clone -U deeprepo-basicstore local-clone-basicstore
585 $ hg clone -U deeprepo-basicstore local-clone-basicstore
553 $ hg -R local-clone-basicstore verify
586 $ hg -R local-clone-basicstore verify
554 checking changesets
587 checking changesets
555 checking manifests
588 checking manifests
556 crosschecking files in changesets and manifests
589 crosschecking files in changesets and manifests
557 checking files
590 checking files
558 8 files, 3 changesets, 10 total revisions
591 8 files, 3 changesets, 10 total revisions
559
592
560 Local clone with encodedstore
593 Local clone with encodedstore
561 $ hg clone -U deeprepo-encodedstore local-clone-encodedstore
594 $ hg clone -U deeprepo-encodedstore local-clone-encodedstore
562 $ hg -R local-clone-encodedstore verify
595 $ hg -R local-clone-encodedstore verify
563 checking changesets
596 checking changesets
564 checking manifests
597 checking manifests
565 crosschecking files in changesets and manifests
598 crosschecking files in changesets and manifests
566 checking files
599 checking files
567 8 files, 3 changesets, 10 total revisions
600 8 files, 3 changesets, 10 total revisions
568
601
569 Local clone with fncachestore
602 Local clone with fncachestore
570 $ hg clone -U deeprepo local-clone-fncachestore
603 $ hg clone -U deeprepo local-clone-fncachestore
571 $ hg -R local-clone-fncachestore verify
604 $ hg -R local-clone-fncachestore verify
572 checking changesets
605 checking changesets
573 checking manifests
606 checking manifests
574 crosschecking files in changesets and manifests
607 crosschecking files in changesets and manifests
575 checking files
608 checking files
576 8 files, 3 changesets, 10 total revisions
609 8 files, 3 changesets, 10 total revisions
577
610
578 Stream clone with basicstore
611 Stream clone with basicstore
579 $ hg clone --config experimental.changegroup3=True --uncompressed -U \
612 $ hg clone --config experimental.changegroup3=True --uncompressed -U \
580 > http://localhost:$HGPORT3 stream-clone-basicstore
613 > http://localhost:$HGPORT3 stream-clone-basicstore
581 streaming all changes
614 streaming all changes
582 18 files to transfer, * of data (glob)
615 18 files to transfer, * of data (glob)
583 transferred * in * seconds (*) (glob)
616 transferred * in * seconds (*) (glob)
584 searching for changes
617 searching for changes
585 no changes found
618 no changes found
586 $ hg -R stream-clone-basicstore verify
619 $ hg -R stream-clone-basicstore verify
587 checking changesets
620 checking changesets
588 checking manifests
621 checking manifests
589 crosschecking files in changesets and manifests
622 crosschecking files in changesets and manifests
590 checking files
623 checking files
591 8 files, 3 changesets, 10 total revisions
624 8 files, 3 changesets, 10 total revisions
592
625
593 Stream clone with encodedstore
626 Stream clone with encodedstore
594 $ hg clone --config experimental.changegroup3=True --uncompressed -U \
627 $ hg clone --config experimental.changegroup3=True --uncompressed -U \
595 > http://localhost:$HGPORT4 stream-clone-encodedstore
628 > http://localhost:$HGPORT4 stream-clone-encodedstore
596 streaming all changes
629 streaming all changes
597 18 files to transfer, * of data (glob)
630 18 files to transfer, * of data (glob)
598 transferred * in * seconds (*) (glob)
631 transferred * in * seconds (*) (glob)
599 searching for changes
632 searching for changes
600 no changes found
633 no changes found
601 $ hg -R stream-clone-encodedstore verify
634 $ hg -R stream-clone-encodedstore verify
602 checking changesets
635 checking changesets
603 checking manifests
636 checking manifests
604 crosschecking files in changesets and manifests
637 crosschecking files in changesets and manifests
605 checking files
638 checking files
606 8 files, 3 changesets, 10 total revisions
639 8 files, 3 changesets, 10 total revisions
607
640
608 Stream clone with fncachestore
641 Stream clone with fncachestore
609 $ hg clone --config experimental.changegroup3=True --uncompressed -U \
642 $ hg clone --config experimental.changegroup3=True --uncompressed -U \
610 > http://localhost:$HGPORT2 stream-clone-fncachestore
643 > http://localhost:$HGPORT2 stream-clone-fncachestore
611 streaming all changes
644 streaming all changes
612 18 files to transfer, * of data (glob)
645 18 files to transfer, * of data (glob)
613 transferred * in * seconds (*) (glob)
646 transferred * in * seconds (*) (glob)
614 searching for changes
647 searching for changes
615 no changes found
648 no changes found
616 $ hg -R stream-clone-fncachestore verify
649 $ hg -R stream-clone-fncachestore verify
617 checking changesets
650 checking changesets
618 checking manifests
651 checking manifests
619 crosschecking files in changesets and manifests
652 crosschecking files in changesets and manifests
620 checking files
653 checking files
621 8 files, 3 changesets, 10 total revisions
654 8 files, 3 changesets, 10 total revisions
622
655
623 Packed bundle
656 Packed bundle
624 $ hg -R deeprepo debugcreatestreamclonebundle repo-packed.hg
657 $ hg -R deeprepo debugcreatestreamclonebundle repo-packed.hg
625 writing 3349 bytes for 18 files
658 writing 3349 bytes for 18 files
626 bundle requirements: generaldelta, revlogv1, treemanifest
659 bundle requirements: generaldelta, revlogv1, treemanifest
627 $ hg debugbundle --spec repo-packed.hg
660 $ hg debugbundle --spec repo-packed.hg
628 none-packed1;requirements%3Dgeneraldelta%2Crevlogv1%2Ctreemanifest
661 none-packed1;requirements%3Dgeneraldelta%2Crevlogv1%2Ctreemanifest
General Comments 0
You need to be logged in to leave comments. Login now