Show More
@@ -17,7 +17,7 b'' | |||
|
17 | 17 | # pass |
|
18 | 18 | |
|
19 | 19 | import sys |
|
20 |
from mercurial import hg, |
|
|
20 | from mercurial import hg, fancyopts, ui, commands | |
|
21 | 21 | |
|
22 | 22 | try: |
|
23 | 23 | sys.exit(commands.dispatch(sys.argv[1:])) |
@@ -116,129 +116,6 b' elif cmd == "tags":' | |||
|
116 | 116 | r = "?" |
|
117 | 117 | print "%-30s %5d:%s" % (k, repo.changelog.rev(n), hg.hex(n)) |
|
118 | 118 | |
|
119 | elif cmd == "verify": | |
|
120 | filelinkrevs = {} | |
|
121 | filenodes = {} | |
|
122 | manifestchangeset = {} | |
|
123 | changesets = revisions = files = 0 | |
|
124 | errors = 0 | |
|
125 | ||
|
126 | ui.status("checking changesets\n") | |
|
127 | for i in range(repo.changelog.count()): | |
|
128 | changesets += 1 | |
|
129 | n = repo.changelog.node(i) | |
|
130 | for p in repo.changelog.parents(n): | |
|
131 | if p not in repo.changelog.nodemap: | |
|
132 | ui.warn("changeset %s has unknown parent %s\n" % | |
|
133 | (hg.short(n), hg.short(p))) | |
|
134 | errors += 1 | |
|
135 | try: | |
|
136 | changes = repo.changelog.read(n) | |
|
137 | except Exception, inst: | |
|
138 | ui.warn("unpacking changeset %s: %s\n" % (short(n), inst)) | |
|
139 | errors += 1 | |
|
140 | ||
|
141 | manifestchangeset[changes[0]] = n | |
|
142 | for f in changes[3]: | |
|
143 | filelinkrevs.setdefault(f, []).append(i) | |
|
144 | ||
|
145 | ui.status("checking manifests\n") | |
|
146 | for i in range(repo.manifest.count()): | |
|
147 | n = repo.manifest.node(i) | |
|
148 | for p in repo.manifest.parents(n): | |
|
149 | if p not in repo.manifest.nodemap: | |
|
150 | ui.warn("manifest %s has unknown parent %s\n" % | |
|
151 | (hg.short(n), hg.short(p))) | |
|
152 | errors += 1 | |
|
153 | ca = repo.changelog.node(repo.manifest.linkrev(n)) | |
|
154 | cc = manifestchangeset[n] | |
|
155 | if ca != cc: | |
|
156 | ui.warn("manifest %s points to %s, not %s\n" % | |
|
157 | (hg.hex(n), hg.hex(ca), hg.hex(cc))) | |
|
158 | errors += 1 | |
|
159 | ||
|
160 | try: | |
|
161 | delta = mdiff.patchtext(repo.manifest.delta(n)) | |
|
162 | except KeyboardInterrupt: | |
|
163 | print "aborted" | |
|
164 | sys.exit(0) | |
|
165 | except Exception, inst: | |
|
166 | ui.warn("unpacking manifest %s: %s\n" % (hg.short(n), inst)) | |
|
167 | errors += 1 | |
|
168 | ||
|
169 | ff = [ l.split('\0') for l in delta.splitlines() ] | |
|
170 | for f, fn in ff: | |
|
171 | filenodes.setdefault(f, {})[hg.bin(fn)] = 1 | |
|
172 | ||
|
173 | ui.status("crosschecking files in changesets and manifests\n") | |
|
174 | for f in filenodes: | |
|
175 | if f not in filelinkrevs: | |
|
176 | ui.warn("file %s in manifest but not in changesets\n" % f) | |
|
177 | errors += 1 | |
|
178 | ||
|
179 | for f in filelinkrevs: | |
|
180 | if f not in filenodes: | |
|
181 | ui.warn("file %s in changeset but not in manifest\n" % f) | |
|
182 | errors += 1 | |
|
183 | ||
|
184 | ui.status("checking files\n") | |
|
185 | ff = filenodes.keys() | |
|
186 | ff.sort() | |
|
187 | for f in ff: | |
|
188 | if f == "/dev/null": continue | |
|
189 | files += 1 | |
|
190 | fl = repo.file(f) | |
|
191 | nodes = { hg.nullid: 1 } | |
|
192 | for i in range(fl.count()): | |
|
193 | revisions += 1 | |
|
194 | n = fl.node(i) | |
|
195 | ||
|
196 | if n not in filenodes[f]: | |
|
197 | ui.warn("%s: %d:%s not in manifests\n" % (f, i, hg.short(n))) | |
|
198 | print len(filenodes[f].keys()), fl.count(), f | |
|
199 | errors += 1 | |
|
200 | else: | |
|
201 | del filenodes[f][n] | |
|
202 | ||
|
203 | flr = fl.linkrev(n) | |
|
204 | if flr not in filelinkrevs[f]: | |
|
205 | ui.warn("%s:%s points to unexpected changeset rev %d\n" | |
|
206 | % (f, hg.short(n), fl.linkrev(n))) | |
|
207 | errors += 1 | |
|
208 | else: | |
|
209 | filelinkrevs[f].remove(flr) | |
|
210 | ||
|
211 | # verify contents | |
|
212 | try: | |
|
213 | t = fl.read(n) | |
|
214 | except Exception, inst: | |
|
215 | ui.warn("unpacking file %s %s: %s\n" % (f, hg.short(n), inst)) | |
|
216 | errors += 1 | |
|
217 | ||
|
218 | # verify parents | |
|
219 | (p1, p2) = fl.parents(n) | |
|
220 | if p1 not in nodes: | |
|
221 | ui.warn("file %s:%s unknown parent 1 %s" % | |
|
222 | (f, hg.short(n), hg.short(p1))) | |
|
223 | errors += 1 | |
|
224 | if p2 not in nodes: | |
|
225 | ui.warn("file %s:%s unknown parent 2 %s" % | |
|
226 | (f, hg.short(n), hg.short(p1))) | |
|
227 | errors += 1 | |
|
228 | nodes[n] = 1 | |
|
229 | ||
|
230 | # cross-check | |
|
231 | for node in filenodes[f]: | |
|
232 | ui.warn("node %s in manifests not in %s\n" % (hg.hex(n), f)) | |
|
233 | errors += 1 | |
|
234 | ||
|
235 | ui.status("%d files, %d changesets, %d total revisions\n" % | |
|
236 | (files, changesets, revisions)) | |
|
237 | ||
|
238 | if errors: | |
|
239 | ui.warn("%d integrity errors encountered!\n" % errors) | |
|
240 | sys.exit(1) | |
|
241 | ||
|
242 | 119 | else: |
|
243 | 120 | if cmd: ui.warn("unknown command\n\n") |
|
244 | 121 | sys.exit(1) |
@@ -389,6 +389,10 b' def tip(ui, repo):' | |||
|
389 | 389 | def undo(ui, repo): |
|
390 | 390 | repo.undo() |
|
391 | 391 | |
|
392 | def verify(ui, repo): | |
|
393 | """verify the integrity of the repository""" | |
|
394 | return repo.verify() | |
|
395 | ||
|
392 | 396 | table = { |
|
393 | 397 | "add": (add, [], "hg add [files]"), |
|
394 | 398 | "addremove": (addremove, [], "hg addremove"), |
@@ -436,6 +440,7 b' table = {' | |||
|
436 | 440 | "status": (status, [], 'hg status'), |
|
437 | 441 | "tip": (tip, [], 'hg tip'), |
|
438 | 442 | "undo": (undo, [], 'hg undo'), |
|
443 | "verify": (verify, [], 'hg verify'), | |
|
439 | 444 | } |
|
440 | 445 | |
|
441 | 446 | norepo = "init branch help" |
@@ -993,6 +993,133 b' class localrepository:' | |||
|
993 | 993 | os.unlink(b) |
|
994 | 994 | os.unlink(c) |
|
995 | 995 | |
|
996 | def verify(self): | |
|
997 | filelinkrevs = {} | |
|
998 | filenodes = {} | |
|
999 | manifestchangeset = {} | |
|
1000 | changesets = revisions = files = 0 | |
|
1001 | errors = 0 | |
|
1002 | ||
|
1003 | self.ui.status("checking changesets\n") | |
|
1004 | for i in range(self.changelog.count()): | |
|
1005 | changesets += 1 | |
|
1006 | n = self.changelog.node(i) | |
|
1007 | for p in self.changelog.parents(n): | |
|
1008 | if p not in self.changelog.nodemap: | |
|
1009 | self.ui.warn("changeset %s has unknown parent %s\n" % | |
|
1010 | (short(n), short(p))) | |
|
1011 | errors += 1 | |
|
1012 | try: | |
|
1013 | changes = self.changelog.read(n) | |
|
1014 | except Exception, inst: | |
|
1015 | self.ui.warn("unpacking changeset %s: %s\n" % (short(n), inst)) | |
|
1016 | errors += 1 | |
|
1017 | ||
|
1018 | manifestchangeset[changes[0]] = n | |
|
1019 | for f in changes[3]: | |
|
1020 | filelinkrevs.setdefault(f, []).append(i) | |
|
1021 | ||
|
1022 | self.ui.status("checking manifests\n") | |
|
1023 | for i in range(self.manifest.count()): | |
|
1024 | n = self.manifest.node(i) | |
|
1025 | for p in self.manifest.parents(n): | |
|
1026 | if p not in self.manifest.nodemap: | |
|
1027 | self.ui.warn("manifest %s has unknown parent %s\n" % | |
|
1028 | (short(n), short(p))) | |
|
1029 | errors += 1 | |
|
1030 | ca = self.changelog.node(self.manifest.linkrev(n)) | |
|
1031 | cc = manifestchangeset[n] | |
|
1032 | if ca != cc: | |
|
1033 | self.ui.warn("manifest %s points to %s, not %s\n" % | |
|
1034 | (hex(n), hex(ca), hex(cc))) | |
|
1035 | errors += 1 | |
|
1036 | ||
|
1037 | try: | |
|
1038 | delta = mdiff.patchtext(self.manifest.delta(n)) | |
|
1039 | except KeyboardInterrupt: | |
|
1040 | print "aborted" | |
|
1041 | sys.exit(0) | |
|
1042 | except Exception, inst: | |
|
1043 | self.ui.warn("unpacking manifest %s: %s\n" | |
|
1044 | % (short(n), inst)) | |
|
1045 | errors += 1 | |
|
1046 | ||
|
1047 | ff = [ l.split('\0') for l in delta.splitlines() ] | |
|
1048 | for f, fn in ff: | |
|
1049 | filenodes.setdefault(f, {})[bin(fn)] = 1 | |
|
1050 | ||
|
1051 | self.ui.status("crosschecking files in changesets and manifests\n") | |
|
1052 | for f in filenodes: | |
|
1053 | if f not in filelinkrevs: | |
|
1054 | self.ui.warn("file %s in manifest but not in changesets\n" % f) | |
|
1055 | errors += 1 | |
|
1056 | ||
|
1057 | for f in filelinkrevs: | |
|
1058 | if f not in filenodes: | |
|
1059 | self.ui.warn("file %s in changeset but not in manifest\n" % f) | |
|
1060 | errors += 1 | |
|
1061 | ||
|
1062 | self.ui.status("checking files\n") | |
|
1063 | ff = filenodes.keys() | |
|
1064 | ff.sort() | |
|
1065 | for f in ff: | |
|
1066 | if f == "/dev/null": continue | |
|
1067 | files += 1 | |
|
1068 | fl = self.file(f) | |
|
1069 | nodes = { nullid: 1 } | |
|
1070 | for i in range(fl.count()): | |
|
1071 | revisions += 1 | |
|
1072 | n = fl.node(i) | |
|
1073 | ||
|
1074 | if n not in filenodes[f]: | |
|
1075 | self.ui.warn("%s: %d:%s not in manifests\n" | |
|
1076 | % (f, i, short(n))) | |
|
1077 | print len(filenodes[f].keys()), fl.count(), f | |
|
1078 | errors += 1 | |
|
1079 | else: | |
|
1080 | del filenodes[f][n] | |
|
1081 | ||
|
1082 | flr = fl.linkrev(n) | |
|
1083 | if flr not in filelinkrevs[f]: | |
|
1084 | self.ui.warn("%s:%s points to unexpected changeset %d\n" | |
|
1085 | % (f, short(n), fl.linkrev(n))) | |
|
1086 | errors += 1 | |
|
1087 | else: | |
|
1088 | filelinkrevs[f].remove(flr) | |
|
1089 | ||
|
1090 | # verify contents | |
|
1091 | try: | |
|
1092 | t = fl.read(n) | |
|
1093 | except Exception, inst: | |
|
1094 | self.ui.warn("unpacking file %s %s: %s\n" | |
|
1095 | % (f, short(n), inst)) | |
|
1096 | errors += 1 | |
|
1097 | ||
|
1098 | # verify parents | |
|
1099 | (p1, p2) = fl.parents(n) | |
|
1100 | if p1 not in nodes: | |
|
1101 | self.ui.warn("file %s:%s unknown parent 1 %s" % | |
|
1102 | (f, short(n), short(p1))) | |
|
1103 | errors += 1 | |
|
1104 | if p2 not in nodes: | |
|
1105 | self.ui.warn("file %s:%s unknown parent 2 %s" % | |
|
1106 | (f, short(n), short(p1))) | |
|
1107 | errors += 1 | |
|
1108 | nodes[n] = 1 | |
|
1109 | ||
|
1110 | # cross-check | |
|
1111 | for node in filenodes[f]: | |
|
1112 | self.ui.warn("node %s in manifests not in %s\n" | |
|
1113 | % (hex(n), f)) | |
|
1114 | errors += 1 | |
|
1115 | ||
|
1116 | self.ui.status("%d files, %d changesets, %d total revisions\n" % | |
|
1117 | (files, changesets, revisions)) | |
|
1118 | ||
|
1119 | if errors: | |
|
1120 | self.ui.warn("%d integrity errors encountered!\n" % errors) | |
|
1121 | return 1 | |
|
1122 | ||
|
996 | 1123 | class remoterepository: |
|
997 | 1124 | def __init__(self, ui, path): |
|
998 | 1125 | self.url = path |
General Comments 0
You need to be logged in to leave comments.
Login now