Show More
@@ -1,321 +1,326 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 | fncachewarned = False | |||
222 | files = sorted(set(filenodes) | set(filelinkrevs)) |
|
223 | files = sorted(set(filenodes) | set(filelinkrevs)) | |
223 | total = len(files) |
|
224 | total = len(files) | |
224 | for i, f in enumerate(files): |
|
225 | for i, f in enumerate(files): | |
225 | ui.progress(_('checking'), i, item=f, total=total) |
|
226 | ui.progress(_('checking'), i, item=f, total=total) | |
226 | try: |
|
227 | try: | |
227 | linkrevs = filelinkrevs[f] |
|
228 | linkrevs = filelinkrevs[f] | |
228 | except KeyError: |
|
229 | except KeyError: | |
229 | # in manifest but not in changelog |
|
230 | # in manifest but not in changelog | |
230 | linkrevs = [] |
|
231 | linkrevs = [] | |
231 |
|
232 | |||
232 | if linkrevs: |
|
233 | if linkrevs: | |
233 | lr = linkrevs[0] |
|
234 | lr = linkrevs[0] | |
234 | else: |
|
235 | else: | |
235 | lr = None |
|
236 | lr = None | |
236 |
|
237 | |||
237 | try: |
|
238 | try: | |
238 | fl = repo.file(f) |
|
239 | fl = repo.file(f) | |
239 | except error.RevlogError, e: |
|
240 | except error.RevlogError, e: | |
240 | err(lr, _("broken revlog! (%s)") % e, f) |
|
241 | err(lr, _("broken revlog! (%s)") % e, f) | |
241 | continue |
|
242 | continue | |
242 |
|
243 | |||
243 | for ff in fl.files(): |
|
244 | for ff in fl.files(): | |
244 | try: |
|
245 | try: | |
245 | storefiles.remove(ff) |
|
246 | storefiles.remove(ff) | |
246 | except KeyError: |
|
247 | except KeyError: | |
247 | warn(_(" warning: revlog '%s' not in fncache!") % ff) |
|
248 | warn(_(" warning: revlog '%s' not in fncache!") % ff) | |
|
249 | fncachewarned = True | |||
248 |
|
250 | |||
249 | checklog(fl, f, lr) |
|
251 | checklog(fl, f, lr) | |
250 | seen = {} |
|
252 | seen = {} | |
251 | rp = None |
|
253 | rp = None | |
252 | for i in fl: |
|
254 | for i in fl: | |
253 | revisions += 1 |
|
255 | revisions += 1 | |
254 | n = fl.node(i) |
|
256 | n = fl.node(i) | |
255 | lr = checkentry(fl, i, n, seen, linkrevs, f) |
|
257 | lr = checkentry(fl, i, n, seen, linkrevs, f) | |
256 | if f in filenodes: |
|
258 | if f in filenodes: | |
257 | if havemf and n not in filenodes[f]: |
|
259 | if havemf and n not in filenodes[f]: | |
258 | err(lr, _("%s not in manifests") % (short(n)), f) |
|
260 | err(lr, _("%s not in manifests") % (short(n)), f) | |
259 | else: |
|
261 | else: | |
260 | del filenodes[f][n] |
|
262 | del filenodes[f][n] | |
261 |
|
263 | |||
262 | # verify contents |
|
264 | # verify contents | |
263 | try: |
|
265 | try: | |
264 | l = len(fl.read(n)) |
|
266 | l = len(fl.read(n)) | |
265 | rp = fl.renamed(n) |
|
267 | rp = fl.renamed(n) | |
266 | if l != fl.size(i): |
|
268 | if l != fl.size(i): | |
267 | if len(fl.revision(n)) != fl.size(i): |
|
269 | if len(fl.revision(n)) != fl.size(i): | |
268 | err(lr, _("unpacked size is %s, %s expected") % |
|
270 | err(lr, _("unpacked size is %s, %s expected") % | |
269 | (l, fl.size(i)), f) |
|
271 | (l, fl.size(i)), f) | |
270 | except error.CensoredNodeError: |
|
272 | except error.CensoredNodeError: | |
271 | if ui.config("censor", "policy", "abort") == "abort": |
|
273 | if ui.config("censor", "policy", "abort") == "abort": | |
272 | err(lr, _("censored file data"), f) |
|
274 | err(lr, _("censored file data"), f) | |
273 | except Exception, inst: |
|
275 | except Exception, inst: | |
274 | exc(lr, _("unpacking %s") % short(n), inst, f) |
|
276 | exc(lr, _("unpacking %s") % short(n), inst, f) | |
275 |
|
277 | |||
276 | # check renames |
|
278 | # check renames | |
277 | try: |
|
279 | try: | |
278 | if rp: |
|
280 | if rp: | |
279 | if lr is not None and ui.verbose: |
|
281 | if lr is not None and ui.verbose: | |
280 | ctx = lrugetctx(lr) |
|
282 | ctx = lrugetctx(lr) | |
281 | found = False |
|
283 | found = False | |
282 | for pctx in ctx.parents(): |
|
284 | for pctx in ctx.parents(): | |
283 | if rp[0] in pctx: |
|
285 | if rp[0] in pctx: | |
284 | found = True |
|
286 | found = True | |
285 | break |
|
287 | break | |
286 | if not found: |
|
288 | if not found: | |
287 | warn(_("warning: copy source of '%s' not" |
|
289 | warn(_("warning: copy source of '%s' not" | |
288 | " in parents of %s") % (f, ctx)) |
|
290 | " in parents of %s") % (f, ctx)) | |
289 | fl2 = repo.file(rp[0]) |
|
291 | fl2 = repo.file(rp[0]) | |
290 | if not len(fl2): |
|
292 | if not len(fl2): | |
291 | err(lr, _("empty or missing copy source revlog %s:%s") |
|
293 | err(lr, _("empty or missing copy source revlog %s:%s") | |
292 | % (rp[0], short(rp[1])), f) |
|
294 | % (rp[0], short(rp[1])), f) | |
293 | elif rp[1] == nullid: |
|
295 | elif rp[1] == nullid: | |
294 | ui.note(_("warning: %s@%s: copy source" |
|
296 | ui.note(_("warning: %s@%s: copy source" | |
295 | " revision is nullid %s:%s\n") |
|
297 | " revision is nullid %s:%s\n") | |
296 | % (f, lr, rp[0], short(rp[1]))) |
|
298 | % (f, lr, rp[0], short(rp[1]))) | |
297 | else: |
|
299 | else: | |
298 | fl2.rev(rp[1]) |
|
300 | fl2.rev(rp[1]) | |
299 | except Exception, inst: |
|
301 | except Exception, inst: | |
300 | exc(lr, _("checking rename of %s") % short(n), inst, f) |
|
302 | exc(lr, _("checking rename of %s") % short(n), inst, f) | |
301 |
|
303 | |||
302 | # cross-check |
|
304 | # cross-check | |
303 | if f in filenodes: |
|
305 | if f in filenodes: | |
304 | fns = [(lr, n) for n, lr in filenodes[f].iteritems()] |
|
306 | fns = [(lr, n) for n, lr in filenodes[f].iteritems()] | |
305 | for lr, node in sorted(fns): |
|
307 | for lr, node in sorted(fns): | |
306 | err(lr, _("%s in manifests not found") % short(node), f) |
|
308 | err(lr, _("%s in manifests not found") % short(node), f) | |
307 | ui.progress(_('checking'), None) |
|
309 | ui.progress(_('checking'), None) | |
308 |
|
310 | |||
309 | for f in storefiles: |
|
311 | for f in storefiles: | |
310 | warn(_("warning: orphan revlog '%s'") % f) |
|
312 | warn(_("warning: orphan revlog '%s'") % f) | |
311 |
|
313 | |||
312 | ui.status(_("%d files, %d changesets, %d total revisions\n") % |
|
314 | ui.status(_("%d files, %d changesets, %d total revisions\n") % | |
313 | (len(files), len(cl), revisions)) |
|
315 | (len(files), len(cl), revisions)) | |
314 | if warnings[0]: |
|
316 | if warnings[0]: | |
315 | ui.warn(_("%d warnings encountered!\n") % warnings[0]) |
|
317 | ui.warn(_("%d warnings encountered!\n") % warnings[0]) | |
|
318 | if fncachewarned: | |||
|
319 | ui.warn(_('hint: run "hg debugrebuildfncache" to recover from ' | |||
|
320 | 'corrupt fncache\n')) | |||
316 | if errors[0]: |
|
321 | if errors[0]: | |
317 | ui.warn(_("%d integrity errors encountered!\n") % errors[0]) |
|
322 | ui.warn(_("%d integrity errors encountered!\n") % errors[0]) | |
318 | if badrevs: |
|
323 | if badrevs: | |
319 | ui.warn(_("(first damaged changeset appears to be %d)\n") |
|
324 | ui.warn(_("(first damaged changeset appears to be %d)\n") | |
320 | % min(badrevs)) |
|
325 | % min(badrevs)) | |
321 | return 1 |
|
326 | return 1 |
@@ -1,380 +1,397 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 | warning: revlog 'data/a.i' not in fncache! |
|
51 | warning: revlog 'data/a.i' not in fncache! | |
52 | warning: revlog 'data/a.i.hg/c.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! |
|
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 warnings encountered! |
|
55 | 3 warnings encountered! | |
|
56 | hint: run "hg debugrebuildfncache" to recover from corrupt fncache | |||
|
57 | ||||
|
58 | Follow the hint to make sure it works | |||
|
59 | ||||
|
60 | $ hg debugrebuildfncache | |||
|
61 | adding data/a.i | |||
|
62 | adding data/a.i.hg/c.i | |||
|
63 | adding data/a.i/b.i | |||
|
64 | 3 items added, 0 removed from fncache | |||
|
65 | ||||
|
66 | $ hg verify | |||
|
67 | checking changesets | |||
|
68 | checking manifests | |||
|
69 | crosschecking files in changesets and manifests | |||
|
70 | checking files | |||
|
71 | 3 files, 3 changesets, 3 total revisions | |||
|
72 | ||||
56 | $ cd .. |
|
73 | $ cd .. | |
57 |
|
74 | |||
58 | Non store repo: |
|
75 | Non store repo: | |
59 |
|
76 | |||
60 | $ hg --config format.usestore=False init foo |
|
77 | $ hg --config format.usestore=False init foo | |
61 | $ cd foo |
|
78 | $ cd foo | |
62 | $ mkdir tst.d |
|
79 | $ mkdir tst.d | |
63 | $ echo foo > tst.d/foo |
|
80 | $ echo foo > tst.d/foo | |
64 | $ hg ci -Amfoo |
|
81 | $ hg ci -Amfoo | |
65 | adding tst.d/foo |
|
82 | adding tst.d/foo | |
66 | $ find .hg | sort |
|
83 | $ find .hg | sort | |
67 | .hg |
|
84 | .hg | |
68 | .hg/00changelog.i |
|
85 | .hg/00changelog.i | |
69 | .hg/00manifest.i |
|
86 | .hg/00manifest.i | |
70 | .hg/cache |
|
87 | .hg/cache | |
71 | .hg/cache/branch2-served |
|
88 | .hg/cache/branch2-served | |
72 | .hg/cache/rbc-names-v1 |
|
89 | .hg/cache/rbc-names-v1 | |
73 | .hg/cache/rbc-revs-v1 |
|
90 | .hg/cache/rbc-revs-v1 | |
74 | .hg/data |
|
91 | .hg/data | |
75 | .hg/data/tst.d.hg |
|
92 | .hg/data/tst.d.hg | |
76 | .hg/data/tst.d.hg/foo.i |
|
93 | .hg/data/tst.d.hg/foo.i | |
77 | .hg/dirstate |
|
94 | .hg/dirstate | |
78 | .hg/last-message.txt |
|
95 | .hg/last-message.txt | |
79 | .hg/phaseroots |
|
96 | .hg/phaseroots | |
80 | .hg/requires |
|
97 | .hg/requires | |
81 | .hg/undo |
|
98 | .hg/undo | |
82 | .hg/undo.backupfiles |
|
99 | .hg/undo.backupfiles | |
83 | .hg/undo.bookmarks |
|
100 | .hg/undo.bookmarks | |
84 | .hg/undo.branch |
|
101 | .hg/undo.branch | |
85 | .hg/undo.desc |
|
102 | .hg/undo.desc | |
86 | .hg/undo.dirstate |
|
103 | .hg/undo.dirstate | |
87 | .hg/undo.phaseroots |
|
104 | .hg/undo.phaseroots | |
88 | $ cd .. |
|
105 | $ cd .. | |
89 |
|
106 | |||
90 | Non fncache repo: |
|
107 | Non fncache repo: | |
91 |
|
108 | |||
92 | $ hg --config format.usefncache=False init bar |
|
109 | $ hg --config format.usefncache=False init bar | |
93 | $ cd bar |
|
110 | $ cd bar | |
94 | $ mkdir tst.d |
|
111 | $ mkdir tst.d | |
95 | $ echo foo > tst.d/Foo |
|
112 | $ echo foo > tst.d/Foo | |
96 | $ hg ci -Amfoo |
|
113 | $ hg ci -Amfoo | |
97 | adding tst.d/Foo |
|
114 | adding tst.d/Foo | |
98 | $ find .hg | sort |
|
115 | $ find .hg | sort | |
99 | .hg |
|
116 | .hg | |
100 | .hg/00changelog.i |
|
117 | .hg/00changelog.i | |
101 | .hg/cache |
|
118 | .hg/cache | |
102 | .hg/cache/branch2-served |
|
119 | .hg/cache/branch2-served | |
103 | .hg/cache/rbc-names-v1 |
|
120 | .hg/cache/rbc-names-v1 | |
104 | .hg/cache/rbc-revs-v1 |
|
121 | .hg/cache/rbc-revs-v1 | |
105 | .hg/dirstate |
|
122 | .hg/dirstate | |
106 | .hg/last-message.txt |
|
123 | .hg/last-message.txt | |
107 | .hg/requires |
|
124 | .hg/requires | |
108 | .hg/store |
|
125 | .hg/store | |
109 | .hg/store/00changelog.i |
|
126 | .hg/store/00changelog.i | |
110 | .hg/store/00manifest.i |
|
127 | .hg/store/00manifest.i | |
111 | .hg/store/data |
|
128 | .hg/store/data | |
112 | .hg/store/data/tst.d.hg |
|
129 | .hg/store/data/tst.d.hg | |
113 | .hg/store/data/tst.d.hg/_foo.i |
|
130 | .hg/store/data/tst.d.hg/_foo.i | |
114 | .hg/store/phaseroots |
|
131 | .hg/store/phaseroots | |
115 | .hg/store/undo |
|
132 | .hg/store/undo | |
116 | .hg/store/undo.backupfiles |
|
133 | .hg/store/undo.backupfiles | |
117 | .hg/store/undo.phaseroots |
|
134 | .hg/store/undo.phaseroots | |
118 | .hg/undo.bookmarks |
|
135 | .hg/undo.bookmarks | |
119 | .hg/undo.branch |
|
136 | .hg/undo.branch | |
120 | .hg/undo.desc |
|
137 | .hg/undo.desc | |
121 | .hg/undo.dirstate |
|
138 | .hg/undo.dirstate | |
122 | $ cd .. |
|
139 | $ cd .. | |
123 |
|
140 | |||
124 | Encoding of reserved / long paths in the store |
|
141 | Encoding of reserved / long paths in the store | |
125 |
|
142 | |||
126 | $ hg init r2 |
|
143 | $ hg init r2 | |
127 | $ cd r2 |
|
144 | $ cd r2 | |
128 | $ cat <<EOF > .hg/hgrc |
|
145 | $ cat <<EOF > .hg/hgrc | |
129 | > [ui] |
|
146 | > [ui] | |
130 | > portablefilenames = ignore |
|
147 | > portablefilenames = ignore | |
131 | > EOF |
|
148 | > EOF | |
132 |
|
149 | |||
133 | $ hg import -q --bypass - <<EOF |
|
150 | $ hg import -q --bypass - <<EOF | |
134 | > # HG changeset patch |
|
151 | > # HG changeset patch | |
135 | > # User test |
|
152 | > # User test | |
136 | > # Date 0 0 |
|
153 | > # Date 0 0 | |
137 | > # Node ID 1c7a2f7cb77be1a0def34e4c7cabc562ad98fbd7 |
|
154 | > # Node ID 1c7a2f7cb77be1a0def34e4c7cabc562ad98fbd7 | |
138 | > # Parent 0000000000000000000000000000000000000000 |
|
155 | > # Parent 0000000000000000000000000000000000000000 | |
139 | > 1 |
|
156 | > 1 | |
140 | > |
|
157 | > | |
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 |
|
158 | > 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 | |
142 | > new file mode 100644 |
|
159 | > new file mode 100644 | |
143 | > --- /dev/null |
|
160 | > --- /dev/null | |
144 | > +++ b/12345678/12345678/12345678/12345678/12345678/12345678/12345678/12345/xxxxxxxxx-xxxxxxxxx-xxxxxxxxx-123456789-12.3456789-12345-ABCDEFGHIJKLMNOPRSTUVWXYZ-abcdefghjiklmnopqrstuvwxyz |
|
161 | > +++ b/12345678/12345678/12345678/12345678/12345678/12345678/12345678/12345/xxxxxxxxx-xxxxxxxxx-xxxxxxxxx-123456789-12.3456789-12345-ABCDEFGHIJKLMNOPRSTUVWXYZ-abcdefghjiklmnopqrstuvwxyz | |
145 | > @@ -0,0 +1,1 @@ |
|
162 | > @@ -0,0 +1,1 @@ | |
146 | > +foo |
|
163 | > +foo | |
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 |
|
164 | > 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 | |
148 | > new file mode 100644 |
|
165 | > new file mode 100644 | |
149 | > --- /dev/null |
|
166 | > --- /dev/null | |
150 | > +++ b/AUX/SECOND/X.PRN/FOURTH/FI:FTH/SIXTH/SEVENTH/EIGHTH/NINETH/TENTH/ELEVENTH/LOREMIPSUM.TXT |
|
167 | > +++ b/AUX/SECOND/X.PRN/FOURTH/FI:FTH/SIXTH/SEVENTH/EIGHTH/NINETH/TENTH/ELEVENTH/LOREMIPSUM.TXT | |
151 | > @@ -0,0 +1,1 @@ |
|
168 | > @@ -0,0 +1,1 @@ | |
152 | > +foo |
|
169 | > +foo | |
153 | > diff --git a/Project Planning/Resources/AnotherLongDirectoryName/Followedbyanother/AndAnother/AndThenAnExtremelyLongFileName.txt b/Project Planning/Resources/AnotherLongDirectoryName/Followedbyanother/AndAnother/AndThenAnExtremelyLongFileName.txt |
|
170 | > diff --git a/Project Planning/Resources/AnotherLongDirectoryName/Followedbyanother/AndAnother/AndThenAnExtremelyLongFileName.txt b/Project Planning/Resources/AnotherLongDirectoryName/Followedbyanother/AndAnother/AndThenAnExtremelyLongFileName.txt | |
154 | > new file mode 100644 |
|
171 | > new file mode 100644 | |
155 | > --- /dev/null |
|
172 | > --- /dev/null | |
156 | > +++ b/Project Planning/Resources/AnotherLongDirectoryName/Followedbyanother/AndAnother/AndThenAnExtremelyLongFileName.txt |
|
173 | > +++ b/Project Planning/Resources/AnotherLongDirectoryName/Followedbyanother/AndAnother/AndThenAnExtremelyLongFileName.txt | |
157 | > @@ -0,0 +1,1 @@ |
|
174 | > @@ -0,0 +1,1 @@ | |
158 | > +foo |
|
175 | > +foo | |
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 |
|
176 | > 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 | |
160 | > new file mode 100644 |
|
177 | > new file mode 100644 | |
161 | > --- /dev/null |
|
178 | > --- /dev/null | |
162 | > +++ b/bla.aux/prn/PRN/lpt/com3/nul/coma/foo.NUL/normal.c |
|
179 | > +++ b/bla.aux/prn/PRN/lpt/com3/nul/coma/foo.NUL/normal.c | |
163 | > @@ -0,0 +1,1 @@ |
|
180 | > @@ -0,0 +1,1 @@ | |
164 | > +foo |
|
181 | > +foo | |
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 |
|
182 | > 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 | |
166 | > new file mode 100644 |
|
183 | > new file mode 100644 | |
167 | > --- /dev/null |
|
184 | > --- /dev/null | |
168 | > +++ b/enterprise/openesbaddons/contrib-imola/corba-bc/netbeansplugin/wsdlExtension/src/main/java/META-INF/services/org.netbeans.modules.xml.wsdl.bindingsupport.spi.ExtensibilityElementTemplateProvider |
|
185 | > +++ b/enterprise/openesbaddons/contrib-imola/corba-bc/netbeansplugin/wsdlExtension/src/main/java/META-INF/services/org.netbeans.modules.xml.wsdl.bindingsupport.spi.ExtensibilityElementTemplateProvider | |
169 | > @@ -0,0 +1,1 @@ |
|
186 | > @@ -0,0 +1,1 @@ | |
170 | > +foo |
|
187 | > +foo | |
171 | > EOF |
|
188 | > EOF | |
172 |
|
189 | |||
173 | $ find .hg/store -name *.i | sort |
|
190 | $ find .hg/store -name *.i | sort | |
174 | .hg/store/00changelog.i |
|
191 | .hg/store/00changelog.i | |
175 | .hg/store/00manifest.i |
|
192 | .hg/store/00manifest.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 |
|
193 | .hg/store/data/bla.aux/pr~6e/_p_r_n/lpt/co~6d3/nu~6c/coma/foo._n_u_l/normal.c.i | |
177 | .hg/store/dh/12345678/12345678/12345678/12345678/12345678/12345678/12345678/12345/xxxxxx168e07b38e65eff86ab579afaaa8e30bfbe0f35f.i |
|
194 | .hg/store/dh/12345678/12345678/12345678/12345678/12345678/12345678/12345678/12345/xxxxxx168e07b38e65eff86ab579afaaa8e30bfbe0f35f.i | |
178 | .hg/store/dh/au~78/second/x.prn/fourth/fi~3afth/sixth/seventh/eighth/nineth/tenth/loremia20419e358ddff1bf8751e38288aff1d7c32ec05.i |
|
195 | .hg/store/dh/au~78/second/x.prn/fourth/fi~3afth/sixth/seventh/eighth/nineth/tenth/loremia20419e358ddff1bf8751e38288aff1d7c32ec05.i | |
179 | .hg/store/dh/enterpri/openesba/contrib-/corba-bc/netbeans/wsdlexte/src/main/java/org.net7018f27961fdf338a598a40c4683429e7ffb9743.i |
|
196 | .hg/store/dh/enterpri/openesba/contrib-/corba-bc/netbeans/wsdlexte/src/main/java/org.net7018f27961fdf338a598a40c4683429e7ffb9743.i | |
180 | .hg/store/dh/project_/resource/anotherl/followed/andanoth/andthenanextremelylongfilename0d8e1f4187c650e2f1fdca9fd90f786bc0976b6b.i |
|
197 | .hg/store/dh/project_/resource/anotherl/followed/andanoth/andthenanextremelylongfilename0d8e1f4187c650e2f1fdca9fd90f786bc0976b6b.i | |
181 |
|
198 | |||
182 | $ cd .. |
|
199 | $ cd .. | |
183 |
|
200 | |||
184 | Aborting lock does not prevent fncache writes |
|
201 | Aborting lock does not prevent fncache writes | |
185 |
|
202 | |||
186 | $ cat > exceptionext.py <<EOF |
|
203 | $ cat > exceptionext.py <<EOF | |
187 | > import os |
|
204 | > import os | |
188 | > from mercurial import commands, util |
|
205 | > from mercurial import commands, util | |
189 | > from mercurial.extensions import wrapfunction |
|
206 | > from mercurial.extensions import wrapfunction | |
190 | > |
|
207 | > | |
191 | > def lockexception(orig, vfs, lockname, wait, releasefn, acquirefn, desc): |
|
208 | > def lockexception(orig, vfs, lockname, wait, releasefn, acquirefn, desc): | |
192 | > def releasewrap(): |
|
209 | > def releasewrap(): | |
193 | > raise util.Abort("forced lock failure") |
|
210 | > raise util.Abort("forced lock failure") | |
194 | > return orig(vfs, lockname, wait, releasewrap, acquirefn, desc) |
|
211 | > return orig(vfs, lockname, wait, releasewrap, acquirefn, desc) | |
195 | > |
|
212 | > | |
196 | > def reposetup(ui, repo): |
|
213 | > def reposetup(ui, repo): | |
197 | > wrapfunction(repo, '_lock', lockexception) |
|
214 | > wrapfunction(repo, '_lock', lockexception) | |
198 | > |
|
215 | > | |
199 | > cmdtable = {} |
|
216 | > cmdtable = {} | |
200 | > |
|
217 | > | |
201 | > EOF |
|
218 | > EOF | |
202 | $ extpath=`pwd`/exceptionext.py |
|
219 | $ extpath=`pwd`/exceptionext.py | |
203 | $ hg init fncachetxn |
|
220 | $ hg init fncachetxn | |
204 | $ cd fncachetxn |
|
221 | $ cd fncachetxn | |
205 | $ printf "[extensions]\nexceptionext=$extpath\n" >> .hg/hgrc |
|
222 | $ printf "[extensions]\nexceptionext=$extpath\n" >> .hg/hgrc | |
206 | $ touch y |
|
223 | $ touch y | |
207 | $ hg ci -qAm y |
|
224 | $ hg ci -qAm y | |
208 | abort: forced lock failure |
|
225 | abort: forced lock failure | |
209 | [255] |
|
226 | [255] | |
210 | $ cat .hg/store/fncache |
|
227 | $ cat .hg/store/fncache | |
211 | data/y.i |
|
228 | data/y.i | |
212 |
|
229 | |||
213 | Aborting transaction prevents fncache change |
|
230 | Aborting transaction prevents fncache change | |
214 |
|
231 | |||
215 | $ cat > ../exceptionext.py <<EOF |
|
232 | $ cat > ../exceptionext.py <<EOF | |
216 | > import os |
|
233 | > import os | |
217 | > from mercurial import commands, util, localrepo |
|
234 | > from mercurial import commands, util, localrepo | |
218 | > from mercurial.extensions import wrapfunction |
|
235 | > from mercurial.extensions import wrapfunction | |
219 | > |
|
236 | > | |
220 | > def wrapper(orig, self, *args, **kwargs): |
|
237 | > def wrapper(orig, self, *args, **kwargs): | |
221 | > tr = orig(self, *args, **kwargs) |
|
238 | > tr = orig(self, *args, **kwargs) | |
222 | > def fail(tr): |
|
239 | > def fail(tr): | |
223 | > raise util.Abort("forced transaction failure") |
|
240 | > raise util.Abort("forced transaction failure") | |
224 | > # zzz prefix to ensure it sorted after store.write |
|
241 | > # zzz prefix to ensure it sorted after store.write | |
225 | > tr.addfinalize('zzz-forcefails', fail) |
|
242 | > tr.addfinalize('zzz-forcefails', fail) | |
226 | > return tr |
|
243 | > return tr | |
227 | > |
|
244 | > | |
228 | > def uisetup(ui): |
|
245 | > def uisetup(ui): | |
229 | > wrapfunction(localrepo.localrepository, 'transaction', wrapper) |
|
246 | > wrapfunction(localrepo.localrepository, 'transaction', wrapper) | |
230 | > |
|
247 | > | |
231 | > cmdtable = {} |
|
248 | > cmdtable = {} | |
232 | > |
|
249 | > | |
233 | > EOF |
|
250 | > EOF | |
234 | $ rm -f "${extpath}c" |
|
251 | $ rm -f "${extpath}c" | |
235 | $ touch z |
|
252 | $ touch z | |
236 | $ hg ci -qAm z |
|
253 | $ hg ci -qAm z | |
237 | transaction abort! |
|
254 | transaction abort! | |
238 | rollback completed |
|
255 | rollback completed | |
239 | abort: forced transaction failure |
|
256 | abort: forced transaction failure | |
240 | [255] |
|
257 | [255] | |
241 | $ cat .hg/store/fncache |
|
258 | $ cat .hg/store/fncache | |
242 | data/y.i |
|
259 | data/y.i | |
243 |
|
260 | |||
244 | Aborted transactions can be recovered later |
|
261 | Aborted transactions can be recovered later | |
245 |
|
262 | |||
246 | $ cat > ../exceptionext.py <<EOF |
|
263 | $ cat > ../exceptionext.py <<EOF | |
247 | > import os |
|
264 | > import os | |
248 | > from mercurial import commands, util, transaction, localrepo |
|
265 | > from mercurial import commands, util, transaction, localrepo | |
249 | > from mercurial.extensions import wrapfunction |
|
266 | > from mercurial.extensions import wrapfunction | |
250 | > |
|
267 | > | |
251 | > def trwrapper(orig, self, *args, **kwargs): |
|
268 | > def trwrapper(orig, self, *args, **kwargs): | |
252 | > tr = orig(self, *args, **kwargs) |
|
269 | > tr = orig(self, *args, **kwargs) | |
253 | > def fail(tr): |
|
270 | > def fail(tr): | |
254 | > raise util.Abort("forced transaction failure") |
|
271 | > raise util.Abort("forced transaction failure") | |
255 | > # zzz prefix to ensure it sorted after store.write |
|
272 | > # zzz prefix to ensure it sorted after store.write | |
256 | > tr.addfinalize('zzz-forcefails', fail) |
|
273 | > tr.addfinalize('zzz-forcefails', fail) | |
257 | > return tr |
|
274 | > return tr | |
258 | > |
|
275 | > | |
259 | > def abortwrapper(orig, self, *args, **kwargs): |
|
276 | > def abortwrapper(orig, self, *args, **kwargs): | |
260 | > raise util.Abort("forced transaction failure") |
|
277 | > raise util.Abort("forced transaction failure") | |
261 | > |
|
278 | > | |
262 | > def uisetup(ui): |
|
279 | > def uisetup(ui): | |
263 | > wrapfunction(localrepo.localrepository, 'transaction', trwrapper) |
|
280 | > wrapfunction(localrepo.localrepository, 'transaction', trwrapper) | |
264 | > wrapfunction(transaction.transaction, '_abort', abortwrapper) |
|
281 | > wrapfunction(transaction.transaction, '_abort', abortwrapper) | |
265 | > |
|
282 | > | |
266 | > cmdtable = {} |
|
283 | > cmdtable = {} | |
267 | > |
|
284 | > | |
268 | > EOF |
|
285 | > EOF | |
269 | $ rm -f "${extpath}c" |
|
286 | $ rm -f "${extpath}c" | |
270 | $ hg up -q 1 |
|
287 | $ hg up -q 1 | |
271 | $ touch z |
|
288 | $ touch z | |
272 | $ hg ci -qAm z 2>/dev/null |
|
289 | $ hg ci -qAm z 2>/dev/null | |
273 | [255] |
|
290 | [255] | |
274 | $ cat .hg/store/fncache | sort |
|
291 | $ cat .hg/store/fncache | sort | |
275 | data/y.i |
|
292 | data/y.i | |
276 | data/z.i |
|
293 | data/z.i | |
277 | $ hg recover |
|
294 | $ hg recover | |
278 | rolling back interrupted transaction |
|
295 | rolling back interrupted transaction | |
279 | checking changesets |
|
296 | checking changesets | |
280 | checking manifests |
|
297 | checking manifests | |
281 | crosschecking files in changesets and manifests |
|
298 | crosschecking files in changesets and manifests | |
282 | checking files |
|
299 | checking files | |
283 | 1 files, 1 changesets, 1 total revisions |
|
300 | 1 files, 1 changesets, 1 total revisions | |
284 | $ cat .hg/store/fncache |
|
301 | $ cat .hg/store/fncache | |
285 | data/y.i |
|
302 | data/y.i | |
286 |
|
303 | |||
287 | $ cd .. |
|
304 | $ cd .. | |
288 |
|
305 | |||
289 | debugrebuildfncache does nothing unless repo has fncache requirement |
|
306 | debugrebuildfncache does nothing unless repo has fncache requirement | |
290 |
|
307 | |||
291 | $ hg --config format.usefncache=false init nofncache |
|
308 | $ hg --config format.usefncache=false init nofncache | |
292 | $ cd nofncache |
|
309 | $ cd nofncache | |
293 | $ hg debugrebuildfncache |
|
310 | $ hg debugrebuildfncache | |
294 | (not rebuilding fncache because repository does not support fncache |
|
311 | (not rebuilding fncache because repository does not support fncache | |
295 |
|
312 | |||
296 | $ cd .. |
|
313 | $ cd .. | |
297 |
|
314 | |||
298 | debugrebuildfncache works on empty repository |
|
315 | debugrebuildfncache works on empty repository | |
299 |
|
316 | |||
300 | $ hg init empty |
|
317 | $ hg init empty | |
301 | $ cd empty |
|
318 | $ cd empty | |
302 | $ hg debugrebuildfncache |
|
319 | $ hg debugrebuildfncache | |
303 | fncache already up to date |
|
320 | fncache already up to date | |
304 | $ cd .. |
|
321 | $ cd .. | |
305 |
|
322 | |||
306 | debugrebuildfncache on an up to date repository no-ops |
|
323 | debugrebuildfncache on an up to date repository no-ops | |
307 |
|
324 | |||
308 | $ hg init repo |
|
325 | $ hg init repo | |
309 | $ cd repo |
|
326 | $ cd repo | |
310 | $ echo initial > foo |
|
327 | $ echo initial > foo | |
311 | $ echo initial > .bar |
|
328 | $ echo initial > .bar | |
312 | $ hg commit -A -m initial |
|
329 | $ hg commit -A -m initial | |
313 | adding .bar |
|
330 | adding .bar | |
314 | adding foo |
|
331 | adding foo | |
315 |
|
332 | |||
316 | $ cat .hg/store/fncache | sort |
|
333 | $ cat .hg/store/fncache | sort | |
317 | data/.bar.i |
|
334 | data/.bar.i | |
318 | data/foo.i |
|
335 | data/foo.i | |
319 |
|
336 | |||
320 | $ hg debugrebuildfncache |
|
337 | $ hg debugrebuildfncache | |
321 | fncache already up to date |
|
338 | fncache already up to date | |
322 |
|
339 | |||
323 | debugrebuildfncache restores deleted fncache file |
|
340 | debugrebuildfncache restores deleted fncache file | |
324 |
|
341 | |||
325 | $ rm -f .hg/store/fncache |
|
342 | $ rm -f .hg/store/fncache | |
326 | $ hg debugrebuildfncache |
|
343 | $ hg debugrebuildfncache | |
327 | adding data/.bar.i |
|
344 | adding data/.bar.i | |
328 | adding data/foo.i |
|
345 | adding data/foo.i | |
329 | 2 items added, 0 removed from fncache |
|
346 | 2 items added, 0 removed from fncache | |
330 |
|
347 | |||
331 | $ cat .hg/store/fncache | sort |
|
348 | $ cat .hg/store/fncache | sort | |
332 | data/.bar.i |
|
349 | data/.bar.i | |
333 | data/foo.i |
|
350 | data/foo.i | |
334 |
|
351 | |||
335 | Rebuild after rebuild should no-op |
|
352 | Rebuild after rebuild should no-op | |
336 |
|
353 | |||
337 | $ hg debugrebuildfncache |
|
354 | $ hg debugrebuildfncache | |
338 | fncache already up to date |
|
355 | fncache already up to date | |
339 |
|
356 | |||
340 | A single missing file should get restored, an extra file should be removed |
|
357 | A single missing file should get restored, an extra file should be removed | |
341 |
|
358 | |||
342 | $ cat > .hg/store/fncache << EOF |
|
359 | $ cat > .hg/store/fncache << EOF | |
343 | > data/foo.i |
|
360 | > data/foo.i | |
344 | > data/bad-entry.i |
|
361 | > data/bad-entry.i | |
345 | > EOF |
|
362 | > EOF | |
346 |
|
363 | |||
347 | $ hg debugrebuildfncache |
|
364 | $ hg debugrebuildfncache | |
348 | removing data/bad-entry.i |
|
365 | removing data/bad-entry.i | |
349 | adding data/.bar.i |
|
366 | adding data/.bar.i | |
350 | 1 items added, 1 removed from fncache |
|
367 | 1 items added, 1 removed from fncache | |
351 |
|
368 | |||
352 | $ cat .hg/store/fncache | sort |
|
369 | $ cat .hg/store/fncache | sort | |
353 | data/.bar.i |
|
370 | data/.bar.i | |
354 | data/foo.i |
|
371 | data/foo.i | |
355 |
|
372 | |||
356 | $ cd .. |
|
373 | $ cd .. | |
357 |
|
374 | |||
358 | Try a simple variation without dotencode to ensure fncache is ignorant of encoding |
|
375 | Try a simple variation without dotencode to ensure fncache is ignorant of encoding | |
359 |
|
376 | |||
360 | $ hg --config format.dotencode=false init nodotencode |
|
377 | $ hg --config format.dotencode=false init nodotencode | |
361 | $ cd nodotencode |
|
378 | $ cd nodotencode | |
362 | $ echo initial > foo |
|
379 | $ echo initial > foo | |
363 | $ echo initial > .bar |
|
380 | $ echo initial > .bar | |
364 | $ hg commit -A -m initial |
|
381 | $ hg commit -A -m initial | |
365 | adding .bar |
|
382 | adding .bar | |
366 | adding foo |
|
383 | adding foo | |
367 |
|
384 | |||
368 | $ cat .hg/store/fncache | sort |
|
385 | $ cat .hg/store/fncache | sort | |
369 | data/.bar.i |
|
386 | data/.bar.i | |
370 | data/foo.i |
|
387 | data/foo.i | |
371 |
|
388 | |||
372 | $ rm .hg/store/fncache |
|
389 | $ rm .hg/store/fncache | |
373 | $ hg debugrebuildfncache |
|
390 | $ hg debugrebuildfncache | |
374 | adding data/.bar.i |
|
391 | adding data/.bar.i | |
375 | adding data/foo.i |
|
392 | adding data/foo.i | |
376 | 2 items added, 0 removed from fncache |
|
393 | 2 items added, 0 removed from fncache | |
377 |
|
394 | |||
378 | $ cat .hg/store/fncache | sort |
|
395 | $ cat .hg/store/fncache | sort | |
379 | data/.bar.i |
|
396 | data/.bar.i | |
380 | data/foo.i |
|
397 | data/foo.i |
@@ -1,116 +1,117 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 | warning: revlog 'data/FOO.txt.i' not in fncache! |
|
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 | warning: revlog 'data/QUICK.txt.i' not in fncache! |
|
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 | warning: revlog 'data/bar.txt.i' not in fncache! |
|
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 | 3 warnings encountered! |
|
57 | 3 warnings encountered! | |
|
58 | hint: run "hg debugrebuildfncache" to recover from corrupt fncache | |||
58 | 6 integrity errors encountered! |
|
59 | 6 integrity errors encountered! | |
59 | (first damaged changeset appears to be 0) |
|
60 | (first damaged changeset appears to be 0) | |
60 | [1] |
|
61 | [1] | |
61 |
|
62 | |||
62 | $ cd ../../.. |
|
63 | $ cd ../../.. | |
63 | $ cd .. |
|
64 | $ cd .. | |
64 |
|
65 | |||
65 | test changelog without a manifest |
|
66 | test changelog without a manifest | |
66 |
|
67 | |||
67 | $ hg init b |
|
68 | $ hg init b | |
68 | $ cd b |
|
69 | $ cd b | |
69 | $ hg branch foo |
|
70 | $ hg branch foo | |
70 | marked working directory as branch foo |
|
71 | marked working directory as branch foo | |
71 | (branches are permanent and global, did you want a bookmark?) |
|
72 | (branches are permanent and global, did you want a bookmark?) | |
72 | $ hg ci -m branchfoo |
|
73 | $ hg ci -m branchfoo | |
73 | $ hg verify |
|
74 | $ hg verify | |
74 | checking changesets |
|
75 | checking changesets | |
75 | checking manifests |
|
76 | checking manifests | |
76 | crosschecking files in changesets and manifests |
|
77 | crosschecking files in changesets and manifests | |
77 | checking files |
|
78 | checking files | |
78 | 0 files, 1 changesets, 0 total revisions |
|
79 | 0 files, 1 changesets, 0 total revisions | |
79 |
|
80 | |||
80 | test revlog corruption |
|
81 | test revlog corruption | |
81 |
|
82 | |||
82 | $ touch a |
|
83 | $ touch a | |
83 | $ hg add a |
|
84 | $ hg add a | |
84 | $ hg ci -m a |
|
85 | $ hg ci -m a | |
85 |
|
86 | |||
86 | $ echo 'corrupted' > b |
|
87 | $ echo 'corrupted' > b | |
87 | $ dd if=.hg/store/data/a.i of=start bs=1 count=20 2>/dev/null |
|
88 | $ dd if=.hg/store/data/a.i of=start bs=1 count=20 2>/dev/null | |
88 | $ cat start b > .hg/store/data/a.i |
|
89 | $ cat start b > .hg/store/data/a.i | |
89 |
|
90 | |||
90 | $ hg verify |
|
91 | $ hg verify | |
91 | checking changesets |
|
92 | checking changesets | |
92 | checking manifests |
|
93 | checking manifests | |
93 | crosschecking files in changesets and manifests |
|
94 | crosschecking files in changesets and manifests | |
94 | checking files |
|
95 | checking files | |
95 | a@1: broken revlog! (index data/a.i is corrupted) |
|
96 | a@1: broken revlog! (index data/a.i is corrupted) | |
96 | warning: orphan revlog 'data/a.i' |
|
97 | warning: orphan revlog 'data/a.i' | |
97 | 1 files, 2 changesets, 0 total revisions |
|
98 | 1 files, 2 changesets, 0 total revisions | |
98 | 1 warnings encountered! |
|
99 | 1 warnings encountered! | |
99 | 1 integrity errors encountered! |
|
100 | 1 integrity errors encountered! | |
100 | (first damaged changeset appears to be 1) |
|
101 | (first damaged changeset appears to be 1) | |
101 | [1] |
|
102 | [1] | |
102 |
|
103 | |||
103 | $ cd .. |
|
104 | $ cd .. | |
104 |
|
105 | |||
105 | test revlog format 0 |
|
106 | test revlog format 0 | |
106 |
|
107 | |||
107 | $ revlog-formatv0.py |
|
108 | $ revlog-formatv0.py | |
108 | $ cd formatv0 |
|
109 | $ cd formatv0 | |
109 | $ hg verify |
|
110 | $ hg verify | |
110 | repository uses revlog format 0 |
|
111 | repository uses revlog format 0 | |
111 | checking changesets |
|
112 | checking changesets | |
112 | checking manifests |
|
113 | checking manifests | |
113 | crosschecking files in changesets and manifests |
|
114 | crosschecking files in changesets and manifests | |
114 | checking files |
|
115 | checking files | |
115 | 1 files, 1 changesets, 1 total revisions |
|
116 | 1 files, 1 changesets, 1 total revisions | |
116 | $ cd .. |
|
117 | $ cd .. |
General Comments 0
You need to be logged in to leave comments.
Login now