##// END OF EJS Templates
hg init: when hardlinking, remove dirstate...
mpm@selenic.com -
r300:d3400605 default
parent child Browse files
Show More
@@ -1,652 +1,655 b''
1 # commands.py - command processing for mercurial
1 # commands.py - command processing for mercurial
2 #
2 #
3 # Copyright 2005 Matt Mackall <mpm@selenic.com>
3 # Copyright 2005 Matt Mackall <mpm@selenic.com>
4 #
4 #
5 # This software may be used and distributed according to the terms
5 # This software may be used and distributed according to the terms
6 # of the GNU General Public License, incorporated herein by reference.
6 # of the GNU General Public License, incorporated herein by reference.
7
7
8 import os, re, sys, signal
8 import os, re, sys, signal
9 import fancyopts, ui, hg
9 import fancyopts, ui, hg
10 from demandload import *
10 from demandload import *
11 demandload(globals(), "mdiff time hgweb traceback")
11 demandload(globals(), "mdiff time hgweb traceback")
12
12
13 class UnknownCommand(Exception): pass
13 class UnknownCommand(Exception): pass
14
14
15 def filterfiles(filters, files):
15 def filterfiles(filters, files):
16 l = [ x for x in files if x in filters ]
16 l = [ x for x in files if x in filters ]
17
17
18 for t in filters:
18 for t in filters:
19 if t and t[-1] != os.sep: t += os.sep
19 if t and t[-1] != os.sep: t += os.sep
20 l += [ x for x in files if x.startswith(t) ]
20 l += [ x for x in files if x.startswith(t) ]
21 return l
21 return l
22
22
23 def relfilter(repo, files):
23 def relfilter(repo, files):
24 if os.getcwd() != repo.root:
24 if os.getcwd() != repo.root:
25 p = os.getcwd()[len(repo.root) + 1: ]
25 p = os.getcwd()[len(repo.root) + 1: ]
26 return filterfiles([p], files)
26 return filterfiles([p], files)
27 return files
27 return files
28
28
29 def relpath(repo, args):
29 def relpath(repo, args):
30 if os.getcwd() != repo.root:
30 if os.getcwd() != repo.root:
31 p = os.getcwd()[len(repo.root) + 1: ]
31 p = os.getcwd()[len(repo.root) + 1: ]
32 return [ os.path.normpath(os.path.join(p, x)) for x in args ]
32 return [ os.path.normpath(os.path.join(p, x)) for x in args ]
33 return args
33 return args
34
34
35 def dodiff(repo, files = None, node1 = None, node2 = None):
35 def dodiff(repo, files = None, node1 = None, node2 = None):
36 def date(c):
36 def date(c):
37 return time.asctime(time.gmtime(float(c[2].split(' ')[0])))
37 return time.asctime(time.gmtime(float(c[2].split(' ')[0])))
38
38
39 if node2:
39 if node2:
40 change = repo.changelog.read(node2)
40 change = repo.changelog.read(node2)
41 mmap2 = repo.manifest.read(change[0])
41 mmap2 = repo.manifest.read(change[0])
42 (c, a, d) = repo.diffrevs(node1, node2)
42 (c, a, d) = repo.diffrevs(node1, node2)
43 def read(f): return repo.file(f).read(mmap2[f])
43 def read(f): return repo.file(f).read(mmap2[f])
44 date2 = date(change)
44 date2 = date(change)
45 else:
45 else:
46 date2 = time.asctime()
46 date2 = time.asctime()
47 (c, a, d, u) = repo.diffdir(repo.root, node1)
47 (c, a, d, u) = repo.diffdir(repo.root, node1)
48 if not node1:
48 if not node1:
49 node1 = repo.dirstate.parents()[0]
49 node1 = repo.dirstate.parents()[0]
50 def read(f): return file(os.path.join(repo.root, f)).read()
50 def read(f): return file(os.path.join(repo.root, f)).read()
51
51
52 change = repo.changelog.read(node1)
52 change = repo.changelog.read(node1)
53 mmap = repo.manifest.read(change[0])
53 mmap = repo.manifest.read(change[0])
54 date1 = date(change)
54 date1 = date(change)
55
55
56 if files:
56 if files:
57 c, a, d = map(lambda x: filterfiles(files, x), (c, a, d))
57 c, a, d = map(lambda x: filterfiles(files, x), (c, a, d))
58
58
59 for f in c:
59 for f in c:
60 to = None
60 to = None
61 if f in mmap:
61 if f in mmap:
62 to = repo.file(f).read(mmap[f])
62 to = repo.file(f).read(mmap[f])
63 tn = read(f)
63 tn = read(f)
64 sys.stdout.write(mdiff.unidiff(to, date1, tn, date2, f))
64 sys.stdout.write(mdiff.unidiff(to, date1, tn, date2, f))
65 for f in a:
65 for f in a:
66 to = None
66 to = None
67 tn = read(f)
67 tn = read(f)
68 sys.stdout.write(mdiff.unidiff(to, date1, tn, date2, f))
68 sys.stdout.write(mdiff.unidiff(to, date1, tn, date2, f))
69 for f in d:
69 for f in d:
70 to = repo.file(f).read(mmap[f])
70 to = repo.file(f).read(mmap[f])
71 tn = None
71 tn = None
72 sys.stdout.write(mdiff.unidiff(to, date1, tn, date2, f))
72 sys.stdout.write(mdiff.unidiff(to, date1, tn, date2, f))
73
73
74 def help(ui, cmd=None):
74 def help(ui, cmd=None):
75 '''show help for a given command or all commands'''
75 '''show help for a given command or all commands'''
76 if cmd:
76 if cmd:
77 try:
77 try:
78 i = find(cmd)
78 i = find(cmd)
79 ui.write("%s\n\n" % i[2])
79 ui.write("%s\n\n" % i[2])
80
80
81 if i[1]:
81 if i[1]:
82 for s, l, d, c in i[1]:
82 for s, l, d, c in i[1]:
83 opt=' '
83 opt=' '
84 if s: opt = opt + '-' + s + ' '
84 if s: opt = opt + '-' + s + ' '
85 if l: opt = opt + '--' + l + ' '
85 if l: opt = opt + '--' + l + ' '
86 if d: opt = opt + '(' + str(d) + ')'
86 if d: opt = opt + '(' + str(d) + ')'
87 ui.write(opt, "\n")
87 ui.write(opt, "\n")
88 if c: ui.write(' %s\n' % c)
88 if c: ui.write(' %s\n' % c)
89 ui.write("\n")
89 ui.write("\n")
90
90
91 ui.write(i[0].__doc__, "\n")
91 ui.write(i[0].__doc__, "\n")
92 except UnknownCommand:
92 except UnknownCommand:
93 ui.warn("hg: unknown command %s\n" % cmd)
93 ui.warn("hg: unknown command %s\n" % cmd)
94 sys.exit(0)
94 sys.exit(0)
95 else:
95 else:
96 ui.status('hg commands:\n\n')
96 ui.status('hg commands:\n\n')
97
97
98 h = {}
98 h = {}
99 for e in table.values():
99 for e in table.values():
100 f = e[0]
100 f = e[0]
101 if f.__name__.startswith("debug"): continue
101 if f.__name__.startswith("debug"): continue
102 d = ""
102 d = ""
103 if f.__doc__:
103 if f.__doc__:
104 d = f.__doc__.splitlines(0)[0].rstrip()
104 d = f.__doc__.splitlines(0)[0].rstrip()
105 h[f.__name__] = d
105 h[f.__name__] = d
106
106
107 fns = h.keys()
107 fns = h.keys()
108 fns.sort()
108 fns.sort()
109 m = max(map(len, fns))
109 m = max(map(len, fns))
110 for f in fns:
110 for f in fns:
111 ui.status(' %-*s %s\n' % (m, f, h[f]))
111 ui.status(' %-*s %s\n' % (m, f, h[f]))
112
112
113 # Commands start here, listed alphabetically
113 # Commands start here, listed alphabetically
114
114
115 def add(ui, repo, file, *files):
115 def add(ui, repo, file, *files):
116 '''add the specified files on the next commit'''
116 '''add the specified files on the next commit'''
117 repo.add(relpath(repo, (file,) + files))
117 repo.add(relpath(repo, (file,) + files))
118
118
119 def addremove(ui, repo):
119 def addremove(ui, repo):
120 """add all new files, delete all missing files"""
120 """add all new files, delete all missing files"""
121 (c, a, d, u) = repo.diffdir(repo.root)
121 (c, a, d, u) = repo.diffdir(repo.root)
122 repo.add(u)
122 repo.add(u)
123 repo.remove(d)
123 repo.remove(d)
124
124
125 def annotate(u, repo, file, *files, **ops):
125 def annotate(u, repo, file, *files, **ops):
126 """show changeset information per file line"""
126 """show changeset information per file line"""
127 def getnode(rev):
127 def getnode(rev):
128 return hg.short(repo.changelog.node(rev))
128 return hg.short(repo.changelog.node(rev))
129
129
130 def getname(rev):
130 def getname(rev):
131 try:
131 try:
132 return bcache[rev]
132 return bcache[rev]
133 except KeyError:
133 except KeyError:
134 cl = repo.changelog.read(repo.changelog.node(rev))
134 cl = repo.changelog.read(repo.changelog.node(rev))
135 name = cl[1]
135 name = cl[1]
136 f = name.find('@')
136 f = name.find('@')
137 if f >= 0:
137 if f >= 0:
138 name = name[:f]
138 name = name[:f]
139 bcache[rev] = name
139 bcache[rev] = name
140 return name
140 return name
141
141
142 bcache = {}
142 bcache = {}
143 opmap = [['user', getname], ['number', str], ['changeset', getnode]]
143 opmap = [['user', getname], ['number', str], ['changeset', getnode]]
144 if not ops['user'] and not ops['changeset']:
144 if not ops['user'] and not ops['changeset']:
145 ops['number'] = 1
145 ops['number'] = 1
146
146
147 node = repo.dirstate.parents()[0]
147 node = repo.dirstate.parents()[0]
148 if ops['revision']:
148 if ops['revision']:
149 node = repo.changelog.lookup(ops['revision'])
149 node = repo.changelog.lookup(ops['revision'])
150 change = repo.changelog.read(node)
150 change = repo.changelog.read(node)
151 mmap = repo.manifest.read(change[0])
151 mmap = repo.manifest.read(change[0])
152 maxuserlen = 0
152 maxuserlen = 0
153 maxchangelen = 0
153 maxchangelen = 0
154 for f in relpath(repo, (file,) + files):
154 for f in relpath(repo, (file,) + files):
155 lines = repo.file(f).annotate(mmap[f])
155 lines = repo.file(f).annotate(mmap[f])
156 pieces = []
156 pieces = []
157
157
158 for o, f in opmap:
158 for o, f in opmap:
159 if ops[o]:
159 if ops[o]:
160 l = [ f(n) for n,t in lines ]
160 l = [ f(n) for n,t in lines ]
161 m = max(map(len, l))
161 m = max(map(len, l))
162 pieces.append([ "%*s" % (m, x) for x in l])
162 pieces.append([ "%*s" % (m, x) for x in l])
163
163
164 for p,l in zip(zip(*pieces), lines):
164 for p,l in zip(zip(*pieces), lines):
165 u.write(" ".join(p) + ": " + l[1])
165 u.write(" ".join(p) + ": " + l[1])
166
166
167 def cat(ui, repo, file, rev = []):
167 def cat(ui, repo, file, rev = []):
168 """output the latest or given revision of a file"""
168 """output the latest or given revision of a file"""
169 r = repo.file(relpath(repo, [file])[0])
169 r = repo.file(relpath(repo, [file])[0])
170 n = r.tip()
170 n = r.tip()
171 if rev: n = r.lookup(rev)
171 if rev: n = r.lookup(rev)
172 sys.stdout.write(r.read(n))
172 sys.stdout.write(r.read(n))
173
173
174 def commit(ui, repo, *files, **opts):
174 def commit(ui, repo, *files, **opts):
175 """commit the specified files or all outstanding changes"""
175 """commit the specified files or all outstanding changes"""
176 text = opts['text']
176 text = opts['text']
177 if not text and opts['logfile']:
177 if not text and opts['logfile']:
178 try: text = open(opts['logfile']).read()
178 try: text = open(opts['logfile']).read()
179 except IOError: pass
179 except IOError: pass
180
180
181 repo.commit(relpath(repo, files), text)
181 repo.commit(relpath(repo, files), text)
182
182
183 def debugaddchangegroup(ui, repo):
183 def debugaddchangegroup(ui, repo):
184 data = sys.stdin.read()
184 data = sys.stdin.read()
185 repo.addchangegroup(data)
185 repo.addchangegroup(data)
186
186
187 def debugchangegroup(ui, repo, roots):
187 def debugchangegroup(ui, repo, roots):
188 newer = repo.newer(map(repo.lookup, roots))
188 newer = repo.newer(map(repo.lookup, roots))
189 for chunk in repo.changegroup(newer):
189 for chunk in repo.changegroup(newer):
190 sys.stdout.write(chunk)
190 sys.stdout.write(chunk)
191
191
192 def debugindex(ui, file):
192 def debugindex(ui, file):
193 r = hg.revlog(open, file, "")
193 r = hg.revlog(open, file, "")
194 print " rev offset length base linkrev"+\
194 print " rev offset length base linkrev"+\
195 " p1 p2 nodeid"
195 " p1 p2 nodeid"
196 for i in range(r.count()):
196 for i in range(r.count()):
197 e = r.index[i]
197 e = r.index[i]
198 print "% 6d % 9d % 7d % 6d % 7d %s.. %s.. %s.." % (
198 print "% 6d % 9d % 7d % 6d % 7d %s.. %s.. %s.." % (
199 i, e[0], e[1], e[2], e[3],
199 i, e[0], e[1], e[2], e[3],
200 hg.hex(e[4][:5]), hg.hex(e[5][:5]), hg.hex(e[6][:5]))
200 hg.hex(e[4][:5]), hg.hex(e[5][:5]), hg.hex(e[6][:5]))
201
201
202 def debugindexdot(ui, file):
202 def debugindexdot(ui, file):
203 r = hg.revlog(open, file, "")
203 r = hg.revlog(open, file, "")
204 print "digraph G {"
204 print "digraph G {"
205 for i in range(r.count()):
205 for i in range(r.count()):
206 e = r.index[i]
206 e = r.index[i]
207 print "\t%d -> %d" % (r.rev(e[4]), i)
207 print "\t%d -> %d" % (r.rev(e[4]), i)
208 if e[5] != hg.nullid:
208 if e[5] != hg.nullid:
209 print "\t%d -> %d" % (r.rev(e[5]), i)
209 print "\t%d -> %d" % (r.rev(e[5]), i)
210 print "}"
210 print "}"
211
211
212 def diff(ui, repo, *files, **opts):
212 def diff(ui, repo, *files, **opts):
213 """diff working directory (or selected files)"""
213 """diff working directory (or selected files)"""
214 revs = []
214 revs = []
215 if opts['rev']:
215 if opts['rev']:
216 revs = map(lambda x: repo.lookup(x), opts['rev'])
216 revs = map(lambda x: repo.lookup(x), opts['rev'])
217
217
218 if len(revs) > 2:
218 if len(revs) > 2:
219 self.ui.warn("too many revisions to diff\n")
219 self.ui.warn("too many revisions to diff\n")
220 sys.exit(1)
220 sys.exit(1)
221
221
222 if files:
222 if files:
223 files = relpath(repo, files)
223 files = relpath(repo, files)
224 else:
224 else:
225 files = relpath(repo, [""])
225 files = relpath(repo, [""])
226
226
227 dodiff(repo, files, *revs)
227 dodiff(repo, files, *revs)
228
228
229 def export(ui, repo, changeset):
229 def export(ui, repo, changeset):
230 """dump the changeset header and diffs for a revision"""
230 """dump the changeset header and diffs for a revision"""
231 node = repo.lookup(changeset)
231 node = repo.lookup(changeset)
232 prev, other = repo.changelog.parents(node)
232 prev, other = repo.changelog.parents(node)
233 change = repo.changelog.read(node)
233 change = repo.changelog.read(node)
234 print "# HG changeset patch"
234 print "# HG changeset patch"
235 print "# User %s" % change[1]
235 print "# User %s" % change[1]
236 print "# Node ID %s" % hg.hex(node)
236 print "# Node ID %s" % hg.hex(node)
237 print "# Parent %s" % hg.hex(prev)
237 print "# Parent %s" % hg.hex(prev)
238 print
238 print
239 if other != hg.nullid:
239 if other != hg.nullid:
240 print "# Parent %s" % hg.hex(other)
240 print "# Parent %s" % hg.hex(other)
241 print change[4].rstrip()
241 print change[4].rstrip()
242 print
242 print
243
243
244 dodiff(repo, None, prev, node)
244 dodiff(repo, None, prev, node)
245
245
246 def forget(ui, repo, file, *files):
246 def forget(ui, repo, file, *files):
247 """don't add the specified files on the next commit"""
247 """don't add the specified files on the next commit"""
248 repo.forget(relpath(repo, (file,) + files))
248 repo.forget(relpath(repo, (file,) + files))
249
249
250 def heads(ui, repo):
250 def heads(ui, repo):
251 '''show current repository heads'''
251 '''show current repository heads'''
252 for n in repo.changelog.heads():
252 for n in repo.changelog.heads():
253 i = repo.changelog.rev(n)
253 i = repo.changelog.rev(n)
254 changes = repo.changelog.read(n)
254 changes = repo.changelog.read(n)
255 (p1, p2) = repo.changelog.parents(n)
255 (p1, p2) = repo.changelog.parents(n)
256 (h, h1, h2) = map(hg.hex, (n, p1, p2))
256 (h, h1, h2) = map(hg.hex, (n, p1, p2))
257 (i1, i2) = map(repo.changelog.rev, (p1, p2))
257 (i1, i2) = map(repo.changelog.rev, (p1, p2))
258 print "rev: %4d:%s" % (i, h)
258 print "rev: %4d:%s" % (i, h)
259 print "parents: %4d:%s" % (i1, h1)
259 print "parents: %4d:%s" % (i1, h1)
260 if i2: print " %4d:%s" % (i2, h2)
260 if i2: print " %4d:%s" % (i2, h2)
261 print "manifest: %4d:%s" % (repo.manifest.rev(changes[0]),
261 print "manifest: %4d:%s" % (repo.manifest.rev(changes[0]),
262 hg.hex(changes[0]))
262 hg.hex(changes[0]))
263 print "user:", changes[1]
263 print "user:", changes[1]
264 print "date:", time.asctime(
264 print "date:", time.asctime(
265 time.localtime(float(changes[2].split(' ')[0])))
265 time.localtime(float(changes[2].split(' ')[0])))
266 if ui.verbose: print "files:", " ".join(changes[3])
266 if ui.verbose: print "files:", " ".join(changes[3])
267 print "description:"
267 print "description:"
268 print changes[4]
268 print changes[4]
269
269
270 def history(ui, repo):
270 def history(ui, repo):
271 """show the changelog history"""
271 """show the changelog history"""
272 for i in range(repo.changelog.count() - 1, -1, -1):
272 for i in range(repo.changelog.count() - 1, -1, -1):
273 n = repo.changelog.node(i)
273 n = repo.changelog.node(i)
274 changes = repo.changelog.read(n)
274 changes = repo.changelog.read(n)
275 (p1, p2) = repo.changelog.parents(n)
275 (p1, p2) = repo.changelog.parents(n)
276 (h, h1, h2) = map(hg.hex, (n, p1, p2))
276 (h, h1, h2) = map(hg.hex, (n, p1, p2))
277 (i1, i2) = map(repo.changelog.rev, (p1, p2))
277 (i1, i2) = map(repo.changelog.rev, (p1, p2))
278 print "rev: %4d:%s" % (i, h)
278 print "rev: %4d:%s" % (i, h)
279 print "parents: %4d:%s" % (i1, h1)
279 print "parents: %4d:%s" % (i1, h1)
280 if i2: print " %4d:%s" % (i2, h2)
280 if i2: print " %4d:%s" % (i2, h2)
281 print "manifest: %4d:%s" % (repo.manifest.rev(changes[0]),
281 print "manifest: %4d:%s" % (repo.manifest.rev(changes[0]),
282 hg.hex(changes[0]))
282 hg.hex(changes[0]))
283 print "user:", changes[1]
283 print "user:", changes[1]
284 print "date:", time.asctime(
284 print "date:", time.asctime(
285 time.localtime(float(changes[2].split(' ')[0])))
285 time.localtime(float(changes[2].split(' ')[0])))
286 if ui.verbose: print "files:", " ".join(changes[3])
286 if ui.verbose: print "files:", " ".join(changes[3])
287 print "description:"
287 print "description:"
288 print changes[4]
288 print changes[4]
289
289
290 def init(ui, source=None):
290 def init(ui, source=None):
291 """create a new repository or copy an existing one"""
291 """create a new repository or copy an existing one"""
292
292
293 if source:
293 if source:
294 paths = {}
294 paths = {}
295 for name, path in ui.configitems("paths"):
295 for name, path in ui.configitems("paths"):
296 paths[name] = path
296 paths[name] = path
297
297
298 if source in paths: source = paths[source]
298 if source in paths: source = paths[source]
299
299
300 link = 0
300 link = 0
301 if not source.startswith("http://"):
301 if not source.startswith("http://"):
302 d1 = os.stat(os.getcwd()).st_dev
302 d1 = os.stat(os.getcwd()).st_dev
303 d2 = os.stat(source).st_dev
303 d2 = os.stat(source).st_dev
304 if d1 == d2: link = 1
304 if d1 == d2: link = 1
305
305
306 if link:
306 if link:
307 ui.debug("copying by hardlink\n")
307 ui.debug("copying by hardlink\n")
308 os.system("cp -al %s/.hg .hg" % source)
308 os.system("cp -al %s/.hg .hg" % source)
309 try:
310 os.remove(".hg/dirstate")
311 except: pass
309 else:
312 else:
310 repo = hg.repository(ui, ".", create=1)
313 repo = hg.repository(ui, ".", create=1)
311 other = hg.repository(ui, source)
314 other = hg.repository(ui, source)
312 cg = repo.getchangegroup(other)
315 cg = repo.getchangegroup(other)
313 repo.addchangegroup(cg)
316 repo.addchangegroup(cg)
314 else:
317 else:
315 hg.repository(ui, ".", create=1)
318 hg.repository(ui, ".", create=1)
316
319
317 def log(ui, repo, f):
320 def log(ui, repo, f):
318 """show the revision history of a single file"""
321 """show the revision history of a single file"""
319 f = relpath(repo, [f])[0]
322 f = relpath(repo, [f])[0]
320
323
321 r = repo.file(f)
324 r = repo.file(f)
322 for i in range(r.count() - 1, -1, -1):
325 for i in range(r.count() - 1, -1, -1):
323 n = r.node(i)
326 n = r.node(i)
324 (p1, p2) = r.parents(n)
327 (p1, p2) = r.parents(n)
325 (h, h1, h2) = map(hg.hex, (n, p1, p2))
328 (h, h1, h2) = map(hg.hex, (n, p1, p2))
326 (i1, i2) = map(r.rev, (p1, p2))
329 (i1, i2) = map(r.rev, (p1, p2))
327 cr = r.linkrev(n)
330 cr = r.linkrev(n)
328 cn = hg.hex(repo.changelog.node(cr))
331 cn = hg.hex(repo.changelog.node(cr))
329 print "rev: %4d:%s" % (i, h)
332 print "rev: %4d:%s" % (i, h)
330 print "changeset: %4d:%s" % (cr, cn)
333 print "changeset: %4d:%s" % (cr, cn)
331 print "parents: %4d:%s" % (i1, h1)
334 print "parents: %4d:%s" % (i1, h1)
332 if i2: print " %4d:%s" % (i2, h2)
335 if i2: print " %4d:%s" % (i2, h2)
333 changes = repo.changelog.read(repo.changelog.node(cr))
336 changes = repo.changelog.read(repo.changelog.node(cr))
334 print "user: %s" % changes[1]
337 print "user: %s" % changes[1]
335 print "date: %s" % time.asctime(
338 print "date: %s" % time.asctime(
336 time.localtime(float(changes[2].split(' ')[0])))
339 time.localtime(float(changes[2].split(' ')[0])))
337 print "description:"
340 print "description:"
338 print changes[4].rstrip()
341 print changes[4].rstrip()
339 print
342 print
340
343
341 def manifest(ui, repo, rev = []):
344 def manifest(ui, repo, rev = []):
342 """output the latest or given revision of the project manifest"""
345 """output the latest or given revision of the project manifest"""
343 n = repo.manifest.tip()
346 n = repo.manifest.tip()
344 if rev:
347 if rev:
345 n = repo.manifest.lookup(rev)
348 n = repo.manifest.lookup(rev)
346 m = repo.manifest.read(n)
349 m = repo.manifest.read(n)
347 mf = repo.manifest.readflags(n)
350 mf = repo.manifest.readflags(n)
348 files = m.keys()
351 files = m.keys()
349 files.sort()
352 files.sort()
350
353
351 for f in files:
354 for f in files:
352 ui.write("%40s %3s %s\n" % (hg.hex(m[f]), mf[f] and "755" or "644", f))
355 ui.write("%40s %3s %s\n" % (hg.hex(m[f]), mf[f] and "755" or "644", f))
353
356
354 def parents(ui, repo, node = None):
357 def parents(ui, repo, node = None):
355 '''show the parents of the current working dir'''
358 '''show the parents of the current working dir'''
356 if node:
359 if node:
357 p = repo.changelog.parents(repo.lookup(hg.bin(node)))
360 p = repo.changelog.parents(repo.lookup(hg.bin(node)))
358 else:
361 else:
359 p = repo.dirstate.parents()
362 p = repo.dirstate.parents()
360
363
361 for n in p:
364 for n in p:
362 if n != hg.nullid:
365 if n != hg.nullid:
363 ui.write("%d:%s\n" % (repo.changelog.rev(n), hg.hex(n)))
366 ui.write("%d:%s\n" % (repo.changelog.rev(n), hg.hex(n)))
364
367
365 def patch(ui, repo, patch1, *patches, **opts):
368 def patch(ui, repo, patch1, *patches, **opts):
366 """import an ordered set of patches"""
369 """import an ordered set of patches"""
367 try:
370 try:
368 import psyco
371 import psyco
369 psyco.full()
372 psyco.full()
370 except:
373 except:
371 pass
374 pass
372
375
373 patches = (patch1,) + patches
376 patches = (patch1,) + patches
374
377
375 d = opts["base"]
378 d = opts["base"]
376 strip = opts["strip"]
379 strip = opts["strip"]
377 quiet = opts["quiet"] and "> /dev/null" or ""
380 quiet = opts["quiet"] and "> /dev/null" or ""
378
381
379 for patch in patches:
382 for patch in patches:
380 ui.status("applying %s\n" % patch)
383 ui.status("applying %s\n" % patch)
381 pf = os.path.join(d, patch)
384 pf = os.path.join(d, patch)
382
385
383 text = ""
386 text = ""
384 for l in file(pf):
387 for l in file(pf):
385 if l[:4] == "--- ": break
388 if l[:4] == "--- ": break
386 text += l
389 text += l
387
390
388 f = os.popen("lsdiff --strip %d %s" % (strip, pf))
391 f = os.popen("lsdiff --strip %d %s" % (strip, pf))
389 files = filter(None, map(lambda x: x.rstrip(), f.read().splitlines()))
392 files = filter(None, map(lambda x: x.rstrip(), f.read().splitlines()))
390 f.close()
393 f.close()
391
394
392 if files:
395 if files:
393 if os.system("patch -p%d < %s %s" % (strip, pf, quiet)):
396 if os.system("patch -p%d < %s %s" % (strip, pf, quiet)):
394 raise "patch failed!"
397 raise "patch failed!"
395 repo.commit(files, text)
398 repo.commit(files, text)
396
399
397 def pull(ui, repo, source):
400 def pull(ui, repo, source):
398 """pull changes from the specified source"""
401 """pull changes from the specified source"""
399 paths = {}
402 paths = {}
400 for name, path in ui.configitems("paths"):
403 for name, path in ui.configitems("paths"):
401 paths[name] = path
404 paths[name] = path
402
405
403 if source in paths: source = paths[source]
406 if source in paths: source = paths[source]
404
407
405 other = hg.repository(ui, source)
408 other = hg.repository(ui, source)
406 cg = repo.getchangegroup(other)
409 cg = repo.getchangegroup(other)
407 repo.addchangegroup(cg)
410 repo.addchangegroup(cg)
408
411
409 def rawcommit(ui, repo, files, **rc):
412 def rawcommit(ui, repo, files, **rc):
410 "raw commit interface"
413 "raw commit interface"
411
414
412 text = rc['text']
415 text = rc['text']
413 if not text and rc['logfile']:
416 if not text and rc['logfile']:
414 try: text = open(rc['logfile']).read()
417 try: text = open(rc['logfile']).read()
415 except IOError: pass
418 except IOError: pass
416 if not text and not rc['logfile']:
419 if not text and not rc['logfile']:
417 print "missing commit text"
420 print "missing commit text"
418 return 1
421 return 1
419
422
420 files = relpath(repo, files)
423 files = relpath(repo, files)
421 if rc['files']:
424 if rc['files']:
422 files += open(rc['files']).read().splitlines()
425 files += open(rc['files']).read().splitlines()
423
426
424 repo.rawcommit(files, text, rc['user'], rc['date'], *rc['parent'])
427 repo.rawcommit(files, text, rc['user'], rc['date'], *rc['parent'])
425
428
426 def recover(ui, repo):
429 def recover(ui, repo):
427 """roll back an interrupted transaction"""
430 """roll back an interrupted transaction"""
428 repo.recover()
431 repo.recover()
429
432
430 def remove(ui, repo, file, *files):
433 def remove(ui, repo, file, *files):
431 """remove the specified files on the next commit"""
434 """remove the specified files on the next commit"""
432 repo.remove(relpath(repo, (file,) + files))
435 repo.remove(relpath(repo, (file,) + files))
433
436
434 def serve(ui, repo, **opts):
437 def serve(ui, repo, **opts):
435 """export the repository via HTTP"""
438 """export the repository via HTTP"""
436 hgweb.server(repo.root, opts["name"], opts["templates"],
439 hgweb.server(repo.root, opts["name"], opts["templates"],
437 opts["address"], opts["port"])
440 opts["address"], opts["port"])
438
441
439 def status(ui, repo):
442 def status(ui, repo):
440 '''show changed files in the working directory
443 '''show changed files in the working directory
441
444
442 C = changed
445 C = changed
443 A = added
446 A = added
444 R = removed
447 R = removed
445 ? = not tracked'''
448 ? = not tracked'''
446
449
447 (c, a, d, u) = repo.diffdir(repo.root)
450 (c, a, d, u) = repo.diffdir(repo.root)
448 (c, a, d, u) = map(lambda x: relfilter(repo, x), (c, a, d, u))
451 (c, a, d, u) = map(lambda x: relfilter(repo, x), (c, a, d, u))
449
452
450 for f in c: print "C", f
453 for f in c: print "C", f
451 for f in a: print "A", f
454 for f in a: print "A", f
452 for f in d: print "R", f
455 for f in d: print "R", f
453 for f in u: print "?", f
456 for f in u: print "?", f
454
457
455 def tags(ui, repo):
458 def tags(ui, repo):
456 """list repository tags"""
459 """list repository tags"""
457 repo.lookup(0) # prime the cache
460 repo.lookup(0) # prime the cache
458 i = repo.tags.items()
461 i = repo.tags.items()
459 n = []
462 n = []
460 for e in i:
463 for e in i:
461 try:
464 try:
462 l = repo.changelog.rev(e[1])
465 l = repo.changelog.rev(e[1])
463 except KeyError:
466 except KeyError:
464 l = -2
467 l = -2
465 n.append((l, e))
468 n.append((l, e))
466
469
467 n.sort()
470 n.sort()
468 n.reverse()
471 n.reverse()
469 i = [ e[1] for e in n ]
472 i = [ e[1] for e in n ]
470 for k, n in i:
473 for k, n in i:
471 try:
474 try:
472 r = repo.changelog.rev(n)
475 r = repo.changelog.rev(n)
473 except KeyError:
476 except KeyError:
474 r = "?"
477 r = "?"
475 print "%-30s %5d:%s" % (k, repo.changelog.rev(n), hg.hex(n))
478 print "%-30s %5d:%s" % (k, repo.changelog.rev(n), hg.hex(n))
476
479
477 def tip(ui, repo):
480 def tip(ui, repo):
478 """show the tip revision"""
481 """show the tip revision"""
479 n = repo.changelog.tip()
482 n = repo.changelog.tip()
480 t = repo.changelog.rev(n)
483 t = repo.changelog.rev(n)
481 ui.status("%d:%s\n" % (t, hg.hex(n)))
484 ui.status("%d:%s\n" % (t, hg.hex(n)))
482
485
483 def undo(ui, repo):
486 def undo(ui, repo):
484 """undo the last transaction"""
487 """undo the last transaction"""
485 repo.undo()
488 repo.undo()
486
489
487 def update(ui, repo, node=None, merge=False, clean=False):
490 def update(ui, repo, node=None, merge=False, clean=False):
488 '''update or merge working directory
491 '''update or merge working directory
489
492
490 If there are no outstanding changes in the working directory and
493 If there are no outstanding changes in the working directory and
491 there is a linear relationship between the current version and the
494 there is a linear relationship between the current version and the
492 requested version, the result is the requested version.
495 requested version, the result is the requested version.
493
496
494 Otherwise the result is a merge between the contents of the
497 Otherwise the result is a merge between the contents of the
495 current working directory and the requested version. Files that
498 current working directory and the requested version. Files that
496 changed between either parent are marked as changed for the next
499 changed between either parent are marked as changed for the next
497 commit and a commit must be performed before any further updates
500 commit and a commit must be performed before any further updates
498 are allowed.
501 are allowed.
499 '''
502 '''
500 node = node and repo.lookup(node) or repo.changelog.tip()
503 node = node and repo.lookup(node) or repo.changelog.tip()
501 return repo.update(node, allow=merge, force=clean)
504 return repo.update(node, allow=merge, force=clean)
502
505
503 def verify(ui, repo):
506 def verify(ui, repo):
504 """verify the integrity of the repository"""
507 """verify the integrity of the repository"""
505 return repo.verify()
508 return repo.verify()
506
509
507 # Command options and aliases are listed here, alphabetically
510 # Command options and aliases are listed here, alphabetically
508
511
509 table = {
512 table = {
510 "add": (add, [], "hg add [files]"),
513 "add": (add, [], "hg add [files]"),
511 "addremove": (addremove, [], "hg addremove"),
514 "addremove": (addremove, [], "hg addremove"),
512 "ann|annotate": (annotate,
515 "ann|annotate": (annotate,
513 [('r', 'revision', '', 'revision'),
516 [('r', 'revision', '', 'revision'),
514 ('u', 'user', None, 'show user'),
517 ('u', 'user', None, 'show user'),
515 ('n', 'number', None, 'show revision number'),
518 ('n', 'number', None, 'show revision number'),
516 ('c', 'changeset', None, 'show changeset')],
519 ('c', 'changeset', None, 'show changeset')],
517 'hg annotate [-u] [-c] [-n] [-r id] [files]'),
520 'hg annotate [-u] [-c] [-n] [-r id] [files]'),
518 "cat|dump": (cat, [], 'hg cat <file> [rev]'),
521 "cat|dump": (cat, [], 'hg cat <file> [rev]'),
519 "commit|ci": (commit,
522 "commit|ci": (commit,
520 [('t', 'text', "", 'commit text'),
523 [('t', 'text', "", 'commit text'),
521 ('l', 'logfile', "", 'commit text file')],
524 ('l', 'logfile', "", 'commit text file')],
522 'hg commit [files]'),
525 'hg commit [files]'),
523 "debugaddchangegroup": (debugaddchangegroup, [], 'debugaddchangegroup'),
526 "debugaddchangegroup": (debugaddchangegroup, [], 'debugaddchangegroup'),
524 "debugchangegroup": (debugchangegroup, [], 'debugchangegroup [roots]'),
527 "debugchangegroup": (debugchangegroup, [], 'debugchangegroup [roots]'),
525 "debugindex": (debugindex, [], 'debugindex <file>'),
528 "debugindex": (debugindex, [], 'debugindex <file>'),
526 "debugindexdot": (debugindexdot, [], 'debugindexdot <file>'),
529 "debugindexdot": (debugindexdot, [], 'debugindexdot <file>'),
527 "diff": (diff, [('r', 'rev', [], 'revision')],
530 "diff": (diff, [('r', 'rev', [], 'revision')],
528 'hg diff [-r A] [-r B] [files]'),
531 'hg diff [-r A] [-r B] [files]'),
529 "export": (export, [], "hg export <changeset>"),
532 "export": (export, [], "hg export <changeset>"),
530 "forget": (forget, [], "hg forget [files]"),
533 "forget": (forget, [], "hg forget [files]"),
531 "heads": (heads, [], 'hg heads'),
534 "heads": (heads, [], 'hg heads'),
532 "history": (history, [], 'hg history'),
535 "history": (history, [], 'hg history'),
533 "help": (help, [], 'hg help [command]'),
536 "help": (help, [], 'hg help [command]'),
534 "init": (init, [], 'hg init [url]'),
537 "init": (init, [], 'hg init [url]'),
535 "log": (log, [], 'hg log <file>'),
538 "log": (log, [], 'hg log <file>'),
536 "manifest|dumpmanifest": (manifest, [], 'hg manifest [rev]'),
539 "manifest|dumpmanifest": (manifest, [], 'hg manifest [rev]'),
537 "parents": (parents, [], 'hg parents [node]'),
540 "parents": (parents, [], 'hg parents [node]'),
538 "patch|import": (patch,
541 "patch|import": (patch,
539 [('p', 'strip', 1, 'path strip'),
542 [('p', 'strip', 1, 'path strip'),
540 ('b', 'base', "", 'base path'),
543 ('b', 'base', "", 'base path'),
541 ('q', 'quiet', "", 'silence diff')],
544 ('q', 'quiet', "", 'silence diff')],
542 "hg import [options] patches"),
545 "hg import [options] patches"),
543 "pull|merge": (pull, [], 'hg pull [source]'),
546 "pull|merge": (pull, [], 'hg pull [source]'),
544 "rawcommit": (rawcommit,
547 "rawcommit": (rawcommit,
545 [('p', 'parent', [], 'parent'),
548 [('p', 'parent', [], 'parent'),
546 ('d', 'date', "", 'data'),
549 ('d', 'date', "", 'data'),
547 ('u', 'user', "", 'user'),
550 ('u', 'user', "", 'user'),
548 ('F', 'files', "", 'file list'),
551 ('F', 'files', "", 'file list'),
549 ('t', 'text', "", 'commit text'),
552 ('t', 'text', "", 'commit text'),
550 ('l', 'logfile', "", 'commit text file')],
553 ('l', 'logfile', "", 'commit text file')],
551 'hg rawcommit [options] [files]'),
554 'hg rawcommit [options] [files]'),
552 "recover": (recover, [], "hg recover"),
555 "recover": (recover, [], "hg recover"),
553 "remove": (remove, [], "hg remove [files]"),
556 "remove": (remove, [], "hg remove [files]"),
554 "serve": (serve, [('p', 'port', 8000, 'listen port'),
557 "serve": (serve, [('p', 'port', 8000, 'listen port'),
555 ('a', 'address', '', 'interface address'),
558 ('a', 'address', '', 'interface address'),
556 ('n', 'name', os.getcwd(), 'repository name'),
559 ('n', 'name', os.getcwd(), 'repository name'),
557 ('t', 'templates', "", 'template map')],
560 ('t', 'templates', "", 'template map')],
558 "hg serve [options]"),
561 "hg serve [options]"),
559 "status": (status, [], 'hg status'),
562 "status": (status, [], 'hg status'),
560 "tags": (tags, [], 'hg tags'),
563 "tags": (tags, [], 'hg tags'),
561 "tip": (tip, [], 'hg tip'),
564 "tip": (tip, [], 'hg tip'),
562 "undo": (undo, [], 'hg undo'),
565 "undo": (undo, [], 'hg undo'),
563 "update|up|checkout|co|resolve": (update,
566 "update|up|checkout|co|resolve": (update,
564 [('m', 'merge', None,
567 [('m', 'merge', None,
565 'allow merging of conflicts'),
568 'allow merging of conflicts'),
566 ('C', 'clean', None,
569 ('C', 'clean', None,
567 'overwrite locally modified files')],
570 'overwrite locally modified files')],
568 'hg update [options] [node]'),
571 'hg update [options] [node]'),
569 "verify": (verify, [], 'hg verify'),
572 "verify": (verify, [], 'hg verify'),
570 }
573 }
571
574
572 norepo = "init branch help debugindex debugindexdot"
575 norepo = "init branch help debugindex debugindexdot"
573
576
574 def find(cmd):
577 def find(cmd):
575 i = None
578 i = None
576 for e in table.keys():
579 for e in table.keys():
577 if re.match(e + "$", cmd):
580 if re.match(e + "$", cmd):
578 return table[e]
581 return table[e]
579
582
580 raise UnknownCommand(cmd)
583 raise UnknownCommand(cmd)
581
584
582 class SignalInterrupt(Exception): pass
585 class SignalInterrupt(Exception): pass
583
586
584 def catchterm(*args):
587 def catchterm(*args):
585 raise SignalInterrupt
588 raise SignalInterrupt
586
589
587 def run():
590 def run():
588 sys.exit(dispatch(sys.argv[1:]))
591 sys.exit(dispatch(sys.argv[1:]))
589
592
590 def dispatch(args):
593 def dispatch(args):
591 options = {}
594 options = {}
592 opts = [('v', 'verbose', None, 'verbose'),
595 opts = [('v', 'verbose', None, 'verbose'),
593 ('d', 'debug', None, 'debug'),
596 ('d', 'debug', None, 'debug'),
594 ('q', 'quiet', None, 'quiet'),
597 ('q', 'quiet', None, 'quiet'),
595 ('y', 'noninteractive', None, 'run non-interactively'),
598 ('y', 'noninteractive', None, 'run non-interactively'),
596 ]
599 ]
597
600
598 args = fancyopts.fancyopts(args, opts, options,
601 args = fancyopts.fancyopts(args, opts, options,
599 'hg [options] <command> [options] [files]')
602 'hg [options] <command> [options] [files]')
600
603
601 if not args:
604 if not args:
602 cmd = "help"
605 cmd = "help"
603 else:
606 else:
604 cmd, args = args[0], args[1:]
607 cmd, args = args[0], args[1:]
605
608
606 u = ui.ui(options["verbose"], options["debug"], options["quiet"],
609 u = ui.ui(options["verbose"], options["debug"], options["quiet"],
607 not options["noninteractive"])
610 not options["noninteractive"])
608
611
609 try:
612 try:
610 i = find(cmd)
613 i = find(cmd)
611 except UnknownCommand:
614 except UnknownCommand:
612 u.warn("hg: unknown command '%s'\n" % cmd)
615 u.warn("hg: unknown command '%s'\n" % cmd)
613 help(u)
616 help(u)
614 sys.exit(1)
617 sys.exit(1)
615
618
616 signal.signal(signal.SIGTERM, catchterm)
619 signal.signal(signal.SIGTERM, catchterm)
617
620
618 cmdoptions = {}
621 cmdoptions = {}
619 try:
622 try:
620 args = fancyopts.fancyopts(args, i[1], cmdoptions, i[2])
623 args = fancyopts.fancyopts(args, i[1], cmdoptions, i[2])
621 except fancyopts.getopt.GetoptError, inst:
624 except fancyopts.getopt.GetoptError, inst:
622 u.warn("hg %s: %s\n" % (cmd, inst))
625 u.warn("hg %s: %s\n" % (cmd, inst))
623 help(u, cmd)
626 help(u, cmd)
624 sys.exit(-1)
627 sys.exit(-1)
625
628
626 if cmd not in norepo.split():
629 if cmd not in norepo.split():
627 repo = hg.repository(ui = u)
630 repo = hg.repository(ui = u)
628 d = lambda: i[0](u, repo, *args, **cmdoptions)
631 d = lambda: i[0](u, repo, *args, **cmdoptions)
629 else:
632 else:
630 d = lambda: i[0](u, *args, **cmdoptions)
633 d = lambda: i[0](u, *args, **cmdoptions)
631
634
632 try:
635 try:
633 return d()
636 return d()
634 except SignalInterrupt:
637 except SignalInterrupt:
635 u.warn("killed!\n")
638 u.warn("killed!\n")
636 except KeyboardInterrupt:
639 except KeyboardInterrupt:
637 u.warn("interrupted!\n")
640 u.warn("interrupted!\n")
638 except IOError, inst:
641 except IOError, inst:
639 if inst.errno == 32:
642 if inst.errno == 32:
640 u.warn("broken pipe\n")
643 u.warn("broken pipe\n")
641 else:
644 else:
642 raise
645 raise
643 except TypeError, inst:
646 except TypeError, inst:
644 # was this an argument error?
647 # was this an argument error?
645 tb = traceback.extract_tb(sys.exc_info()[2])
648 tb = traceback.extract_tb(sys.exc_info()[2])
646 if len(tb) > 2: # no
649 if len(tb) > 2: # no
647 raise
650 raise
648 u.debug(inst, "\n")
651 u.debug(inst, "\n")
649 u.warn("%s: invalid arguments\n" % i[0].__name__)
652 u.warn("%s: invalid arguments\n" % i[0].__name__)
650 help(u, cmd)
653 help(u, cmd)
651 sys.exit(-1)
654 sys.exit(-1)
652
655
General Comments 0
You need to be logged in to leave comments. Login now