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