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