##// END OF EJS Templates
verify: clarify misleading fncache message...
Matt Mackall -
r25627:9573d8f3 default
parent child Browse files
Show More
@@ -1,321 +1,321 b''
1 1 # verify.py - repository integrity checking for Mercurial
2 2 #
3 3 # Copyright 2006, 2007 Matt Mackall <mpm@selenic.com>
4 4 #
5 5 # This software may be used and distributed according to the terms of the
6 6 # GNU General Public License version 2 or any later version.
7 7
8 8 from node import nullid, short
9 9 from i18n import _
10 10 import os
11 11 import revlog, util, error
12 12
13 13 def verify(repo):
14 14 lock = repo.lock()
15 15 try:
16 16 return _verify(repo)
17 17 finally:
18 18 lock.release()
19 19
20 20 def _normpath(f):
21 21 # under hg < 2.4, convert didn't sanitize paths properly, so a
22 22 # converted repo may contain repeated slashes
23 23 while '//' in f:
24 24 f = f.replace('//', '/')
25 25 return f
26 26
27 27 def _verify(repo):
28 28 repo = repo.unfiltered()
29 29 mflinkrevs = {}
30 30 filelinkrevs = {}
31 31 filenodes = {}
32 32 revisions = 0
33 33 badrevs = set()
34 34 errors = [0]
35 35 warnings = [0]
36 36 ui = repo.ui
37 37 cl = repo.changelog
38 38 mf = repo.manifest
39 39 lrugetctx = util.lrucachefunc(repo.changectx)
40 40
41 41 if not repo.url().startswith('file:'):
42 42 raise util.Abort(_("cannot verify bundle or remote repos"))
43 43
44 44 def err(linkrev, msg, filename=None):
45 45 if linkrev is not None:
46 46 badrevs.add(linkrev)
47 47 else:
48 48 linkrev = '?'
49 49 msg = "%s: %s" % (linkrev, msg)
50 50 if filename:
51 51 msg = "%s@%s" % (filename, msg)
52 52 ui.warn(" " + msg + "\n")
53 53 errors[0] += 1
54 54
55 55 def exc(linkrev, msg, inst, filename=None):
56 56 if isinstance(inst, KeyboardInterrupt):
57 57 ui.warn(_("interrupted"))
58 58 raise
59 59 if not str(inst):
60 60 inst = repr(inst)
61 61 err(linkrev, "%s: %s" % (msg, inst), filename)
62 62
63 63 def warn(msg):
64 64 ui.warn(msg + "\n")
65 65 warnings[0] += 1
66 66
67 67 def checklog(obj, name, linkrev):
68 68 if not len(obj) and (havecl or havemf):
69 69 err(linkrev, _("empty or missing %s") % name)
70 70 return
71 71
72 72 d = obj.checksize()
73 73 if d[0]:
74 74 err(None, _("data length off by %d bytes") % d[0], name)
75 75 if d[1]:
76 76 err(None, _("index contains %d extra bytes") % d[1], name)
77 77
78 78 if obj.version != revlog.REVLOGV0:
79 79 if not revlogv1:
80 80 warn(_("warning: `%s' uses revlog format 1") % name)
81 81 elif revlogv1:
82 82 warn(_("warning: `%s' uses revlog format 0") % name)
83 83
84 84 def checkentry(obj, i, node, seen, linkrevs, f):
85 85 lr = obj.linkrev(obj.rev(node))
86 86 if lr < 0 or (havecl and lr not in linkrevs):
87 87 if lr < 0 or lr >= len(cl):
88 88 msg = _("rev %d points to nonexistent changeset %d")
89 89 else:
90 90 msg = _("rev %d points to unexpected changeset %d")
91 91 err(None, msg % (i, lr), f)
92 92 if linkrevs:
93 93 if f and len(linkrevs) > 1:
94 94 try:
95 95 # attempt to filter down to real linkrevs
96 96 linkrevs = [l for l in linkrevs
97 97 if lrugetctx(l)[f].filenode() == node]
98 98 except Exception:
99 99 pass
100 100 warn(_(" (expected %s)") % " ".join(map(str, linkrevs)))
101 101 lr = None # can't be trusted
102 102
103 103 try:
104 104 p1, p2 = obj.parents(node)
105 105 if p1 not in seen and p1 != nullid:
106 106 err(lr, _("unknown parent 1 %s of %s") %
107 107 (short(p1), short(node)), f)
108 108 if p2 not in seen and p2 != nullid:
109 109 err(lr, _("unknown parent 2 %s of %s") %
110 110 (short(p2), short(node)), f)
111 111 except Exception, inst:
112 112 exc(lr, _("checking parents of %s") % short(node), inst, f)
113 113
114 114 if node in seen:
115 115 err(lr, _("duplicate revision %d (%d)") % (i, seen[node]), f)
116 116 seen[node] = i
117 117 return lr
118 118
119 119 if os.path.exists(repo.sjoin("journal")):
120 120 ui.warn(_("abandoned transaction found - run hg recover\n"))
121 121
122 122 revlogv1 = cl.version != revlog.REVLOGV0
123 123 if ui.verbose or not revlogv1:
124 124 ui.status(_("repository uses revlog format %d\n") %
125 125 (revlogv1 and 1 or 0))
126 126
127 127 havecl = len(cl) > 0
128 128 havemf = len(mf) > 0
129 129
130 130 ui.status(_("checking changesets\n"))
131 131 refersmf = False
132 132 seen = {}
133 133 checklog(cl, "changelog", 0)
134 134 total = len(repo)
135 135 for i in repo:
136 136 ui.progress(_('checking'), i, total=total, unit=_('changesets'))
137 137 n = cl.node(i)
138 138 checkentry(cl, i, n, seen, [i], "changelog")
139 139
140 140 try:
141 141 changes = cl.read(n)
142 142 if changes[0] != nullid:
143 143 mflinkrevs.setdefault(changes[0], []).append(i)
144 144 refersmf = True
145 145 for f in changes[3]:
146 146 filelinkrevs.setdefault(_normpath(f), []).append(i)
147 147 except Exception, inst:
148 148 refersmf = True
149 149 exc(i, _("unpacking changeset %s") % short(n), inst)
150 150 ui.progress(_('checking'), None)
151 151
152 152 ui.status(_("checking manifests\n"))
153 153 seen = {}
154 154 if refersmf:
155 155 # Do not check manifest if there are only changelog entries with
156 156 # null manifests.
157 157 checklog(mf, "manifest", 0)
158 158 total = len(mf)
159 159 for i in mf:
160 160 ui.progress(_('checking'), i, total=total, unit=_('manifests'))
161 161 n = mf.node(i)
162 162 lr = checkentry(mf, i, n, seen, mflinkrevs.get(n, []), "manifest")
163 163 if n in mflinkrevs:
164 164 del mflinkrevs[n]
165 165 else:
166 166 err(lr, _("%s not in changesets") % short(n), "manifest")
167 167
168 168 try:
169 169 for f, fn in mf.readdelta(n).iteritems():
170 170 if not f:
171 171 err(lr, _("file without name in manifest"))
172 172 elif f != "/dev/null": # ignore this in very old repos
173 173 filenodes.setdefault(_normpath(f), {}).setdefault(fn, lr)
174 174 except Exception, inst:
175 175 exc(lr, _("reading manifest delta %s") % short(n), inst)
176 176 ui.progress(_('checking'), None)
177 177
178 178 ui.status(_("crosschecking files in changesets and manifests\n"))
179 179
180 180 total = len(mflinkrevs) + len(filelinkrevs) + len(filenodes)
181 181 count = 0
182 182 if havemf:
183 183 for c, m in sorted([(c, m) for m in mflinkrevs
184 184 for c in mflinkrevs[m]]):
185 185 count += 1
186 186 if m == nullid:
187 187 continue
188 188 ui.progress(_('crosschecking'), count, total=total)
189 189 err(c, _("changeset refers to unknown manifest %s") % short(m))
190 190 mflinkrevs = None # del is bad here due to scope issues
191 191
192 192 for f in sorted(filelinkrevs):
193 193 count += 1
194 194 ui.progress(_('crosschecking'), count, total=total)
195 195 if f not in filenodes:
196 196 lr = filelinkrevs[f][0]
197 197 err(lr, _("in changeset but not in manifest"), f)
198 198
199 199 if havecl:
200 200 for f in sorted(filenodes):
201 201 count += 1
202 202 ui.progress(_('crosschecking'), count, total=total)
203 203 if f not in filelinkrevs:
204 204 try:
205 205 fl = repo.file(f)
206 206 lr = min([fl.linkrev(fl.rev(n)) for n in filenodes[f]])
207 207 except Exception:
208 208 lr = None
209 209 err(lr, _("in manifest but not in changeset"), f)
210 210
211 211 ui.progress(_('crosschecking'), None)
212 212
213 213 ui.status(_("checking files\n"))
214 214
215 215 storefiles = set()
216 216 for f, f2, size in repo.store.datafiles():
217 217 if not f:
218 218 err(None, _("cannot decode filename '%s'") % f2)
219 219 elif size > 0 or not revlogv1:
220 220 storefiles.add(_normpath(f))
221 221
222 222 files = sorted(set(filenodes) | set(filelinkrevs))
223 223 total = len(files)
224 224 for i, f in enumerate(files):
225 225 ui.progress(_('checking'), i, item=f, total=total)
226 226 try:
227 227 linkrevs = filelinkrevs[f]
228 228 except KeyError:
229 229 # in manifest but not in changelog
230 230 linkrevs = []
231 231
232 232 if linkrevs:
233 233 lr = linkrevs[0]
234 234 else:
235 235 lr = None
236 236
237 237 try:
238 238 fl = repo.file(f)
239 239 except error.RevlogError, e:
240 240 err(lr, _("broken revlog! (%s)") % e, f)
241 241 continue
242 242
243 243 for ff in fl.files():
244 244 try:
245 245 storefiles.remove(ff)
246 246 except KeyError:
247 err(lr, _("missing revlog!"), ff)
247 warn(_(" warning: revlog '%s' not in fncache!") % ff)
248 248
249 249 checklog(fl, f, lr)
250 250 seen = {}
251 251 rp = None
252 252 for i in fl:
253 253 revisions += 1
254 254 n = fl.node(i)
255 255 lr = checkentry(fl, i, n, seen, linkrevs, f)
256 256 if f in filenodes:
257 257 if havemf and n not in filenodes[f]:
258 258 err(lr, _("%s not in manifests") % (short(n)), f)
259 259 else:
260 260 del filenodes[f][n]
261 261
262 262 # verify contents
263 263 try:
264 264 l = len(fl.read(n))
265 265 rp = fl.renamed(n)
266 266 if l != fl.size(i):
267 267 if len(fl.revision(n)) != fl.size(i):
268 268 err(lr, _("unpacked size is %s, %s expected") %
269 269 (l, fl.size(i)), f)
270 270 except error.CensoredNodeError:
271 271 if ui.config("censor", "policy", "abort") == "abort":
272 272 err(lr, _("censored file data"), f)
273 273 except Exception, inst:
274 274 exc(lr, _("unpacking %s") % short(n), inst, f)
275 275
276 276 # check renames
277 277 try:
278 278 if rp:
279 279 if lr is not None and ui.verbose:
280 280 ctx = lrugetctx(lr)
281 281 found = False
282 282 for pctx in ctx.parents():
283 283 if rp[0] in pctx:
284 284 found = True
285 285 break
286 286 if not found:
287 287 warn(_("warning: copy source of '%s' not"
288 288 " in parents of %s") % (f, ctx))
289 289 fl2 = repo.file(rp[0])
290 290 if not len(fl2):
291 291 err(lr, _("empty or missing copy source revlog %s:%s")
292 292 % (rp[0], short(rp[1])), f)
293 293 elif rp[1] == nullid:
294 294 ui.note(_("warning: %s@%s: copy source"
295 295 " revision is nullid %s:%s\n")
296 296 % (f, lr, rp[0], short(rp[1])))
297 297 else:
298 298 fl2.rev(rp[1])
299 299 except Exception, inst:
300 300 exc(lr, _("checking rename of %s") % short(n), inst, f)
301 301
302 302 # cross-check
303 303 if f in filenodes:
304 304 fns = [(lr, n) for n, lr in filenodes[f].iteritems()]
305 305 for lr, node in sorted(fns):
306 306 err(lr, _("%s in manifests not found") % short(node), f)
307 307 ui.progress(_('checking'), None)
308 308
309 309 for f in storefiles:
310 310 warn(_("warning: orphan revlog '%s'") % f)
311 311
312 312 ui.status(_("%d files, %d changesets, %d total revisions\n") %
313 313 (len(files), len(cl), revisions))
314 314 if warnings[0]:
315 315 ui.warn(_("%d warnings encountered!\n") % warnings[0])
316 316 if errors[0]:
317 317 ui.warn(_("%d integrity errors encountered!\n") % errors[0])
318 318 if badrevs:
319 319 ui.warn(_("(first damaged changeset appears to be %d)\n")
320 320 % min(badrevs))
321 321 return 1
@@ -1,287 +1,285 b''
1 1 Init repo1:
2 2
3 3 $ hg init repo1
4 4 $ cd repo1
5 5 $ echo "some text" > a
6 6 $ hg add
7 7 adding a
8 8 $ hg ci -m first
9 9 $ cat .hg/store/fncache | sort
10 10 data/a.i
11 11
12 12 Testing a.i/b:
13 13
14 14 $ mkdir a.i
15 15 $ echo "some other text" > a.i/b
16 16 $ hg add
17 17 adding a.i/b (glob)
18 18 $ hg ci -m second
19 19 $ cat .hg/store/fncache | sort
20 20 data/a.i
21 21 data/a.i.hg/b.i
22 22
23 23 Testing a.i.hg/c:
24 24
25 25 $ mkdir a.i.hg
26 26 $ echo "yet another text" > a.i.hg/c
27 27 $ hg add
28 28 adding a.i.hg/c (glob)
29 29 $ hg ci -m third
30 30 $ cat .hg/store/fncache | sort
31 31 data/a.i
32 32 data/a.i.hg.hg/c.i
33 33 data/a.i.hg/b.i
34 34
35 35 Testing verify:
36 36
37 37 $ hg verify
38 38 checking changesets
39 39 checking manifests
40 40 crosschecking files in changesets and manifests
41 41 checking files
42 42 3 files, 3 changesets, 3 total revisions
43 43
44 44 $ rm .hg/store/fncache
45 45
46 46 $ hg verify
47 47 checking changesets
48 48 checking manifests
49 49 crosschecking files in changesets and manifests
50 50 checking files
51 data/a.i@0: missing revlog!
52 data/a.i.hg/c.i@2: missing revlog!
53 data/a.i/b.i@1: missing revlog!
51 warning: revlog 'data/a.i' not in fncache!
52 warning: revlog 'data/a.i.hg/c.i' not in fncache!
53 warning: revlog 'data/a.i/b.i' not in fncache!
54 54 3 files, 3 changesets, 3 total revisions
55 3 integrity errors encountered!
56 (first damaged changeset appears to be 0)
57 [1]
55 3 warnings encountered!
58 56 $ cd ..
59 57
60 58 Non store repo:
61 59
62 60 $ hg --config format.usestore=False init foo
63 61 $ cd foo
64 62 $ mkdir tst.d
65 63 $ echo foo > tst.d/foo
66 64 $ hg ci -Amfoo
67 65 adding tst.d/foo
68 66 $ find .hg | sort
69 67 .hg
70 68 .hg/00changelog.i
71 69 .hg/00manifest.i
72 70 .hg/cache
73 71 .hg/cache/branch2-served
74 72 .hg/cache/rbc-names-v1
75 73 .hg/cache/rbc-revs-v1
76 74 .hg/data
77 75 .hg/data/tst.d.hg
78 76 .hg/data/tst.d.hg/foo.i
79 77 .hg/dirstate
80 78 .hg/last-message.txt
81 79 .hg/phaseroots
82 80 .hg/requires
83 81 .hg/undo
84 82 .hg/undo.backupfiles
85 83 .hg/undo.bookmarks
86 84 .hg/undo.branch
87 85 .hg/undo.desc
88 86 .hg/undo.dirstate
89 87 .hg/undo.phaseroots
90 88 $ cd ..
91 89
92 90 Non fncache repo:
93 91
94 92 $ hg --config format.usefncache=False init bar
95 93 $ cd bar
96 94 $ mkdir tst.d
97 95 $ echo foo > tst.d/Foo
98 96 $ hg ci -Amfoo
99 97 adding tst.d/Foo
100 98 $ find .hg | sort
101 99 .hg
102 100 .hg/00changelog.i
103 101 .hg/cache
104 102 .hg/cache/branch2-served
105 103 .hg/cache/rbc-names-v1
106 104 .hg/cache/rbc-revs-v1
107 105 .hg/dirstate
108 106 .hg/last-message.txt
109 107 .hg/requires
110 108 .hg/store
111 109 .hg/store/00changelog.i
112 110 .hg/store/00manifest.i
113 111 .hg/store/data
114 112 .hg/store/data/tst.d.hg
115 113 .hg/store/data/tst.d.hg/_foo.i
116 114 .hg/store/phaseroots
117 115 .hg/store/undo
118 116 .hg/store/undo.backupfiles
119 117 .hg/store/undo.phaseroots
120 118 .hg/undo.bookmarks
121 119 .hg/undo.branch
122 120 .hg/undo.desc
123 121 .hg/undo.dirstate
124 122 $ cd ..
125 123
126 124 Encoding of reserved / long paths in the store
127 125
128 126 $ hg init r2
129 127 $ cd r2
130 128 $ cat <<EOF > .hg/hgrc
131 129 > [ui]
132 130 > portablefilenames = ignore
133 131 > EOF
134 132
135 133 $ hg import -q --bypass - <<EOF
136 134 > # HG changeset patch
137 135 > # User test
138 136 > # Date 0 0
139 137 > # Node ID 1c7a2f7cb77be1a0def34e4c7cabc562ad98fbd7
140 138 > # Parent 0000000000000000000000000000000000000000
141 139 > 1
142 140 >
143 141 > diff --git a/12345678/12345678/12345678/12345678/12345678/12345678/12345678/12345/xxxxxxxxx-xxxxxxxxx-xxxxxxxxx-123456789-12.3456789-12345-ABCDEFGHIJKLMNOPRSTUVWXYZ-abcdefghjiklmnopqrstuvwxyz b/12345678/12345678/12345678/12345678/12345678/12345678/12345678/12345/xxxxxxxxx-xxxxxxxxx-xxxxxxxxx-123456789-12.3456789-12345-ABCDEFGHIJKLMNOPRSTUVWXYZ-abcdefghjiklmnopqrstuvwxyz
144 142 > new file mode 100644
145 143 > --- /dev/null
146 144 > +++ b/12345678/12345678/12345678/12345678/12345678/12345678/12345678/12345/xxxxxxxxx-xxxxxxxxx-xxxxxxxxx-123456789-12.3456789-12345-ABCDEFGHIJKLMNOPRSTUVWXYZ-abcdefghjiklmnopqrstuvwxyz
147 145 > @@ -0,0 +1,1 @@
148 146 > +foo
149 147 > diff --git a/AUX/SECOND/X.PRN/FOURTH/FI:FTH/SIXTH/SEVENTH/EIGHTH/NINETH/TENTH/ELEVENTH/LOREMIPSUM.TXT b/AUX/SECOND/X.PRN/FOURTH/FI:FTH/SIXTH/SEVENTH/EIGHTH/NINETH/TENTH/ELEVENTH/LOREMIPSUM.TXT
150 148 > new file mode 100644
151 149 > --- /dev/null
152 150 > +++ b/AUX/SECOND/X.PRN/FOURTH/FI:FTH/SIXTH/SEVENTH/EIGHTH/NINETH/TENTH/ELEVENTH/LOREMIPSUM.TXT
153 151 > @@ -0,0 +1,1 @@
154 152 > +foo
155 153 > diff --git a/Project Planning/Resources/AnotherLongDirectoryName/Followedbyanother/AndAnother/AndThenAnExtremelyLongFileName.txt b/Project Planning/Resources/AnotherLongDirectoryName/Followedbyanother/AndAnother/AndThenAnExtremelyLongFileName.txt
156 154 > new file mode 100644
157 155 > --- /dev/null
158 156 > +++ b/Project Planning/Resources/AnotherLongDirectoryName/Followedbyanother/AndAnother/AndThenAnExtremelyLongFileName.txt
159 157 > @@ -0,0 +1,1 @@
160 158 > +foo
161 159 > diff --git a/bla.aux/prn/PRN/lpt/com3/nul/coma/foo.NUL/normal.c b/bla.aux/prn/PRN/lpt/com3/nul/coma/foo.NUL/normal.c
162 160 > new file mode 100644
163 161 > --- /dev/null
164 162 > +++ b/bla.aux/prn/PRN/lpt/com3/nul/coma/foo.NUL/normal.c
165 163 > @@ -0,0 +1,1 @@
166 164 > +foo
167 165 > diff --git a/enterprise/openesbaddons/contrib-imola/corba-bc/netbeansplugin/wsdlExtension/src/main/java/META-INF/services/org.netbeans.modules.xml.wsdl.bindingsupport.spi.ExtensibilityElementTemplateProvider b/enterprise/openesbaddons/contrib-imola/corba-bc/netbeansplugin/wsdlExtension/src/main/java/META-INF/services/org.netbeans.modules.xml.wsdl.bindingsupport.spi.ExtensibilityElementTemplateProvider
168 166 > new file mode 100644
169 167 > --- /dev/null
170 168 > +++ b/enterprise/openesbaddons/contrib-imola/corba-bc/netbeansplugin/wsdlExtension/src/main/java/META-INF/services/org.netbeans.modules.xml.wsdl.bindingsupport.spi.ExtensibilityElementTemplateProvider
171 169 > @@ -0,0 +1,1 @@
172 170 > +foo
173 171 > EOF
174 172
175 173 $ find .hg/store -name *.i | sort
176 174 .hg/store/00changelog.i
177 175 .hg/store/00manifest.i
178 176 .hg/store/data/bla.aux/pr~6e/_p_r_n/lpt/co~6d3/nu~6c/coma/foo._n_u_l/normal.c.i
179 177 .hg/store/dh/12345678/12345678/12345678/12345678/12345678/12345678/12345678/12345/xxxxxx168e07b38e65eff86ab579afaaa8e30bfbe0f35f.i
180 178 .hg/store/dh/au~78/second/x.prn/fourth/fi~3afth/sixth/seventh/eighth/nineth/tenth/loremia20419e358ddff1bf8751e38288aff1d7c32ec05.i
181 179 .hg/store/dh/enterpri/openesba/contrib-/corba-bc/netbeans/wsdlexte/src/main/java/org.net7018f27961fdf338a598a40c4683429e7ffb9743.i
182 180 .hg/store/dh/project_/resource/anotherl/followed/andanoth/andthenanextremelylongfilename0d8e1f4187c650e2f1fdca9fd90f786bc0976b6b.i
183 181
184 182 $ cd ..
185 183
186 184 Aborting lock does not prevent fncache writes
187 185
188 186 $ cat > exceptionext.py <<EOF
189 187 > import os
190 188 > from mercurial import commands, util
191 189 > from mercurial.extensions import wrapfunction
192 190 >
193 191 > def lockexception(orig, vfs, lockname, wait, releasefn, acquirefn, desc):
194 192 > def releasewrap():
195 193 > raise util.Abort("forced lock failure")
196 194 > return orig(vfs, lockname, wait, releasewrap, acquirefn, desc)
197 195 >
198 196 > def reposetup(ui, repo):
199 197 > wrapfunction(repo, '_lock', lockexception)
200 198 >
201 199 > cmdtable = {}
202 200 >
203 201 > EOF
204 202 $ extpath=`pwd`/exceptionext.py
205 203 $ hg init fncachetxn
206 204 $ cd fncachetxn
207 205 $ printf "[extensions]\nexceptionext=$extpath\n" >> .hg/hgrc
208 206 $ touch y
209 207 $ hg ci -qAm y
210 208 abort: forced lock failure
211 209 [255]
212 210 $ cat .hg/store/fncache
213 211 data/y.i
214 212
215 213 Aborting transaction prevents fncache change
216 214
217 215 $ cat > ../exceptionext.py <<EOF
218 216 > import os
219 217 > from mercurial import commands, util, localrepo
220 218 > from mercurial.extensions import wrapfunction
221 219 >
222 220 > def wrapper(orig, self, *args, **kwargs):
223 221 > tr = orig(self, *args, **kwargs)
224 222 > def fail(tr):
225 223 > raise util.Abort("forced transaction failure")
226 224 > # zzz prefix to ensure it sorted after store.write
227 225 > tr.addfinalize('zzz-forcefails', fail)
228 226 > return tr
229 227 >
230 228 > def uisetup(ui):
231 229 > wrapfunction(localrepo.localrepository, 'transaction', wrapper)
232 230 >
233 231 > cmdtable = {}
234 232 >
235 233 > EOF
236 234 $ rm -f "${extpath}c"
237 235 $ touch z
238 236 $ hg ci -qAm z
239 237 transaction abort!
240 238 rollback completed
241 239 abort: forced transaction failure
242 240 [255]
243 241 $ cat .hg/store/fncache
244 242 data/y.i
245 243
246 244 Aborted transactions can be recovered later
247 245
248 246 $ cat > ../exceptionext.py <<EOF
249 247 > import os
250 248 > from mercurial import commands, util, transaction, localrepo
251 249 > from mercurial.extensions import wrapfunction
252 250 >
253 251 > def trwrapper(orig, self, *args, **kwargs):
254 252 > tr = orig(self, *args, **kwargs)
255 253 > def fail(tr):
256 254 > raise util.Abort("forced transaction failure")
257 255 > # zzz prefix to ensure it sorted after store.write
258 256 > tr.addfinalize('zzz-forcefails', fail)
259 257 > return tr
260 258 >
261 259 > def abortwrapper(orig, self, *args, **kwargs):
262 260 > raise util.Abort("forced transaction failure")
263 261 >
264 262 > def uisetup(ui):
265 263 > wrapfunction(localrepo.localrepository, 'transaction', trwrapper)
266 264 > wrapfunction(transaction.transaction, '_abort', abortwrapper)
267 265 >
268 266 > cmdtable = {}
269 267 >
270 268 > EOF
271 269 $ rm -f "${extpath}c"
272 270 $ hg up -q 1
273 271 $ touch z
274 272 $ hg ci -qAm z 2>/dev/null
275 273 [255]
276 274 $ cat .hg/store/fncache | sort
277 275 data/y.i
278 276 data/z.i
279 277 $ hg recover
280 278 rolling back interrupted transaction
281 279 checking changesets
282 280 checking manifests
283 281 crosschecking files in changesets and manifests
284 282 checking files
285 283 1 files, 1 changesets, 1 total revisions
286 284 $ cat .hg/store/fncache
287 285 data/y.i
@@ -1,115 +1,116 b''
1 1 prepare repo
2 2
3 3 $ hg init a
4 4 $ cd a
5 5 $ echo "some text" > FOO.txt
6 6 $ echo "another text" > bar.txt
7 7 $ echo "more text" > QUICK.txt
8 8 $ hg add
9 9 adding FOO.txt
10 10 adding QUICK.txt
11 11 adding bar.txt
12 12 $ hg ci -mtest1
13 13
14 14 verify
15 15
16 16 $ hg verify
17 17 checking changesets
18 18 checking manifests
19 19 crosschecking files in changesets and manifests
20 20 checking files
21 21 3 files, 1 changesets, 3 total revisions
22 22
23 23 verify with journal
24 24
25 25 $ touch .hg/store/journal
26 26 $ hg verify
27 27 abandoned transaction found - run hg recover
28 28 checking changesets
29 29 checking manifests
30 30 crosschecking files in changesets and manifests
31 31 checking files
32 32 3 files, 1 changesets, 3 total revisions
33 33 $ rm .hg/store/journal
34 34
35 35 introduce some bugs in repo
36 36
37 37 $ cd .hg/store/data
38 38 $ mv _f_o_o.txt.i X_f_o_o.txt.i
39 39 $ mv bar.txt.i xbar.txt.i
40 40 $ rm _q_u_i_c_k.txt.i
41 41
42 42 $ hg verify
43 43 checking changesets
44 44 checking manifests
45 45 crosschecking files in changesets and manifests
46 46 checking files
47 data/FOO.txt.i@0: missing revlog!
47 warning: revlog 'data/FOO.txt.i' not in fncache!
48 48 0: empty or missing FOO.txt
49 49 FOO.txt@0: f62022d3d590 in manifests not found
50 data/QUICK.txt.i@0: missing revlog!
50 warning: revlog 'data/QUICK.txt.i' not in fncache!
51 51 0: empty or missing QUICK.txt
52 52 QUICK.txt@0: 88b857db8eba in manifests not found
53 data/bar.txt.i@0: missing revlog!
53 warning: revlog 'data/bar.txt.i' not in fncache!
54 54 0: empty or missing bar.txt
55 55 bar.txt@0: 256559129457 in manifests not found
56 56 3 files, 1 changesets, 0 total revisions
57 9 integrity errors encountered!
57 3 warnings encountered!
58 6 integrity errors encountered!
58 59 (first damaged changeset appears to be 0)
59 60 [1]
60 61
61 62 $ cd ../../..
62 63 $ cd ..
63 64
64 65 test changelog without a manifest
65 66
66 67 $ hg init b
67 68 $ cd b
68 69 $ hg branch foo
69 70 marked working directory as branch foo
70 71 (branches are permanent and global, did you want a bookmark?)
71 72 $ hg ci -m branchfoo
72 73 $ hg verify
73 74 checking changesets
74 75 checking manifests
75 76 crosschecking files in changesets and manifests
76 77 checking files
77 78 0 files, 1 changesets, 0 total revisions
78 79
79 80 test revlog corruption
80 81
81 82 $ touch a
82 83 $ hg add a
83 84 $ hg ci -m a
84 85
85 86 $ echo 'corrupted' > b
86 87 $ dd if=.hg/store/data/a.i of=start bs=1 count=20 2>/dev/null
87 88 $ cat start b > .hg/store/data/a.i
88 89
89 90 $ hg verify
90 91 checking changesets
91 92 checking manifests
92 93 crosschecking files in changesets and manifests
93 94 checking files
94 95 a@1: broken revlog! (index data/a.i is corrupted)
95 96 warning: orphan revlog 'data/a.i'
96 97 1 files, 2 changesets, 0 total revisions
97 98 1 warnings encountered!
98 99 1 integrity errors encountered!
99 100 (first damaged changeset appears to be 1)
100 101 [1]
101 102
102 103 $ cd ..
103 104
104 105 test revlog format 0
105 106
106 107 $ revlog-formatv0.py
107 108 $ cd formatv0
108 109 $ hg verify
109 110 repository uses revlog format 0
110 111 checking changesets
111 112 checking manifests
112 113 crosschecking files in changesets and manifests
113 114 checking files
114 115 1 files, 1 changesets, 1 total revisions
115 116 $ cd ..
General Comments 0
You need to be logged in to leave comments. Login now