##// END OF EJS Templates
Use revlog.delta and mdiff.patchtext to massively speed up processing...
mpm@selenic.com -
r121:66fb61d9 default
parent child Browse files
Show More
@@ -1,536 +1,544 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 = filterfiles(c, files)
75 c = filterfiles(c, files)
76 d = filterfiles(d, files)
76 d = filterfiles(d, files)
77
77
78 for f in c:
78 for f in c:
79 to = repo.file(f).read(mmap[f])
79 to = repo.file(f).read(mmap[f])
80 tn = read(f)
80 tn = read(f)
81 sys.stdout.write(mdiff.unidiff(to, date1, tn, date2, f))
81 sys.stdout.write(mdiff.unidiff(to, date1, tn, date2, f))
82 for f in d:
82 for f in d:
83 to = repo.file(f).read(mmap[f])
83 to = repo.file(f).read(mmap[f])
84 tn = ""
84 tn = ""
85 sys.stdout.write(mdiff.unidiff(to, date1, tn, date2, f))
85 sys.stdout.write(mdiff.unidiff(to, date1, tn, date2, f))
86
86
87 options = {}
87 options = {}
88 opts = [('v', 'verbose', None, 'verbose'),
88 opts = [('v', 'verbose', None, 'verbose'),
89 ('d', 'debug', None, 'debug'),
89 ('d', 'debug', None, 'debug'),
90 ('q', 'quiet', None, 'quiet'),
90 ('q', 'quiet', None, 'quiet'),
91 ('y', 'noninteractive', None, 'run non-interactively'),
91 ('y', 'noninteractive', None, 'run non-interactively'),
92 ]
92 ]
93
93
94 args = fancyopts.fancyopts(sys.argv[1:], opts, options,
94 args = fancyopts.fancyopts(sys.argv[1:], opts, options,
95 'hg [options] <command> [command options] [files]')
95 'hg [options] <command> [command options] [files]')
96
96
97 try:
97 try:
98 cmd = args[0]
98 cmd = args[0]
99 args = args[1:]
99 args = args[1:]
100 except:
100 except:
101 cmd = ""
101 cmd = ""
102
102
103 ui = hg.ui(options["verbose"], options["debug"], options["quiet"],
103 ui = hg.ui(options["verbose"], options["debug"], options["quiet"],
104 not options["noninteractive"])
104 not options["noninteractive"])
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 relpath = None
122 relpath = None
123 if os.getcwd() != repo.root:
123 if os.getcwd() != repo.root:
124 relpath = os.getcwd()[len(repo.root) + 1: ]
124 relpath = os.getcwd()[len(repo.root) + 1: ]
125
125
126 if cmd == "checkout" or cmd == "co":
126 if cmd == "checkout" or cmd == "co":
127 node = repo.changelog.tip()
127 node = repo.changelog.tip()
128 if args:
128 if args:
129 node = repo.lookup(args[0])
129 node = repo.lookup(args[0])
130 repo.checkout(node)
130 repo.checkout(node)
131
131
132 elif cmd == "add":
132 elif cmd == "add":
133 repo.add(args)
133 repo.add(args)
134
134
135 elif cmd == "remove" or cmd == "rm" or cmd == "del" or cmd == "delete":
135 elif cmd == "remove" or cmd == "rm" or cmd == "del" or cmd == "delete":
136 repo.remove(args)
136 repo.remove(args)
137
137
138 elif cmd == "commit" or cmd == "checkin" or cmd == "ci":
138 elif cmd == "commit" or cmd == "checkin" or cmd == "ci":
139 if 1:
139 if 1:
140 if len(args) > 0:
140 if len(args) > 0:
141 repo.commit(repo.current, args)
141 repo.commit(repo.current, args)
142 else:
142 else:
143 repo.commit(repo.current)
143 repo.commit(repo.current)
144
144
145 elif cmd == "import" or cmd == "patch":
145 elif cmd == "import" or cmd == "patch":
146 try:
146 try:
147 import psyco
147 import psyco
148 psyco.full()
148 psyco.full()
149 except:
149 except:
150 pass
150 pass
151
151
152 ioptions = {}
152 ioptions = {}
153 opts = [('p', 'strip', 1, 'path strip'),
153 opts = [('p', 'strip', 1, 'path strip'),
154 ('b', 'base', "", 'base path'),
154 ('b', 'base', "", 'base path'),
155 ('q', 'quiet', "", 'silence diff')
155 ('q', 'quiet', "", 'silence diff')
156 ]
156 ]
157
157
158 args = fancyopts.fancyopts(args, opts, ioptions,
158 args = fancyopts.fancyopts(args, opts, ioptions,
159 'hg import [options] <patch names>')
159 'hg import [options] <patch names>')
160 d = ioptions["base"]
160 d = ioptions["base"]
161 strip = ioptions["strip"]
161 strip = ioptions["strip"]
162 quiet = ioptions["quiet"] and "> /dev/null" or ""
162 quiet = ioptions["quiet"] and "> /dev/null" or ""
163
163
164 for patch in args:
164 for patch in args:
165 ui.status("applying %s\n" % patch)
165 ui.status("applying %s\n" % patch)
166 pf = os.path.join(d, patch)
166 pf = os.path.join(d, patch)
167
167
168 text = ""
168 text = ""
169 for l in file(pf):
169 for l in file(pf):
170 if l[:4] == "--- ": break
170 if l[:4] == "--- ": break
171 text += l
171 text += l
172
172
173 f = os.popen("lsdiff --strip %d %s" % (strip, pf))
173 f = os.popen("lsdiff --strip %d %s" % (strip, pf))
174 files = filter(None, map(lambda x: x.rstrip(), f.read().splitlines()))
174 files = filter(None, map(lambda x: x.rstrip(), f.read().splitlines()))
175 f.close()
175 f.close()
176
176
177 if files:
177 if files:
178 if os.system("patch -p%d < %s %s" % (strip, pf, quiet)):
178 if os.system("patch -p%d < %s %s" % (strip, pf, quiet)):
179 raise "patch failed!"
179 raise "patch failed!"
180 repo.commit(repo.current, files, text)
180 repo.commit(repo.current, files, text)
181
181
182 elif cmd == "status":
182 elif cmd == "status":
183 (c, a, d) = repo.diffdir(repo.root, repo.current)
183 (c, a, d) = repo.diffdir(repo.root, repo.current)
184 if relpath:
184 if relpath:
185 (c, a, d) = map(lambda x: filterfiles(x, [ relpath ]), (c, a, d))
185 (c, a, d) = map(lambda x: filterfiles(x, [ relpath ]), (c, a, d))
186
186
187 for f in c: print "C", f
187 for f in c: print "C", f
188 for f in a: print "?", f
188 for f in a: print "?", f
189 for f in d: print "R", f
189 for f in d: print "R", f
190
190
191 elif cmd == "diff":
191 elif cmd == "diff":
192 revs = []
192 revs = []
193
193
194 if args:
194 if args:
195 doptions = {}
195 doptions = {}
196 opts = [('r', 'revision', [], 'revision')]
196 opts = [('r', 'revision', [], 'revision')]
197 args = fancyopts.fancyopts(args, opts, doptions,
197 args = fancyopts.fancyopts(args, opts, doptions,
198 'hg diff [options] [files]')
198 'hg diff [options] [files]')
199 revs = map(lambda x: repo.lookup(x), doptions['revision'])
199 revs = map(lambda x: repo.lookup(x), doptions['revision'])
200
200
201 if len(revs) > 2:
201 if len(revs) > 2:
202 self.ui.warn("too many revisions to diff\n")
202 self.ui.warn("too many revisions to diff\n")
203 sys.exit(1)
203 sys.exit(1)
204
204
205 if relpath:
205 if relpath:
206 if not args: args = [ relpath ]
206 if not args: args = [ relpath ]
207 else: args = [ os.path.join(relpath, x) for x in args ]
207 else: args = [ os.path.join(relpath, x) for x in args ]
208
208
209 diff(args, *revs)
209 diff(args, *revs)
210
210
211 elif cmd == "annotate":
211 elif cmd == "annotate":
212 aoptions = {}
212 aoptions = {}
213 opts = [('r', 'revision', '', 'revision')]
213 opts = [('r', 'revision', '', 'revision')]
214 args = fancyopts.fancyopts(args, opts, aoptions,
214 args = fancyopts.fancyopts(args, opts, aoptions,
215 'hg annotate [-r id] [files]')
215 'hg annotate [-r id] [files]')
216 if args:
216 if args:
217 node = repo.current
217 node = repo.current
218 if aoptions['revision']:
218 if aoptions['revision']:
219 node = repo.changelog.lookup(aoptions['revision'])
219 node = repo.changelog.lookup(aoptions['revision'])
220 change = repo.changelog.read(node)
220 change = repo.changelog.read(node)
221 mmap = repo.manifest.read(change[0])
221 mmap = repo.manifest.read(change[0])
222 for f in args:
222 for f in args:
223 for n, l in repo.file(f).annotate(mmap[f]):
223 for n, l in repo.file(f).annotate(mmap[f]):
224 sys.stdout.write("% 6s:%s"%(n, l))
224 sys.stdout.write("% 6s:%s"%(n, l))
225
225
226 elif cmd == "blame":
226 elif cmd == "blame":
227 aoptions = {}
227 aoptions = {}
228 opts = [('r', 'revision', '', 'revision')]
228 opts = [('r', 'revision', '', 'revision')]
229 args = fancyopts.fancyopts(args, opts, aoptions,
229 args = fancyopts.fancyopts(args, opts, aoptions,
230 'hg blame [-r id] [files]')
230 'hg blame [-r id] [files]')
231 if args:
231 if args:
232 bcache = {}
232 bcache = {}
233 node = repo.current
233 node = repo.current
234 if aoptions['revision']:
234 if aoptions['revision']:
235 node = repo.changelog.lookup(aoptions['revision'])
235 node = repo.changelog.lookup(aoptions['revision'])
236 change = repo.changelog.read(node)
236 change = repo.changelog.read(node)
237 mmap = repo.manifest.read(change[0])
237 mmap = repo.manifest.read(change[0])
238 for f in args:
238 for f in args:
239 for n, l in repo.file(f).annotate(mmap[f]):
239 for n, l in repo.file(f).annotate(mmap[f]):
240 try:
240 try:
241 name = bcache[n]
241 name = bcache[n]
242 except KeyError:
242 except KeyError:
243 cl = repo.changelog.read(repo.changelog.node(n))
243 cl = repo.changelog.read(repo.changelog.node(n))
244 name = cl[1]
244 name = cl[1]
245 f = name.find('@')
245 f = name.find('@')
246 if f >= 0:
246 if f >= 0:
247 name = name[:f]
247 name = name[:f]
248 bcache[n] = name
248 bcache[n] = name
249 sys.stdout.write("% 10s:%s"%(name, l))
249 sys.stdout.write("% 10s:%s"%(name, l))
250
250
251 elif cmd == "export":
251 elif cmd == "export":
252 node = repo.lookup(args[0])
252 node = repo.lookup(args[0])
253 prev, other = repo.changelog.parents(node)
253 prev, other = repo.changelog.parents(node)
254 change = repo.changelog.read(node)
254 change = repo.changelog.read(node)
255 print "# HG changeset patch"
255 print "# HG changeset patch"
256 print "# User %s" % change[1]
256 print "# User %s" % change[1]
257 print "# Node ID %s" % hg.hex(node)
257 print "# Node ID %s" % hg.hex(node)
258 print "# Parent %s" % hg.hex(prev)
258 print "# Parent %s" % hg.hex(prev)
259 print
259 print
260 if other != hg.nullid:
260 if other != hg.nullid:
261 print "# Parent %s" % hg.hex(other)
261 print "# Parent %s" % hg.hex(other)
262 print change[4]
262 print change[4]
263
263
264 diff(None, prev, node)
264 diff(None, prev, node)
265
265
266 elif cmd == "debugchangegroup":
266 elif cmd == "debugchangegroup":
267 newer = repo.newer(map(repo.lookup, args))
267 newer = repo.newer(map(repo.lookup, args))
268 for chunk in repo.changegroup(newer):
268 for chunk in repo.changegroup(newer):
269 sys.stdout.write(chunk)
269 sys.stdout.write(chunk)
270
270
271 elif cmd == "debugaddchangegroup":
271 elif cmd == "debugaddchangegroup":
272 data = sys.stdin.read()
272 data = sys.stdin.read()
273 repo.addchangegroup(data)
273 repo.addchangegroup(data)
274
274
275 elif cmd == "addremove":
275 elif cmd == "addremove":
276 (c, a, d) = repo.diffdir(repo.root, repo.current)
276 (c, a, d) = repo.diffdir(repo.root, repo.current)
277 repo.add(a)
277 repo.add(a)
278 repo.remove(d)
278 repo.remove(d)
279
279
280 elif cmd == "history":
280 elif cmd == "history":
281 for i in range(repo.changelog.count()):
281 for i in range(repo.changelog.count()):
282 n = repo.changelog.node(i)
282 n = repo.changelog.node(i)
283 changes = repo.changelog.read(n)
283 changes = repo.changelog.read(n)
284 (p1, p2) = repo.changelog.parents(n)
284 (p1, p2) = repo.changelog.parents(n)
285 (h, h1, h2) = map(hg.hex, (n, p1, p2))
285 (h, h1, h2) = map(hg.hex, (n, p1, p2))
286 (i1, i2) = map(repo.changelog.rev, (p1, p2))
286 (i1, i2) = map(repo.changelog.rev, (p1, p2))
287 print "rev: %4d:%s" % (i, h)
287 print "rev: %4d:%s" % (i, h)
288 print "parents: %4d:%s" % (i1, h1)
288 print "parents: %4d:%s" % (i1, h1)
289 if i2: print " %4d:%s" % (i2, h2)
289 if i2: print " %4d:%s" % (i2, h2)
290 print "manifest: %4d:%s" % (repo.manifest.rev(changes[0]),
290 print "manifest: %4d:%s" % (repo.manifest.rev(changes[0]),
291 hg.hex(changes[0]))
291 hg.hex(changes[0]))
292 print "user:", changes[1]
292 print "user:", changes[1]
293 print "date:", time.asctime(
293 print "date:", time.asctime(
294 time.localtime(float(changes[2].split(' ')[0])))
294 time.localtime(float(changes[2].split(' ')[0])))
295 print "files:", " ".join(changes[3])
295 print "files:", " ".join(changes[3])
296 print "description:"
296 print "description:"
297 print changes[4]
297 print changes[4]
298
298
299 elif cmd == "tip":
299 elif cmd == "tip":
300 n = repo.changelog.tip()
300 n = repo.changelog.tip()
301 t = repo.changelog.rev(n)
301 t = repo.changelog.rev(n)
302 ui.status("%d:%s\n" % (t, hg.hex(n)))
302 ui.status("%d:%s\n" % (t, hg.hex(n)))
303
303
304 elif cmd == "log":
304 elif cmd == "log":
305
305
306 if len(args) == 1:
306 if len(args) == 1:
307 if relpath:
307 if relpath:
308 args[0] = os.path.join(relpath, args[0])
308 args[0] = os.path.join(relpath, args[0])
309
309
310 r = repo.file(args[0])
310 r = repo.file(args[0])
311 for i in range(r.count()):
311 for i in range(r.count()):
312 n = r.node(i)
312 n = r.node(i)
313 (p1, p2) = r.parents(n)
313 (p1, p2) = r.parents(n)
314 (h, h1, h2) = map(hg.hex, (n, p1, p2))
314 (h, h1, h2) = map(hg.hex, (n, p1, p2))
315 (i1, i2) = map(r.rev, (p1, p2))
315 (i1, i2) = map(r.rev, (p1, p2))
316 cr = r.linkrev(n)
316 cr = r.linkrev(n)
317 cn = hg.hex(repo.changelog.node(cr))
317 cn = hg.hex(repo.changelog.node(cr))
318 print "rev: %4d:%s" % (i, h)
318 print "rev: %4d:%s" % (i, h)
319 print "changeset: %4d:%s" % (cr, cn)
319 print "changeset: %4d:%s" % (cr, cn)
320 print "parents: %4d:%s" % (i1, h1)
320 print "parents: %4d:%s" % (i1, h1)
321 if i2: print " %4d:%s" % (i2, h2)
321 if i2: print " %4d:%s" % (i2, h2)
322 changes = repo.changelog.read(repo.changelog.node(cr))
322 changes = repo.changelog.read(repo.changelog.node(cr))
323 print "user: %s" % changes[1]
323 print "user: %s" % changes[1]
324 print "date: %s" % time.asctime(
324 print "date: %s" % time.asctime(
325 time.localtime(float(changes[2].split(' ')[0])))
325 time.localtime(float(changes[2].split(' ')[0])))
326 print "description:"
326 print "description:"
327 print changes[4]
327 print changes[4]
328 print
328 print
329 elif len(args) > 1:
329 elif len(args) > 1:
330 print "too many args"
330 print "too many args"
331 else:
331 else:
332 print "missing filename"
332 print "missing filename"
333
333
334 elif cmd == "dump":
334 elif cmd == "dump":
335 if args:
335 if args:
336 r = repo.file(args[0])
336 r = repo.file(args[0])
337 n = r.tip()
337 n = r.tip()
338 if len(args) > 1: n = r.lookup(args[1])
338 if len(args) > 1: n = r.lookup(args[1])
339 sys.stdout.write(r.read(n))
339 sys.stdout.write(r.read(n))
340 else:
340 else:
341 print "missing filename"
341 print "missing filename"
342
342
343 elif cmd == "dumpmanifest":
343 elif cmd == "dumpmanifest":
344 n = repo.manifest.tip()
344 n = repo.manifest.tip()
345 if len(args) > 0:
345 if len(args) > 0:
346 n = repo.manifest.lookup(args[0])
346 n = repo.manifest.lookup(args[0])
347 m = repo.manifest.read(n)
347 m = repo.manifest.read(n)
348 files = m.keys()
348 files = m.keys()
349 files.sort()
349 files.sort()
350
350
351 for f in files:
351 for f in files:
352 print hg.hex(m[f]), f
352 print hg.hex(m[f]), f
353
353
354 elif cmd == "debugprompt":
354 elif cmd == "debugprompt":
355 print ui.prompt(args[0], args[1], args[2])
355 print ui.prompt(args[0], args[1], args[2])
356
356
357 elif cmd == "debughash":
357 elif cmd == "debughash":
358 f = repo.file(args[0])
358 f = repo.file(args[0])
359 print f.encodepath(args[0])
359 print f.encodepath(args[0])
360
360
361 elif cmd == "debugindex":
361 elif cmd == "debugindex":
362 if ".hg" not in args[0]:
362 if ".hg" not in args[0]:
363 args[0] = ".hg/data/" + repo.file(args[0]).encodepath(args[0]) + "i"
363 args[0] = ".hg/data/" + repo.file(args[0]).encodepath(args[0]) + "i"
364
364
365 r = hg.revlog(open, args[0], "")
365 r = hg.revlog(open, args[0], "")
366 print " rev offset length base linkrev"+\
366 print " rev offset length base linkrev"+\
367 " p1 p2 nodeid"
367 " p1 p2 nodeid"
368 for i in range(r.count()):
368 for i in range(r.count()):
369 e = r.index[i]
369 e = r.index[i]
370 print "% 6d % 9d % 7d % 6d % 7d %s.. %s.. %s.." % (
370 print "% 6d % 9d % 7d % 6d % 7d %s.. %s.. %s.." % (
371 i, e[0], e[1], e[2], e[3],
371 i, e[0], e[1], e[2], e[3],
372 hg.hex(e[4][:5]), hg.hex(e[5][:5]), hg.hex(e[6][:5]))
372 hg.hex(e[4][:5]), hg.hex(e[5][:5]), hg.hex(e[6][:5]))
373
373
374 elif cmd == "debugindexdot":
374 elif cmd == "debugindexdot":
375 if ".hg" not in args[0]:
375 if ".hg" not in args[0]:
376 args[0] = ".hg/data/" + repo.file(args[0]).encodepath(args[0]) + "i"
376 args[0] = ".hg/data/" + repo.file(args[0]).encodepath(args[0]) + "i"
377
377
378 r = hg.revlog(open, args[0], "")
378 r = hg.revlog(open, args[0], "")
379 print "digraph G {"
379 print "digraph G {"
380 for i in range(r.count()):
380 for i in range(r.count()):
381 e = r.index[i]
381 e = r.index[i]
382 print "\t%d -> %d" % (r.rev(e[4]), i)
382 print "\t%d -> %d" % (r.rev(e[4]), i)
383 if e[5] != hg.nullid:
383 if e[5] != hg.nullid:
384 print "\t%d -> %d" % (r.rev(e[5]), i)
384 print "\t%d -> %d" % (r.rev(e[5]), i)
385 print "}"
385 print "}"
386
386
387 elif cmd == "merge":
387 elif cmd == "merge":
388 if args:
388 if args:
389 other = hg.repository(ui, args[0])
389 other = hg.repository(ui, args[0])
390 ui.status("requesting changegroup\n")
390 ui.status("requesting changegroup\n")
391 cg = repo.getchangegroup(other)
391 cg = repo.getchangegroup(other)
392 repo.addchangegroup(cg)
392 repo.addchangegroup(cg)
393 else:
393 else:
394 print "missing source repository"
394 print "missing source repository"
395
395
396 elif cmd == "tags":
396 elif cmd == "tags":
397 repo.lookup(0) # prime the cache
397 repo.lookup(0) # prime the cache
398 i = repo.tags.items()
398 i = repo.tags.items()
399 i.sort()
399 i.sort()
400 for k, n in i:
400 for k, n in i:
401 try:
401 try:
402 r = repo.changelog.rev(n)
402 r = repo.changelog.rev(n)
403 except KeyError:
403 except KeyError:
404 r = "?"
404 r = "?"
405 print "%-30s %5d:%s" % (k, repo.changelog.rev(n), hg.hex(n))
405 print "%-30s %5d:%s" % (k, repo.changelog.rev(n), hg.hex(n))
406
406
407 elif cmd == "debugoldmerge":
407 elif cmd == "debugoldmerge":
408 if args:
408 if args:
409 other = hg.repository(ui, args[0])
409 other = hg.repository(ui, args[0])
410 repo.merge(other)
410 repo.merge(other)
411 else:
411 else:
412 print "missing source repository"
412 print "missing source repository"
413
413
414 elif cmd == "verify":
414 elif cmd == "verify":
415 filelinkrevs = {}
415 filelinkrevs = {}
416 filenodes = {}
416 filenodes = {}
417 manifestchangeset = {}
417 manifestchangeset = {}
418 changesets = revisions = files = 0
418 changesets = revisions = files = 0
419 errors = 0
419 errors = 0
420
420
421 ui.status("checking changesets\n")
421 ui.status("checking changesets\n")
422 for i in range(repo.changelog.count()):
422 for i in range(repo.changelog.count()):
423 changesets += 1
423 changesets += 1
424 n = repo.changelog.node(i)
424 n = repo.changelog.node(i)
425 for p in repo.changelog.parents(n):
425 for p in repo.changelog.parents(n):
426 if p not in repo.changelog.nodemap:
426 if p not in repo.changelog.nodemap:
427 ui.warn("changeset %s has unknown parent %s\n" %
427 ui.warn("changeset %s has unknown parent %s\n" %
428 (hg.short(n), hg.short(p)))
428 (hg.short(n), hg.short(p)))
429 errors += 1
429 errors += 1
430 try:
430 try:
431 changes = repo.changelog.read(n)
431 changes = repo.changelog.read(n)
432 except Error, inst:
432 except Error, inst:
433 ui.warn("unpacking changeset %s: %s\n" % (short(n), inst))
433 ui.warn("unpacking changeset %s: %s\n" % (short(n), inst))
434 errors += 1
434 errors += 1
435
435
436 manifestchangeset[changes[0]] = n
436 manifestchangeset[changes[0]] = n
437 for f in changes[3]:
437 for f in changes[3]:
438 revisions += 1
438 revisions += 1
439 filelinkrevs.setdefault(f, []).append(i)
439 filelinkrevs.setdefault(f, []).append(i)
440
440
441 ui.status("checking manifests\n")
441 ui.status("checking manifests\n")
442 for i in range(repo.manifest.count()):
442 for i in range(repo.manifest.count()):
443 n = repo.manifest.node(i)
443 n = repo.manifest.node(i)
444 for p in repo.manifest.parents(n):
444 for p in repo.manifest.parents(n):
445 if p not in repo.manifest.nodemap:
445 if p not in repo.manifest.nodemap:
446 ui.warn("manifest %s has unknown parent %s\n" %
446 ui.warn("manifest %s has unknown parent %s\n" %
447 (hg.short(n), hg.short(p)))
447 (hg.short(n), hg.short(p)))
448 errors += 1
448 errors += 1
449 ca = repo.changelog.node(repo.manifest.linkrev(n))
449 ca = repo.changelog.node(repo.manifest.linkrev(n))
450 cc = manifestchangeset[n]
450 cc = manifestchangeset[n]
451 if ca != cc:
451 if ca != cc:
452 ui.warn("manifest %s points to %s, not %s\n" %
452 ui.warn("manifest %s points to %s, not %s\n" %
453 (hg.hex(n), hg.hex(ca), hg.hex(cc)))
453 (hg.hex(n), hg.hex(ca), hg.hex(cc)))
454 errors += 1
454 errors += 1
455
455
456 try:
456 try:
457 m = repo.manifest.read(n)
457 delta = mdiff.patchtext(repo.manifest.delta(n))
458 except KeyboardInterrupt:
459 print "aborted"
460 sys.exit(0)
458 except Exception, inst:
461 except Exception, inst:
459 ui.warn("unpacking manifest %s: %s\n" % (hg.short(n), inst))
462 ui.warn("unpacking manifest %s: %s\n" % (hg.short(n), inst))
460 errors += 1
463 errors += 1
461
464
462 for f, fn in m.items():
465 ff = [ l.split('\0') for l in delta.splitlines() ]
463 filenodes.setdefault(f, {})[fn] = 1
466 for f, fn in ff:
467 filenodes.setdefault(f, {})[hg.bin(fn)] = 1
464
468
465 ui.status("crosschecking files in changesets and manifests\n")
469 ui.status("crosschecking files in changesets and manifests\n")
466 for f in filenodes:
470 for f in filenodes:
467 if f not in filelinkrevs:
471 if f not in filelinkrevs:
468 ui.warn("file %s in manifest but not in changesets\n" % f)
472 ui.warn("file %s in manifest but not in changesets\n" % f)
469 errors += 1
473 errors += 1
470
474
471 for f in filelinkrevs:
475 for f in filelinkrevs:
472 if f not in filenodes:
476 if f not in filenodes:
473 ui.warn("file %s in changeset but not in manifest" % f)
477 ui.warn("file %s in changeset but not in manifest\n" % f)
474 errors += 1
478 errors += 1
475
479
476 ui.status("checking files\n")
480 ui.status("checking files\n")
477 for f in filenodes:
481 ff = filenodes.keys()
482 ff.sort()
483 for f in ff:
484 if f == "/dev/null": continue
478 files += 1
485 files += 1
479 fl = repo.file(f)
486 fl = repo.file(f)
480 nodes = { hg.nullid: 1 }
487 nodes = { hg.nullid: 1 }
481 for i in range(fl.count()):
488 for i in range(fl.count()):
482 n = fl.node(i)
489 n = fl.node(i)
483
490
484 if n not in filenodes[f]:
491 if n not in filenodes[f]:
485 ui.warn("%s:%s not in manifests\n" % (f, hg.short(n)))
492 ui.warn("%s: %d:%s not in manifests\n" % (f, i, hg.short(n)))
493 print len(filenodes[f].keys()), fl.count(), f
486 errors += 1
494 errors += 1
487 else:
495 else:
488 del filenodes[f][n]
496 del filenodes[f][n]
489
497
490 flr = fl.linkrev(n)
498 flr = fl.linkrev(n)
491 if flr not in filelinkrevs[f]:
499 if flr not in filelinkrevs[f]:
492 ui.warn("%s:%s points to unexpected changeset rev %d\n"
500 ui.warn("%s:%s points to unexpected changeset rev %d\n"
493 % (f, hg.short(n), fl.linkrev(n)))
501 % (f, hg.short(n), fl.linkrev(n)))
494 errors += 1
502 errors += 1
495 else:
503 else:
496 filelinkrevs[f].remove(flr)
504 filelinkrevs[f].remove(flr)
497
505
498 # verify contents
506 # verify contents
499 try:
507 try:
500 t = fl.read(n)
508 t = fl.read(n)
501 except Error, inst:
509 except Error, inst:
502 ui.warn("unpacking file %s %s: %s\n" % (f, short(n), inst))
510 ui.warn("unpacking file %s %s: %s\n" % (f, short(n), inst))
503 errors += 1
511 errors += 1
504
512
505 # verify parents
513 # verify parents
506 (p1, p2) = fl.parents(n)
514 (p1, p2) = fl.parents(n)
507 if p1 not in nodes:
515 if p1 not in nodes:
508 ui.warn("file %s:%s unknown parent 1 %s" %
516 ui.warn("file %s:%s unknown parent 1 %s" %
509 (f, hg.short(n), hg.short(p1)))
517 (f, hg.short(n), hg.short(p1)))
510 errors += 1
518 errors += 1
511 if p2 not in nodes:
519 if p2 not in nodes:
512 ui.warn("file %s:%s unknown parent 2 %s" %
520 ui.warn("file %s:%s unknown parent 2 %s" %
513 (f, hg.short(n), hg.short(p1)))
521 (f, hg.short(n), hg.short(p1)))
514 errors += 1
522 errors += 1
515 nodes[n] = 1
523 nodes[n] = 1
516
524
517 # cross-check
525 # cross-check
518 for flr in filelinkrevs[f]:
526 for flr in filelinkrevs[f]:
519 ui.warn("changeset rev %d not in %s\n" % (flr, f))
527 ui.warn("changeset rev %d not in %s\n" % (flr, f))
520 errors += 1
528 errors += 1
521
529
522 for node in filenodes[f]:
530 for node in filenodes[f]:
523 ui.warn("node %s in manifests not in %s\n" % (hg.hex(n), f))
531 ui.warn("node %s in manifests not in %s\n" % (hg.hex(n), f))
524 errors += 1
532 errors += 1
525
533
526 ui.status("%d files, %d changesets, %d total revisions\n" %
534 ui.status("%d files, %d changesets, %d total revisions\n" %
527 (files, changesets, revisions))
535 (files, changesets, revisions))
528
536
529 if errors:
537 if errors:
530 ui.warn("%d integrity errors encountered!\n" % errors)
538 ui.warn("%d integrity errors encountered!\n" % errors)
531 sys.exit(1)
539 sys.exit(1)
532
540
533 else:
541 else:
534 print "unknown command\n"
542 print "unknown command\n"
535 help()
543 help()
536 sys.exit(1)
544 sys.exit(1)
General Comments 0
You need to be logged in to leave comments. Login now