##// END OF EJS Templates
Add debugindexdot to generate graphviz dot files from indexes
mpm@selenic.com -
r92:e6fc7ff5 default
parent child Browse files
Show More
@@ -1,501 +1,514 b''
1 #!/usr/bin/env python
1 #!/usr/bin/env python
2 #
2 #
3 # mercurial - a minimal scalable distributed SCM
3 # mercurial - a minimal scalable distributed SCM
4 # v0.4f "jane dark"
4 # v0.4f "jane dark"
5 #
5 #
6 # Copyright 2005 Matt Mackall <mpm@selenic.com>
6 # Copyright 2005 Matt Mackall <mpm@selenic.com>
7 #
7 #
8 # This software may be used and distributed according to the terms
8 # This software may be used and distributed according to the terms
9 # of the GNU General Public License, incorporated herein by reference.
9 # of the GNU General Public License, incorporated herein by reference.
10
10
11 # the psyco compiler makes commits a bit faster
11 # the psyco compiler makes commits a bit faster
12 # and makes changegroup merge about 20 times slower!
12 # and makes changegroup merge about 20 times slower!
13 # try:
13 # try:
14 # import psyco
14 # import psyco
15 # psyco.full()
15 # psyco.full()
16 # except:
16 # except:
17 # pass
17 # pass
18
18
19 import sys, os, time
19 import sys, os, time
20 from mercurial import hg, mdiff, fancyopts
20 from mercurial import hg, mdiff, fancyopts
21
21
22 def help():
22 def help():
23 print """\
23 print """\
24 commands:
24 commands:
25
25
26 init create a new repository in this directory
26 init create a new repository in this directory
27 branch <path> create a branch of <path> in this directory
27 branch <path> create a branch of <path> in this directory
28 merge <path> merge changes from <path> into local repository
28 merge <path> merge changes from <path> into local repository
29 checkout [changeset] checkout the latest or given changeset
29 checkout [changeset] checkout the latest or given changeset
30 status show new, missing, and changed files in working dir
30 status show new, missing, and changed files in working dir
31 add [files...] add the given files in the next commit
31 add [files...] add the given files in the next commit
32 remove [files...] remove the given files in the next commit
32 remove [files...] remove the given files in the next commit
33 addremove add all new files, delete all missing files
33 addremove add all new files, delete all missing files
34 commit commit all changes to the repository
34 commit commit all changes to the repository
35 history show changeset history
35 history show changeset history
36 log <file> show revision history of a single file
36 log <file> show revision history of a single file
37 dump <file> [rev] dump the latest or given revision of a file
37 dump <file> [rev] dump the latest or given revision of a file
38 dumpmanifest [rev] dump the latest or given revision of the manifest
38 dumpmanifest [rev] dump the latest or given revision of the manifest
39 diff [files...] diff working directory (or selected files)
39 diff [files...] diff working directory (or selected files)
40 tags show current changeset tags
40 tags show current changeset tags
41 annotate [files...] show changeset number per file line
41 annotate [files...] show changeset number per file line
42 blame [files...] show commit user per file line
42 blame [files...] show commit user per file line
43 """
43 """
44
44
45 def filterfiles(list, files):
45 def filterfiles(list, files):
46 l = [ x for x in list if x in files ]
46 l = [ x for x in list if x in files ]
47
47
48 for f in files:
48 for f in files:
49 if f[-1] != os.sep: f += os.sep
49 if f[-1] != os.sep: f += os.sep
50 l += [ x for x in list if x.startswith(f) ]
50 l += [ x for x in list if x.startswith(f) ]
51 return l
51 return l
52
52
53 def diff(files = None, node1 = None, node2 = None):
53 def diff(files = None, node1 = None, node2 = None):
54 def date(c):
54 def date(c):
55 return time.asctime(time.gmtime(float(c[2].split(' ')[0])))
55 return time.asctime(time.gmtime(float(c[2].split(' ')[0])))
56
56
57 if node2:
57 if node2:
58 change = repo.changelog.read(node2)
58 change = repo.changelog.read(node2)
59 mmap2 = repo.manifest.read(change[0])
59 mmap2 = repo.manifest.read(change[0])
60 (c, a, d) = repo.diffrevs(node1, node2)
60 (c, a, d) = repo.diffrevs(node1, node2)
61 def read(f): return repo.file(f).read(mmap2[f])
61 def read(f): return repo.file(f).read(mmap2[f])
62 date2 = date(change)
62 date2 = date(change)
63 else:
63 else:
64 date2 = time.asctime()
64 date2 = time.asctime()
65 if not node1:
65 if not node1:
66 node1 = repo.current
66 node1 = repo.current
67 (c, a, d) = repo.diffdir(repo.root, node1)
67 (c, a, d) = repo.diffdir(repo.root, node1)
68 def read(f): return file(os.path.join(repo.root, f)).read()
68 def read(f): return file(os.path.join(repo.root, f)).read()
69
69
70 change = repo.changelog.read(node1)
70 change = repo.changelog.read(node1)
71 mmap = repo.manifest.read(change[0])
71 mmap = repo.manifest.read(change[0])
72 date1 = date(change)
72 date1 = date(change)
73
73
74 if files:
74 if files:
75 (c, a, d) = map(lambda x: filterfiles(x, files), (c, a, d))
75 (c, a, d) = map(lambda x: filterfiles(x, files), (c, a, d))
76
76
77 for f in c:
77 for f in c:
78 to = repo.file(f).read(mmap[f])
78 to = repo.file(f).read(mmap[f])
79 tn = read(f)
79 tn = read(f)
80 sys.stdout.write(mdiff.unidiff(to, date1, tn, date2, f))
80 sys.stdout.write(mdiff.unidiff(to, date1, tn, date2, f))
81 for f in a:
81 for f in a:
82 to = ""
82 to = ""
83 tn = read(f)
83 tn = read(f)
84 sys.stdout.write(mdiff.unidiff(to, date1, tn, date2, f))
84 sys.stdout.write(mdiff.unidiff(to, date1, tn, date2, f))
85 for f in d:
85 for f in d:
86 to = repo.file(f).read(mmap[f])
86 to = repo.file(f).read(mmap[f])
87 tn = ""
87 tn = ""
88 sys.stdout.write(mdiff.unidiff(to, date1, tn, date2, f))
88 sys.stdout.write(mdiff.unidiff(to, date1, tn, date2, f))
89
89
90 options = {}
90 options = {}
91 opts = [('v', 'verbose', None, 'verbose'),
91 opts = [('v', 'verbose', None, 'verbose'),
92 ('d', 'debug', None, 'debug'),
92 ('d', 'debug', None, 'debug'),
93 ('q', 'quiet', None, 'quiet')]
93 ('q', 'quiet', None, 'quiet')]
94
94
95 args = fancyopts.fancyopts(sys.argv[1:], opts, options,
95 args = fancyopts.fancyopts(sys.argv[1:], opts, options,
96 'hg [options] <command> [command options] [files]')
96 'hg [options] <command> [command options] [files]')
97
97
98 try:
98 try:
99 cmd = args[0]
99 cmd = args[0]
100 args = args[1:]
100 args = args[1:]
101 except:
101 except:
102 cmd = ""
102 cmd = ""
103
103
104 ui = hg.ui(options["verbose"], options["debug"], options["quiet"])
104 ui = hg.ui(options["verbose"], options["debug"], options["quiet"])
105
105
106 if cmd == "init":
106 if cmd == "init":
107 repo = hg.repository(ui, ".", create=1)
107 repo = hg.repository(ui, ".", create=1)
108 sys.exit(0)
108 sys.exit(0)
109 elif cmd == "branch" or cmd == "clone":
109 elif cmd == "branch" or cmd == "clone":
110 os.system("cp -al %s/.hg .hg" % args[0])
110 os.system("cp -al %s/.hg .hg" % args[0])
111 sys.exit(0)
111 sys.exit(0)
112 elif cmd == "help":
112 elif cmd == "help":
113 help()
113 help()
114 sys.exit(0)
114 sys.exit(0)
115 else:
115 else:
116 try:
116 try:
117 repo = hg.repository(ui=ui)
117 repo = hg.repository(ui=ui)
118 except IOError:
118 except IOError:
119 ui.warn("Unable to open repository\n")
119 ui.warn("Unable to open repository\n")
120 sys.exit(0)
120 sys.exit(0)
121
121
122 if cmd == "checkout" or cmd == "co":
122 if cmd == "checkout" or cmd == "co":
123 node = repo.changelog.tip()
123 node = repo.changelog.tip()
124 if args:
124 if args:
125 node = repo.lookup(args[0])
125 node = repo.lookup(args[0])
126 repo.checkout(node)
126 repo.checkout(node)
127
127
128 elif cmd == "add":
128 elif cmd == "add":
129 repo.add(args)
129 repo.add(args)
130
130
131 elif cmd == "remove" or cmd == "rm" or cmd == "del" or cmd == "delete":
131 elif cmd == "remove" or cmd == "rm" or cmd == "del" or cmd == "delete":
132 repo.remove(args)
132 repo.remove(args)
133
133
134 elif cmd == "commit" or cmd == "checkin" or cmd == "ci":
134 elif cmd == "commit" or cmd == "checkin" or cmd == "ci":
135 if 1:
135 if 1:
136 if len(args) > 0:
136 if len(args) > 0:
137 repo.commit(repo.current, args)
137 repo.commit(repo.current, args)
138 else:
138 else:
139 repo.commit(repo.current)
139 repo.commit(repo.current)
140
140
141 elif cmd == "import" or cmd == "patch":
141 elif cmd == "import" or cmd == "patch":
142 try:
142 try:
143 import psyco
143 import psyco
144 psyco.full()
144 psyco.full()
145 except:
145 except:
146 pass
146 pass
147
147
148 ioptions = {}
148 ioptions = {}
149 opts = [('p', 'strip', 1, 'path strip'),
149 opts = [('p', 'strip', 1, 'path strip'),
150 ('b', 'base', "", 'base path'),
150 ('b', 'base', "", 'base path'),
151 ('q', 'quiet', "", 'silence diff')
151 ('q', 'quiet', "", 'silence diff')
152 ]
152 ]
153
153
154 args = fancyopts.fancyopts(args, opts, ioptions,
154 args = fancyopts.fancyopts(args, opts, ioptions,
155 'hg import [options] <patch names>')
155 'hg import [options] <patch names>')
156 d = ioptions["base"]
156 d = ioptions["base"]
157 strip = ioptions["strip"]
157 strip = ioptions["strip"]
158 quiet = ioptions["quiet"] and "> /dev/null" or ""
158 quiet = ioptions["quiet"] and "> /dev/null" or ""
159
159
160 for patch in args:
160 for patch in args:
161 ui.status("applying %s\n" % patch)
161 ui.status("applying %s\n" % patch)
162 pf = os.path.join(d, patch)
162 pf = os.path.join(d, patch)
163
163
164 text = ""
164 text = ""
165 for l in file(pf):
165 for l in file(pf):
166 if l[:4] == "--- ": break
166 if l[:4] == "--- ": break
167 text += l
167 text += l
168
168
169 f = os.popen("lsdiff --strip %d %s" % (strip, pf))
169 f = os.popen("lsdiff --strip %d %s" % (strip, pf))
170 files = filter(None, map(lambda x: x.rstrip(), f.read().splitlines()))
170 files = filter(None, map(lambda x: x.rstrip(), f.read().splitlines()))
171 f.close()
171 f.close()
172
172
173 if files:
173 if files:
174 if os.system("patch -p%d < %s %s" % (strip, pf, quiet)):
174 if os.system("patch -p%d < %s %s" % (strip, pf, quiet)):
175 raise "patch failed!"
175 raise "patch failed!"
176 repo.commit(repo.current, files, text)
176 repo.commit(repo.current, files, text)
177
177
178 elif cmd == "status":
178 elif cmd == "status":
179 (c, a, d) = repo.diffdir(repo.root, repo.current)
179 (c, a, d) = repo.diffdir(repo.root, repo.current)
180 for f in c: ui.status("C %s\n" % f)
180 for f in c: ui.status("C %s\n" % f)
181 for f in a: ui.status("? %s\n" % f)
181 for f in a: ui.status("? %s\n" % f)
182 for f in d: ui.status("R %s\n" % f)
182 for f in d: ui.status("R %s\n" % f)
183
183
184 elif cmd == "diff":
184 elif cmd == "diff":
185 revs = []
185 revs = []
186
186
187 if args:
187 if args:
188 doptions = {}
188 doptions = {}
189 opts = [('r', 'revision', [], 'revision')]
189 opts = [('r', 'revision', [], 'revision')]
190 args = fancyopts.fancyopts(args, opts, doptions,
190 args = fancyopts.fancyopts(args, opts, doptions,
191 'hg diff [options] [files]')
191 'hg diff [options] [files]')
192 revs = map(lambda x: repo.lookup(x), doptions['revision'])
192 revs = map(lambda x: repo.lookup(x), doptions['revision'])
193
193
194 if len(revs) > 2:
194 if len(revs) > 2:
195 self.ui.warn("too many revisions to diff\n")
195 self.ui.warn("too many revisions to diff\n")
196 sys.exit(1)
196 sys.exit(1)
197
197
198 if os.getcwd() != repo.root:
198 if os.getcwd() != repo.root:
199 relpath = os.getcwd()[len(repo.root) + 1: ]
199 relpath = os.getcwd()[len(repo.root) + 1: ]
200 if not args: args = [ relpath ]
200 if not args: args = [ relpath ]
201 else: args = [ os.path.join(relpath, x) for x in args ]
201 else: args = [ os.path.join(relpath, x) for x in args ]
202
202
203 diff(args, *revs)
203 diff(args, *revs)
204
204
205 elif cmd == "annotate":
205 elif cmd == "annotate":
206 aoptions = {}
206 aoptions = {}
207 opts = [('r', 'revision', '', 'revision')]
207 opts = [('r', 'revision', '', 'revision')]
208 args = fancyopts.fancyopts(args, opts, aoptions,
208 args = fancyopts.fancyopts(args, opts, aoptions,
209 'hg annotate [-r id] [files]')
209 'hg annotate [-r id] [files]')
210 if args:
210 if args:
211 node = repo.current
211 node = repo.current
212 if aoptions['revision']:
212 if aoptions['revision']:
213 node = repo.changelog.lookup(aoptions['revision'])
213 node = repo.changelog.lookup(aoptions['revision'])
214 change = repo.changelog.read(node)
214 change = repo.changelog.read(node)
215 mmap = repo.manifest.read(change[0])
215 mmap = repo.manifest.read(change[0])
216 for f in args:
216 for f in args:
217 for n, l in repo.file(f).annotate(mmap[f]):
217 for n, l in repo.file(f).annotate(mmap[f]):
218 sys.stdout.write("% 6s:%s"%(n, l))
218 sys.stdout.write("% 6s:%s"%(n, l))
219
219
220 elif cmd == "blame":
220 elif cmd == "blame":
221 aoptions = {}
221 aoptions = {}
222 opts = [('r', 'revision', '', 'revision')]
222 opts = [('r', 'revision', '', 'revision')]
223 args = fancyopts.fancyopts(args, opts, aoptions,
223 args = fancyopts.fancyopts(args, opts, aoptions,
224 'hg blame [-r id] [files]')
224 'hg blame [-r id] [files]')
225 if args:
225 if args:
226 bcache = {}
226 bcache = {}
227 node = repo.current
227 node = repo.current
228 if aoptions['revision']:
228 if aoptions['revision']:
229 node = repo.changelog.lookup(aoptions['revision'])
229 node = repo.changelog.lookup(aoptions['revision'])
230 change = repo.changelog.read(node)
230 change = repo.changelog.read(node)
231 mmap = repo.manifest.read(change[0])
231 mmap = repo.manifest.read(change[0])
232 for f in args:
232 for f in args:
233 for n, l in repo.file(f).annotate(mmap[f]):
233 for n, l in repo.file(f).annotate(mmap[f]):
234 try:
234 try:
235 name = bcache[n]
235 name = bcache[n]
236 except KeyError:
236 except KeyError:
237 cl = repo.changelog.read(repo.changelog.node(n))
237 cl = repo.changelog.read(repo.changelog.node(n))
238 name = cl[1]
238 name = cl[1]
239 f = name.find('@')
239 f = name.find('@')
240 if f >= 0:
240 if f >= 0:
241 name = name[:f]
241 name = name[:f]
242 bcache[n] = name
242 bcache[n] = name
243 sys.stdout.write("% 10s:%s"%(name, l))
243 sys.stdout.write("% 10s:%s"%(name, l))
244
244
245 elif cmd == "export":
245 elif cmd == "export":
246 node = repo.lookup(args[0])
246 node = repo.lookup(args[0])
247 prev, other = repo.changelog.parents(node)
247 prev, other = repo.changelog.parents(node)
248 change = repo.changelog.read(node)
248 change = repo.changelog.read(node)
249 print "# HG changeset patch"
249 print "# HG changeset patch"
250 print "# User %s" % change[1]
250 print "# User %s" % change[1]
251 print "# Node ID %s" % hg.hex(node)
251 print "# Node ID %s" % hg.hex(node)
252 print "# Parent %s" % hg.hex(prev)
252 print "# Parent %s" % hg.hex(prev)
253 print
253 print
254 if other != hg.nullid:
254 if other != hg.nullid:
255 print "# Parent %s" % hg.hex(other)
255 print "# Parent %s" % hg.hex(other)
256 print change[4]
256 print change[4]
257
257
258 diff(None, prev, node)
258 diff(None, prev, node)
259
259
260 elif cmd == "debugchangegroup":
260 elif cmd == "debugchangegroup":
261 newer = repo.newer(map(repo.lookup, args))
261 newer = repo.newer(map(repo.lookup, args))
262 for chunk in repo.changegroup(newer):
262 for chunk in repo.changegroup(newer):
263 sys.stdout.write(chunk)
263 sys.stdout.write(chunk)
264
264
265 elif cmd == "debugaddchangegroup":
265 elif cmd == "debugaddchangegroup":
266 data = sys.stdin.read()
266 data = sys.stdin.read()
267 repo.addchangegroup(data)
267 repo.addchangegroup(data)
268
268
269 elif cmd == "addremove":
269 elif cmd == "addremove":
270 (c, a, d) = repo.diffdir(repo.root, repo.current)
270 (c, a, d) = repo.diffdir(repo.root, repo.current)
271 repo.add(a)
271 repo.add(a)
272 repo.remove(d)
272 repo.remove(d)
273
273
274 elif cmd == "history":
274 elif cmd == "history":
275 for i in range(repo.changelog.count()):
275 for i in range(repo.changelog.count()):
276 n = repo.changelog.node(i)
276 n = repo.changelog.node(i)
277 changes = repo.changelog.read(n)
277 changes = repo.changelog.read(n)
278 (p1, p2) = repo.changelog.parents(n)
278 (p1, p2) = repo.changelog.parents(n)
279 (h, h1, h2) = map(hg.hex, (n, p1, p2))
279 (h, h1, h2) = map(hg.hex, (n, p1, p2))
280 (i1, i2) = map(repo.changelog.rev, (p1, p2))
280 (i1, i2) = map(repo.changelog.rev, (p1, p2))
281 print "rev: %4d:%s" % (i, h)
281 print "rev: %4d:%s" % (i, h)
282 print "parents: %4d:%s" % (i1, h1)
282 print "parents: %4d:%s" % (i1, h1)
283 if i2: print " %4d:%s" % (i2, h2)
283 if i2: print " %4d:%s" % (i2, h2)
284 print "manifest: %4d:%s" % (repo.manifest.rev(changes[0]),
284 print "manifest: %4d:%s" % (repo.manifest.rev(changes[0]),
285 hg.hex(changes[0]))
285 hg.hex(changes[0]))
286 print "user:", changes[1]
286 print "user:", changes[1]
287 print "date:", time.asctime(
287 print "date:", time.asctime(
288 time.localtime(float(changes[2].split(' ')[0])))
288 time.localtime(float(changes[2].split(' ')[0])))
289 print "files:", " ".join(changes[3])
289 print "files:", " ".join(changes[3])
290 print "description:"
290 print "description:"
291 print changes[4]
291 print changes[4]
292
292
293 elif cmd == "tip":
293 elif cmd == "tip":
294 n = repo.changelog.tip()
294 n = repo.changelog.tip()
295 t = repo.changelog.rev(n)
295 t = repo.changelog.rev(n)
296 ui.status("%d:%s\n" % (t, hg.hex(n)))
296 ui.status("%d:%s\n" % (t, hg.hex(n)))
297
297
298 elif cmd == "log":
298 elif cmd == "log":
299 if args:
299 if args:
300 r = repo.file(args[0])
300 r = repo.file(args[0])
301 for i in range(r.count()):
301 for i in range(r.count()):
302 n = r.node(i)
302 n = r.node(i)
303 (p1, p2) = r.parents(n)
303 (p1, p2) = r.parents(n)
304 (h, h1, h2) = map(hg.hex, (n, p1, p2))
304 (h, h1, h2) = map(hg.hex, (n, p1, p2))
305 (i1, i2) = map(r.rev, (p1, p2))
305 (i1, i2) = map(r.rev, (p1, p2))
306 cr = r.linkrev(n)
306 cr = r.linkrev(n)
307 cn = hg.hex(repo.changelog.node(cr))
307 cn = hg.hex(repo.changelog.node(cr))
308 print "rev: %4d:%s" % (i, h)
308 print "rev: %4d:%s" % (i, h)
309 print "changeset: %4d:%s" % (cr, cn)
309 print "changeset: %4d:%s" % (cr, cn)
310 print "parents: %4d:%s" % (i1, h1)
310 print "parents: %4d:%s" % (i1, h1)
311 if i2: print " %4d:%s" % (i2, h2)
311 if i2: print " %4d:%s" % (i2, h2)
312 else:
312 else:
313 print "missing filename"
313 print "missing filename"
314
314
315 elif cmd == "dump":
315 elif cmd == "dump":
316 if args:
316 if args:
317 r = repo.file(args[0])
317 r = repo.file(args[0])
318 n = r.tip()
318 n = r.tip()
319 if len(args) > 1: n = r.lookup(args[1])
319 if len(args) > 1: n = r.lookup(args[1])
320 sys.stdout.write(r.read(n))
320 sys.stdout.write(r.read(n))
321 else:
321 else:
322 print "missing filename"
322 print "missing filename"
323
323
324 elif cmd == "dumpmanifest":
324 elif cmd == "dumpmanifest":
325 n = repo.manifest.tip()
325 n = repo.manifest.tip()
326 if len(args) > 0:
326 if len(args) > 0:
327 n = repo.manifest.lookup(args[0])
327 n = repo.manifest.lookup(args[0])
328 m = repo.manifest.read(n)
328 m = repo.manifest.read(n)
329 files = m.keys()
329 files = m.keys()
330 files.sort()
330 files.sort()
331
331
332 for f in files:
332 for f in files:
333 print hg.hex(m[f]), f
333 print hg.hex(m[f]), f
334
334
335 elif cmd == "debughash":
335 elif cmd == "debughash":
336 f = repo.file(args[0])
336 f = repo.file(args[0])
337 print f.encodepath(args[0])
337 print f.encodepath(args[0])
338
338
339 elif cmd == "debugindex":
339 elif cmd == "debugindex":
340 if ".hg" not in args[0]:
340 if ".hg" not in args[0]:
341 args[0] = ".hg/data/" + repo.file(args[0]).encodepath(args[0]) + "i"
341 args[0] = ".hg/data/" + repo.file(args[0]).encodepath(args[0]) + "i"
342
342
343 r = hg.revlog(open, args[0], "")
343 r = hg.revlog(open, args[0], "")
344 print " rev offset length base linkrev"+\
344 print " rev offset length base linkrev"+\
345 " p1 p2 nodeid"
345 " p1 p2 nodeid"
346 for i in range(r.count()):
346 for i in range(r.count()):
347 e = r.index[i]
347 e = r.index[i]
348 print "% 6d % 9d % 7d % 6d % 7d %s.. %s.. %s.." % (
348 print "% 6d % 9d % 7d % 6d % 7d %s.. %s.. %s.." % (
349 i, e[0], e[1], e[2], e[3],
349 i, e[0], e[1], e[2], e[3],
350 hg.hex(e[4][:5]), hg.hex(e[5][:5]), hg.hex(e[6][:5]))
350 hg.hex(e[4][:5]), hg.hex(e[5][:5]), hg.hex(e[6][:5]))
351
351
352 elif cmd == "debugindexdot":
353 if ".hg" not in args[0]:
354 args[0] = ".hg/data/" + repo.file(args[0]).encodepath(args[0]) + "i"
355
356 r = hg.revlog(open, args[0], "")
357 print "digraph G {"
358 for i in range(r.count()):
359 e = r.index[i]
360 print "\t%d -> %d" % (r.rev(e[4]), i)
361 if e[5] != hg.nullid:
362 print "\t%d -> %d" % (r.rev(e[5]), i)
363 print "}"
364
352 elif cmd == "merge":
365 elif cmd == "merge":
353 if args:
366 if args:
354 other = hg.repository(ui, args[0])
367 other = hg.repository(ui, args[0])
355 ui.status("requesting changegroup\n")
368 ui.status("requesting changegroup\n")
356 cg = repo.getchangegroup(other)
369 cg = repo.getchangegroup(other)
357 repo.addchangegroup(cg)
370 repo.addchangegroup(cg)
358 else:
371 else:
359 print "missing source repository"
372 print "missing source repository"
360
373
361 elif cmd == "tags":
374 elif cmd == "tags":
362 repo.lookup(0) # prime the cache
375 repo.lookup(0) # prime the cache
363 i = repo.tags.items()
376 i = repo.tags.items()
364 i.sort()
377 i.sort()
365 for k, n in i:
378 for k, n in i:
366 try:
379 try:
367 r = repo.changelog.rev(n)
380 r = repo.changelog.rev(n)
368 except KeyError:
381 except KeyError:
369 r = "?"
382 r = "?"
370 print "%-30s %5d:%s" % (k, repo.changelog.rev(n), hg.hex(n))
383 print "%-30s %5d:%s" % (k, repo.changelog.rev(n), hg.hex(n))
371
384
372 elif cmd == "debugoldmerge":
385 elif cmd == "debugoldmerge":
373 if args:
386 if args:
374 other = hg.repository(ui, args[0])
387 other = hg.repository(ui, args[0])
375 repo.merge(other)
388 repo.merge(other)
376 else:
389 else:
377 print "missing source repository"
390 print "missing source repository"
378
391
379 elif cmd == "verify":
392 elif cmd == "verify":
380 filelinkrevs = {}
393 filelinkrevs = {}
381 filenodes = {}
394 filenodes = {}
382 manifestchangeset = {}
395 manifestchangeset = {}
383 changesets = revisions = files = 0
396 changesets = revisions = files = 0
384 errors = 0
397 errors = 0
385
398
386 ui.status("checking changesets\n")
399 ui.status("checking changesets\n")
387 for i in range(repo.changelog.count()):
400 for i in range(repo.changelog.count()):
388 changesets += 1
401 changesets += 1
389 n = repo.changelog.node(i)
402 n = repo.changelog.node(i)
390 for p in repo.changelog.parents(n):
403 for p in repo.changelog.parents(n):
391 if p not in repo.changelog.nodemap:
404 if p not in repo.changelog.nodemap:
392 ui.warn("changeset %s has unknown parent %s\n" %
405 ui.warn("changeset %s has unknown parent %s\n" %
393 (hg.short(n), hg.short(p)))
406 (hg.short(n), hg.short(p)))
394 errors += 1
407 errors += 1
395 try:
408 try:
396 changes = repo.changelog.read(n)
409 changes = repo.changelog.read(n)
397 except Error, inst:
410 except Error, inst:
398 ui.warn("unpacking changeset %s: %s\n" % (short(n), inst))
411 ui.warn("unpacking changeset %s: %s\n" % (short(n), inst))
399 errors += 1
412 errors += 1
400
413
401 manifestchangeset[changes[0]] = n
414 manifestchangeset[changes[0]] = n
402 for f in changes[3]:
415 for f in changes[3]:
403 revisions += 1
416 revisions += 1
404 filelinkrevs.setdefault(f, []).append(i)
417 filelinkrevs.setdefault(f, []).append(i)
405
418
406 ui.status("checking manifests\n")
419 ui.status("checking manifests\n")
407 for i in range(repo.manifest.count()):
420 for i in range(repo.manifest.count()):
408 n = repo.manifest.node(i)
421 n = repo.manifest.node(i)
409 for p in repo.manifest.parents(n):
422 for p in repo.manifest.parents(n):
410 if p not in repo.manifest.nodemap:
423 if p not in repo.manifest.nodemap:
411 ui.warn("manifest %s has unknown parent %s\n" %
424 ui.warn("manifest %s has unknown parent %s\n" %
412 (hg.short(n), hg.short(p)))
425 (hg.short(n), hg.short(p)))
413 errors += 1
426 errors += 1
414 ca = repo.changelog.node(repo.manifest.linkrev(n))
427 ca = repo.changelog.node(repo.manifest.linkrev(n))
415 cc = manifestchangeset[n]
428 cc = manifestchangeset[n]
416 if ca != cc:
429 if ca != cc:
417 ui.warn("manifest %s points to %s, not %s\n" %
430 ui.warn("manifest %s points to %s, not %s\n" %
418 (hg.hex(n), hg.hex(ca), hg.hex(cc)))
431 (hg.hex(n), hg.hex(ca), hg.hex(cc)))
419 errors += 1
432 errors += 1
420
433
421 try:
434 try:
422 m = repo.manifest.read(n)
435 m = repo.manifest.read(n)
423 except Error, inst:
436 except Error, inst:
424 ui.warn("unpacking manifest %s: %s\n" % (hg.short(n), inst))
437 ui.warn("unpacking manifest %s: %s\n" % (hg.short(n), inst))
425 errors += 1
438 errors += 1
426
439
427 for f, fn in m.items():
440 for f, fn in m.items():
428 filenodes.setdefault(f, {})[fn] = 1
441 filenodes.setdefault(f, {})[fn] = 1
429
442
430 ui.status("crosschecking files in changesets and manifests\n")
443 ui.status("crosschecking files in changesets and manifests\n")
431 for f in filenodes:
444 for f in filenodes:
432 if f not in filelinkrevs:
445 if f not in filelinkrevs:
433 ui.warn("file %s in manifest but not in changesets\n" % f)
446 ui.warn("file %s in manifest but not in changesets\n" % f)
434 errors += 1
447 errors += 1
435
448
436 for f in filelinkrevs:
449 for f in filelinkrevs:
437 if f not in filenodes:
450 if f not in filenodes:
438 ui.warn("file %s in changeset but not in manifest" % f)
451 ui.warn("file %s in changeset but not in manifest" % f)
439 errors += 1
452 errors += 1
440
453
441 ui.status("checking files\n")
454 ui.status("checking files\n")
442 for f in filenodes:
455 for f in filenodes:
443 files += 1
456 files += 1
444 fl = repo.file(f)
457 fl = repo.file(f)
445 nodes = { hg.nullid: 1 }
458 nodes = { hg.nullid: 1 }
446 for i in range(fl.count()):
459 for i in range(fl.count()):
447 n = fl.node(i)
460 n = fl.node(i)
448
461
449 if n not in filenodes[f]:
462 if n not in filenodes[f]:
450 ui.warn("%s:%s not in manifests\n" % (f, hg.short(n)))
463 ui.warn("%s:%s not in manifests\n" % (f, hg.short(n)))
451 errors += 1
464 errors += 1
452 else:
465 else:
453 del filenodes[f][n]
466 del filenodes[f][n]
454
467
455 flr = fl.linkrev(n)
468 flr = fl.linkrev(n)
456 if flr not in filelinkrevs[f]:
469 if flr not in filelinkrevs[f]:
457 ui.warn("%s:%s points to unexpected changeset rev %d\n"
470 ui.warn("%s:%s points to unexpected changeset rev %d\n"
458 % (f, hg.short(n), fl.linkrev(n)))
471 % (f, hg.short(n), fl.linkrev(n)))
459 errors += 1
472 errors += 1
460 else:
473 else:
461 filelinkrevs[f].remove(flr)
474 filelinkrevs[f].remove(flr)
462
475
463 # verify contents
476 # verify contents
464 try:
477 try:
465 t = fl.read(n)
478 t = fl.read(n)
466 except Error, inst:
479 except Error, inst:
467 ui.warn("unpacking file %s %s: %s\n" % (f, short(n), inst))
480 ui.warn("unpacking file %s %s: %s\n" % (f, short(n), inst))
468 errors += 1
481 errors += 1
469
482
470 # verify parents
483 # verify parents
471 (p1, p2) = fl.parents(n)
484 (p1, p2) = fl.parents(n)
472 if p1 not in nodes:
485 if p1 not in nodes:
473 ui.warn("file %s:%s unknown parent 1 %s" %
486 ui.warn("file %s:%s unknown parent 1 %s" %
474 (f, hg.short(n), hg.short(p1)))
487 (f, hg.short(n), hg.short(p1)))
475 errors += 1
488 errors += 1
476 if p2 not in nodes:
489 if p2 not in nodes:
477 ui.warn("file %s:%s unknown parent 2 %s" %
490 ui.warn("file %s:%s unknown parent 2 %s" %
478 (f, hg.short(n), hg.short(p1)))
491 (f, hg.short(n), hg.short(p1)))
479 errors += 1
492 errors += 1
480 nodes[n] = 1
493 nodes[n] = 1
481
494
482 # cross-check
495 # cross-check
483 for flr in filelinkrevs[f]:
496 for flr in filelinkrevs[f]:
484 ui.warn("changeset rev %d not in %s\n" % (flr, f))
497 ui.warn("changeset rev %d not in %s\n" % (flr, f))
485 errors += 1
498 errors += 1
486
499
487 for node in filenodes[f]:
500 for node in filenodes[f]:
488 ui.warn("node %s in manifests not in %s\n" % (hg.hex(n), f))
501 ui.warn("node %s in manifests not in %s\n" % (hg.hex(n), f))
489 errors += 1
502 errors += 1
490
503
491 ui.status("%d files, %d changesets, %d total revisions\n" %
504 ui.status("%d files, %d changesets, %d total revisions\n" %
492 (files, changesets, revisions))
505 (files, changesets, revisions))
493
506
494 if errors:
507 if errors:
495 ui.warn("%d integrity errors encountered!\n")
508 ui.warn("%d integrity errors encountered!\n")
496 sys.exit(1)
509 sys.exit(1)
497
510
498 else:
511 else:
499 print "unknown command\n"
512 print "unknown command\n"
500 help()
513 help()
501 sys.exit(1)
514 sys.exit(1)
General Comments 0
You need to be logged in to leave comments. Login now