Mercurial > hg > mercurial-crew-with-dirclash
annotate hgext/mq.py @ 2289:854954fd410a
Fix revlog.parseindex
parseindex could fail if read returns too little data in the right
moment (e.g. when there's still leftover data from the previous
iteration and read returns less than "s" bytes).
author | Alexis S. L. Carvalho <alexis@cecm.usp.br> |
---|---|
date | Sun, 14 May 2006 18:22:12 -0300 |
parents | afd7c4ec000f |
children | dacf718e1d48 |
rev | line source |
---|---|
1808 | 1 # queue.py - patch queues for mercurial |
2 # | |
3 # Copyright 2005 Chris Mason <mason@suse.com> | |
4 # | |
5 # This software may be used and distributed according to the terms | |
6 # of the GNU General Public License, incorporated herein by reference. | |
7 | |
8 from mercurial.demandload import * | |
9 demandload(globals(), "os sys re struct traceback errno bz2") | |
10 from mercurial.i18n import gettext as _ | |
11 from mercurial import ui, hg, revlog, commands, util | |
12 | |
13 versionstr = "0.45" | |
14 | |
15 repomap = {} | |
16 | |
2047
ebf1ecb5f4e8
Register qversion as a non repository related command
Edouard Gomez <ed.gomez@free.fr>
parents:
1863
diff
changeset
|
17 commands.norepo += " qversion" |
1808 | 18 class queue: |
19 def __init__(self, ui, path, patchdir=None): | |
20 self.basepath = path | |
21 if patchdir: | |
22 self.path = patchdir | |
23 else: | |
24 self.path = os.path.join(path, "patches") | |
1852
fdf9cbf56ec7
Fix mq's usage of opener, which don't allow absolute paths now.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
1839
diff
changeset
|
25 self.opener = util.opener(self.path) |
1808 | 26 self.ui = ui |
27 self.applied = [] | |
28 self.full_series = [] | |
29 self.applied_dirty = 0 | |
30 self.series_dirty = 0 | |
1852
fdf9cbf56ec7
Fix mq's usage of opener, which don't allow absolute paths now.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
1839
diff
changeset
|
31 self.series_path = "series" |
fdf9cbf56ec7
Fix mq's usage of opener, which don't allow absolute paths now.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
1839
diff
changeset
|
32 self.status_path = "status" |
1810
7596611ab3d5
Whitespace, tab and formatting cleanups, mainly in mq.py
Thomas Arendsen Hein <thomas@intevation.de>
parents:
1808
diff
changeset
|
33 |
1852
fdf9cbf56ec7
Fix mq's usage of opener, which don't allow absolute paths now.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
1839
diff
changeset
|
34 if os.path.exists(os.path.join(self.path, self.series_path)): |
fdf9cbf56ec7
Fix mq's usage of opener, which don't allow absolute paths now.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
1839
diff
changeset
|
35 self.full_series = self.opener(self.series_path).read().splitlines() |
1808 | 36 self.read_series(self.full_series) |
37 | |
1852
fdf9cbf56ec7
Fix mq's usage of opener, which don't allow absolute paths now.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
1839
diff
changeset
|
38 if os.path.exists(os.path.join(self.path, self.status_path)): |
fdf9cbf56ec7
Fix mq's usage of opener, which don't allow absolute paths now.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
1839
diff
changeset
|
39 self.applied = self.opener(self.status_path).read().splitlines() |
1808 | 40 |
41 def find_series(self, patch): | |
42 pre = re.compile("(\s*)([^#]+)") | |
43 index = 0 | |
44 for l in self.full_series: | |
45 m = pre.match(l) | |
46 if m: | |
47 s = m.group(2) | |
48 s = s.rstrip() | |
49 if s == patch: | |
50 return index | |
51 index += 1 | |
52 return None | |
53 | |
54 def read_series(self, list): | |
55 def matcher(list): | |
56 pre = re.compile("(\s*)([^#]+)") | |
57 for l in list: | |
58 m = pre.match(l) | |
59 if m: | |
60 s = m.group(2) | |
61 s = s.rstrip() | |
62 if len(s) > 0: | |
63 yield s | |
64 self.series = [] | |
65 self.series = [ x for x in matcher(list) ] | |
1810
7596611ab3d5
Whitespace, tab and formatting cleanups, mainly in mq.py
Thomas Arendsen Hein <thomas@intevation.de>
parents:
1808
diff
changeset
|
66 |
1808 | 67 def save_dirty(self): |
68 if self.applied_dirty: | |
69 if len(self.applied) > 0: | |
70 nl = "\n" | |
71 else: | |
72 nl = "" | |
73 f = self.opener(self.status_path, "w") | |
74 f.write("\n".join(self.applied) + nl) | |
75 if self.series_dirty: | |
76 if len(self.full_series) > 0: | |
77 nl = "\n" | |
78 else: | |
79 nl = "" | |
80 f = self.opener(self.series_path, "w") | |
81 f.write("\n".join(self.full_series) + nl) | |
82 | |
83 def readheaders(self, patch): | |
84 def eatdiff(lines): | |
85 while lines: | |
86 l = lines[-1] | |
1810
7596611ab3d5
Whitespace, tab and formatting cleanups, mainly in mq.py
Thomas Arendsen Hein <thomas@intevation.de>
parents:
1808
diff
changeset
|
87 if (l.startswith("diff -") or |
7596611ab3d5
Whitespace, tab and formatting cleanups, mainly in mq.py
Thomas Arendsen Hein <thomas@intevation.de>
parents:
1808
diff
changeset
|
88 l.startswith("Index:") or |
7596611ab3d5
Whitespace, tab and formatting cleanups, mainly in mq.py
Thomas Arendsen Hein <thomas@intevation.de>
parents:
1808
diff
changeset
|
89 l.startswith("===========")): |
1808 | 90 del lines[-1] |
91 else: | |
92 break | |
93 def eatempty(lines): | |
94 while lines: | |
95 l = lines[-1] | |
96 if re.match('\s*$', l): | |
97 del lines[-1] | |
98 else: | |
99 break | |
100 | |
101 pf = os.path.join(self.path, patch) | |
102 message = [] | |
103 comments = [] | |
104 user = None | |
105 format = None | |
106 subject = None | |
107 diffstart = 0 | |
108 | |
109 for line in file(pf): | |
110 line = line.rstrip() | |
111 if diffstart: | |
112 if line.startswith('+++ '): | |
113 diffstart = 2 | |
114 break | |
115 if line.startswith("--- "): | |
116 diffstart = 1 | |
117 continue | |
118 elif format == "hgpatch": | |
119 # parse values when importing the result of an hg export | |
120 if line.startswith("# User "): | |
121 user = line[7:] | |
122 elif not line.startswith("# ") and line: | |
123 message.append(line) | |
124 format = None | |
125 elif line == '# HG changeset patch': | |
126 format = "hgpatch" | |
1810
7596611ab3d5
Whitespace, tab and formatting cleanups, mainly in mq.py
Thomas Arendsen Hein <thomas@intevation.de>
parents:
1808
diff
changeset
|
127 elif (format != "tagdone" and (line.startswith("Subject: ") or |
7596611ab3d5
Whitespace, tab and formatting cleanups, mainly in mq.py
Thomas Arendsen Hein <thomas@intevation.de>
parents:
1808
diff
changeset
|
128 line.startswith("subject: "))): |
1808 | 129 subject = line[9:] |
130 format = "tag" | |
1810
7596611ab3d5
Whitespace, tab and formatting cleanups, mainly in mq.py
Thomas Arendsen Hein <thomas@intevation.de>
parents:
1808
diff
changeset
|
131 elif (format != "tagdone" and (line.startswith("From: ") or |
7596611ab3d5
Whitespace, tab and formatting cleanups, mainly in mq.py
Thomas Arendsen Hein <thomas@intevation.de>
parents:
1808
diff
changeset
|
132 line.startswith("from: "))): |
1808 | 133 user = line[6:] |
134 format = "tag" | |
135 elif format == "tag" and line == "": | |
136 # when looking for tags (subject: from: etc) they | |
137 # end once you find a blank line in the source | |
138 format = "tagdone" | |
139 else: | |
140 message.append(line) | |
141 comments.append(line) | |
142 | |
143 eatdiff(message) | |
144 eatdiff(comments) | |
145 eatempty(message) | |
146 eatempty(comments) | |
147 | |
148 # make sure message isn't empty | |
149 if format and format.startswith("tag") and subject: | |
150 message.insert(0, "") | |
151 message.insert(0, subject) | |
152 return (message, comments, user, diffstart > 1) | |
153 | |
154 def mergeone(self, repo, mergeq, head, patch, rev, wlock): | |
155 # first try just applying the patch | |
1810
7596611ab3d5
Whitespace, tab and formatting cleanups, mainly in mq.py
Thomas Arendsen Hein <thomas@intevation.de>
parents:
1808
diff
changeset
|
156 (err, n) = self.apply(repo, [ patch ], update_status=False, |
1808 | 157 strict=True, merge=rev, wlock=wlock) |
158 | |
159 if err == 0: | |
160 return (err, n) | |
161 | |
162 if n is None: | |
163 self.ui.warn("apply failed for patch %s\n" % patch) | |
164 sys.exit(1) | |
165 | |
166 self.ui.warn("patch didn't work out, merging %s\n" % patch) | |
167 | |
168 # apply failed, strip away that rev and merge. | |
169 repo.update(head, allow=False, force=True, wlock=wlock) | |
170 self.strip(repo, n, update=False, backup='strip', wlock=wlock) | |
171 | |
172 c = repo.changelog.read(rev) | |
173 ret = repo.update(rev, allow=True, wlock=wlock) | |
174 if ret: | |
175 self.ui.warn("update returned %d\n" % ret) | |
176 sys.exit(1) | |
177 n = repo.commit(None, c[4], c[1], force=1, wlock=wlock) | |
178 if n == None: | |
179 self.ui.warn("repo commit failed\n") | |
180 sys.exit(1) | |
181 try: | |
182 message, comments, user, patchfound = mergeq.readheaders(patch) | |
183 except: | |
184 self.ui.warn("Unable to read %s\n" % patch) | |
185 sys.exit(1) | |
186 | |
1852
fdf9cbf56ec7
Fix mq's usage of opener, which don't allow absolute paths now.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
1839
diff
changeset
|
187 patchf = self.opener(patch, "w") |
1808 | 188 if comments: |
189 comments = "\n".join(comments) + '\n\n' | |
190 patchf.write(comments) | |
191 commands.dodiff(patchf, self.ui, repo, head, n) | |
192 patchf.close() | |
193 return (0, n) | |
1810
7596611ab3d5
Whitespace, tab and formatting cleanups, mainly in mq.py
Thomas Arendsen Hein <thomas@intevation.de>
parents:
1808
diff
changeset
|
194 |
1808 | 195 def qparents(self, repo, rev=None): |
196 if rev is None: | |
197 (p1, p2) = repo.dirstate.parents() | |
198 if p2 == revlog.nullid: | |
199 return p1 | |
200 if len(self.applied) == 0: | |
201 return None | |
202 (top, patch) = self.applied[-1].split(':') | |
203 top = revlog.bin(top) | |
204 return top | |
205 pp = repo.changelog.parents(rev) | |
206 if pp[1] != revlog.nullid: | |
207 arevs = [ x.split(':')[0] for x in self.applied ] | |
208 p0 = revlog.hex(pp[0]) | |
209 p1 = revlog.hex(pp[1]) | |
210 if p0 in arevs: | |
211 return pp[0] | |
212 if p1 in arevs: | |
213 return pp[1] | |
214 return None | |
215 return pp[0] | |
216 | |
217 def mergepatch(self, repo, mergeq, series, wlock): | |
218 if len(self.applied) == 0: | |
219 # each of the patches merged in will have two parents. This | |
220 # can confuse the qrefresh, qdiff, and strip code because it | |
221 # needs to know which parent is actually in the patch queue. | |
222 # so, we insert a merge marker with only one parent. This way | |
223 # the first patch in the queue is never a merge patch | |
224 # | |
225 pname = ".hg.patches.merge.marker" | |
226 n = repo.commit(None, '[mq]: merge marker', user=None, force=1, | |
227 wlock=wlock) | |
228 self.applied.append(revlog.hex(n) + ":" + pname) | |
229 self.applied_dirty = 1 | |
230 | |
231 head = self.qparents(repo) | |
232 | |
233 for patch in series: | |
234 patch = mergeq.lookup(patch) | |
235 if not patch: | |
236 self.ui.warn("patch %s does not exist\n" % patch) | |
237 return (1, None) | |
238 | |
239 info = mergeq.isapplied(patch) | |
240 if not info: | |
241 self.ui.warn("patch %s is not applied\n" % patch) | |
242 return (1, None) | |
243 rev = revlog.bin(info[1]) | |
244 (err, head) = self.mergeone(repo, mergeq, head, patch, rev, wlock) | |
245 if head: | |
246 self.applied.append(revlog.hex(head) + ":" + patch) | |
247 self.applied_dirty = 1 | |
248 if err: | |
249 return (err, head) | |
250 return (0, head) | |
251 | |
1810
7596611ab3d5
Whitespace, tab and formatting cleanups, mainly in mq.py
Thomas Arendsen Hein <thomas@intevation.de>
parents:
1808
diff
changeset
|
252 def apply(self, repo, series, list=False, update_status=True, |
1808 | 253 strict=False, patchdir=None, merge=None, wlock=None): |
254 # TODO unify with commands.py | |
255 if not patchdir: | |
256 patchdir = self.path | |
257 pwd = os.getcwd() | |
258 os.chdir(repo.root) | |
259 err = 0 | |
260 if not wlock: | |
261 wlock = repo.wlock() | |
262 lock = repo.lock() | |
263 tr = repo.transaction() | |
264 n = None | |
265 for patch in series: | |
266 self.ui.warn("applying %s\n" % patch) | |
267 pf = os.path.join(patchdir, patch) | |
268 | |
269 try: | |
270 message, comments, user, patchfound = self.readheaders(patch) | |
271 except: | |
272 self.ui.warn("Unable to read %s\n" % pf) | |
273 err = 1 | |
274 break | |
275 | |
276 if not message: | |
277 message = "imported patch %s\n" % patch | |
278 else: | |
279 if list: | |
280 message.append("\nimported patch %s" % patch) | |
281 message = '\n'.join(message) | |
282 | |
283 try: | |
2270
afd7c4ec000f
Fix issue240: mq: qpush fails on Solaris
Danek Duvall <danek.duvall@sun.com>
parents:
2185
diff
changeset
|
284 pp = util.find_in_path('gpatch', os.environ.get('PATH', ''), 'patch') |
afd7c4ec000f
Fix issue240: mq: qpush fails on Solaris
Danek Duvall <danek.duvall@sun.com>
parents:
2185
diff
changeset
|
285 f = os.popen("%s -p1 --no-backup-if-mismatch < '%s'" % (pp, pf)) |
1808 | 286 except: |
287 self.ui.warn("patch failed, unable to continue (try -v)\n") | |
288 err = 1 | |
289 break | |
290 files = [] | |
291 fuzz = False | |
292 for l in f: | |
293 l = l.rstrip('\r\n'); | |
294 if self.ui.verbose: | |
295 self.ui.warn(l + "\n") | |
296 if l[:14] == 'patching file ': | |
297 pf = os.path.normpath(l[14:]) | |
1810
7596611ab3d5
Whitespace, tab and formatting cleanups, mainly in mq.py
Thomas Arendsen Hein <thomas@intevation.de>
parents:
1808
diff
changeset
|
298 # when patch finds a space in the file name, it puts |
1808 | 299 # single quotes around the filename. strip them off |
300 if pf[0] == "'" and pf[-1] == "'": | |
301 pf = pf[1:-1] | |
302 if pf not in files: | |
303 files.append(pf) | |
304 printed_file = False | |
305 file_str = l | |
306 elif l.find('with fuzz') >= 0: | |
307 if not printed_file: | |
308 self.ui.warn(file_str + '\n') | |
309 printed_file = True | |
310 self.ui.warn(l + '\n') | |
311 fuzz = True | |
312 elif l.find('saving rejects to file') >= 0: | |
313 self.ui.warn(l + '\n') | |
314 elif l.find('FAILED') >= 0: | |
315 if not printed_file: | |
316 self.ui.warn(file_str + '\n') | |
317 printed_file = True | |
318 self.ui.warn(l + '\n') | |
319 patcherr = f.close() | |
320 | |
321 if merge and len(files) > 0: | |
1810
7596611ab3d5
Whitespace, tab and formatting cleanups, mainly in mq.py
Thomas Arendsen Hein <thomas@intevation.de>
parents:
1808
diff
changeset
|
322 # Mark as merged and update dirstate parent info |
7596611ab3d5
Whitespace, tab and formatting cleanups, mainly in mq.py
Thomas Arendsen Hein <thomas@intevation.de>
parents:
1808
diff
changeset
|
323 repo.dirstate.update(repo.dirstate.filterfiles(files), 'm') |
7596611ab3d5
Whitespace, tab and formatting cleanups, mainly in mq.py
Thomas Arendsen Hein <thomas@intevation.de>
parents:
1808
diff
changeset
|
324 p1, p2 = repo.dirstate.parents() |
7596611ab3d5
Whitespace, tab and formatting cleanups, mainly in mq.py
Thomas Arendsen Hein <thomas@intevation.de>
parents:
1808
diff
changeset
|
325 repo.dirstate.setparents(p1, merge) |
1808 | 326 if len(files) > 0: |
1810
7596611ab3d5
Whitespace, tab and formatting cleanups, mainly in mq.py
Thomas Arendsen Hein <thomas@intevation.de>
parents:
1808
diff
changeset
|
327 commands.addremove_lock(self.ui, repo, files, |
1808 | 328 opts={}, wlock=wlock) |
329 n = repo.commit(files, message, user, force=1, lock=lock, | |
330 wlock=wlock) | |
331 | |
332 if n == None: | |
333 self.ui.warn("repo commit failed\n") | |
334 sys.exit(1) | |
335 | |
336 if update_status: | |
337 self.applied.append(revlog.hex(n) + ":" + patch) | |
338 | |
339 if patcherr: | |
340 if not patchfound: | |
341 self.ui.warn("patch %s is empty\n" % patch) | |
342 err = 0 | |
343 else: | |
344 self.ui.warn("patch failed, rejects left in working dir\n") | |
345 err = 1 | |
346 break | |
347 | |
348 if fuzz and strict: | |
349 self.ui.warn("fuzz found when applying patch, stopping\n") | |
350 err = 1 | |
351 break | |
352 tr.close() | |
353 os.chdir(pwd) | |
354 return (err, n) | |
355 | |
356 def delete(self, repo, patch): | |
357 patch = self.lookup(patch) | |
358 info = self.isapplied(patch) | |
359 if info: | |
360 self.ui.warn("cannot delete applied patch %s\n" % patch) | |
361 sys.exit(1) | |
362 if patch not in self.series: | |
363 self.ui.warn("patch %s not in series file\n" % patch) | |
364 sys.exit(1) | |
365 i = self.find_series(patch) | |
366 del self.full_series[i] | |
367 self.read_series(self.full_series) | |
368 self.series_dirty = 1 | |
1810
7596611ab3d5
Whitespace, tab and formatting cleanups, mainly in mq.py
Thomas Arendsen Hein <thomas@intevation.de>
parents:
1808
diff
changeset
|
369 |
1808 | 370 def check_toppatch(self, repo): |
371 if len(self.applied) > 0: | |
372 (top, patch) = self.applied[-1].split(':') | |
373 top = revlog.bin(top) | |
374 pp = repo.dirstate.parents() | |
375 if top not in pp: | |
376 self.ui.warn("queue top not at dirstate parents. top %s dirstate %s %s\n" %( revlog.short(top), revlog.short(pp[0]), revlog.short(pp[1]))) | |
377 sys.exit(1) | |
378 return top | |
379 return None | |
380 def check_localchanges(self, repo): | |
381 (c, a, r, d, u) = repo.changes(None, None) | |
382 if c or a or d or r: | |
383 self.ui.write("Local changes found, refresh first\n") | |
384 sys.exit(1) | |
385 def new(self, repo, patch, msg=None, force=None): | |
386 if not force: | |
387 self.check_localchanges(repo) | |
388 self.check_toppatch(repo) | |
389 wlock = repo.wlock() | |
390 insert = self.series_end() | |
391 if msg: | |
1810
7596611ab3d5
Whitespace, tab and formatting cleanups, mainly in mq.py
Thomas Arendsen Hein <thomas@intevation.de>
parents:
1808
diff
changeset
|
392 n = repo.commit([], "[mq]: %s" % msg, force=True, wlock=wlock) |
1808 | 393 else: |
1810
7596611ab3d5
Whitespace, tab and formatting cleanups, mainly in mq.py
Thomas Arendsen Hein <thomas@intevation.de>
parents:
1808
diff
changeset
|
394 n = repo.commit([], |
7596611ab3d5
Whitespace, tab and formatting cleanups, mainly in mq.py
Thomas Arendsen Hein <thomas@intevation.de>
parents:
1808
diff
changeset
|
395 "New patch: %s" % patch, force=True, wlock=wlock) |
1808 | 396 if n == None: |
397 self.ui.warn("repo commit failed\n") | |
398 sys.exit(1) | |
399 self.full_series[insert:insert] = [patch] | |
400 self.applied.append(revlog.hex(n) + ":" + patch) | |
401 self.read_series(self.full_series) | |
402 self.series_dirty = 1 | |
403 self.applied_dirty = 1 | |
1852
fdf9cbf56ec7
Fix mq's usage of opener, which don't allow absolute paths now.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
1839
diff
changeset
|
404 p = self.opener(patch, "w") |
1808 | 405 if msg: |
406 msg = msg + "\n" | |
407 p.write(msg) | |
408 p.close() | |
409 wlock = None | |
410 r = self.qrepo() | |
411 if r: r.add([patch]) | |
412 | |
413 def strip(self, repo, rev, update=True, backup="all", wlock=None): | |
414 def limitheads(chlog, stop): | |
415 """return the list of all nodes that have no children""" | |
416 p = {} | |
417 h = [] | |
418 stoprev = 0 | |
419 if stop in chlog.nodemap: | |
420 stoprev = chlog.rev(stop) | |
421 | |
422 for r in range(chlog.count() - 1, -1, -1): | |
423 n = chlog.node(r) | |
424 if n not in p: | |
425 h.append(n) | |
426 if n == stop: | |
427 break | |
428 if r < stoprev: | |
429 break | |
430 for pn in chlog.parents(n): | |
431 p[pn] = 1 | |
432 return h | |
433 | |
434 def bundle(cg): | |
435 backupdir = repo.join("strip-backup") | |
436 if not os.path.isdir(backupdir): | |
437 os.mkdir(backupdir) | |
438 name = os.path.join(backupdir, "%s" % revlog.short(rev)) | |
439 name = savename(name) | |
440 self.ui.warn("saving bundle to %s\n" % name) | |
441 # TODO, exclusive open | |
442 f = open(name, "wb") | |
443 try: | |
444 f.write("HG10") | |
445 z = bz2.BZ2Compressor(9) | |
446 while 1: | |
447 chunk = cg.read(4096) | |
448 if not chunk: | |
449 break | |
450 f.write(z.compress(chunk)) | |
451 f.write(z.flush()) | |
452 except: | |
453 os.unlink(name) | |
454 raise | |
455 f.close() | |
456 return name | |
457 | |
458 def stripall(rev, revnum): | |
459 cl = repo.changelog | |
460 c = cl.read(rev) | |
461 mm = repo.manifest.read(c[0]) | |
462 seen = {} | |
463 | |
464 for x in xrange(revnum, cl.count()): | |
465 c = cl.read(cl.node(x)) | |
466 for f in c[3]: | |
467 if f in seen: | |
468 continue | |
469 seen[f] = 1 | |
470 if f in mm: | |
471 filerev = mm[f] | |
472 else: | |
473 filerev = 0 | |
474 seen[f] = filerev | |
475 # we go in two steps here so the strip loop happens in a | |
476 # sensible order. When stripping many files, this helps keep | |
477 # our disk access patterns under control. | |
478 list = seen.keys() | |
479 list.sort() | |
480 for f in list: | |
481 ff = repo.file(f) | |
482 filerev = seen[f] | |
483 if filerev != 0: | |
484 if filerev in ff.nodemap: | |
485 filerev = ff.rev(filerev) | |
486 else: | |
487 filerev = 0 | |
488 ff.strip(filerev, revnum) | |
489 | |
490 if not wlock: | |
491 wlock = repo.wlock() | |
492 lock = repo.lock() | |
493 chlog = repo.changelog | |
494 # TODO delete the undo files, and handle undo of merge sets | |
495 pp = chlog.parents(rev) | |
496 revnum = chlog.rev(rev) | |
497 | |
498 if update: | |
499 urev = self.qparents(repo, rev) | |
500 repo.update(urev, allow=False, force=True, wlock=wlock) | |
501 repo.dirstate.write() | |
502 | |
503 # save is a list of all the branches we are truncating away | |
504 # that we actually want to keep. changegroup will be used | |
505 # to preserve them and add them back after the truncate | |
506 saveheads = [] | |
507 savebases = {} | |
508 | |
509 tip = chlog.tip() | |
510 heads = limitheads(chlog, rev) | |
511 seen = {} | |
512 | |
513 # search through all the heads, finding those where the revision | |
514 # we want to strip away is an ancestor. Also look for merges | |
515 # that might be turned into new heads by the strip. | |
516 while heads: | |
517 h = heads.pop() | |
518 n = h | |
519 while True: | |
520 seen[n] = 1 | |
521 pp = chlog.parents(n) | |
522 if pp[1] != revlog.nullid and chlog.rev(pp[1]) > revnum: | |
523 if pp[1] not in seen: | |
524 heads.append(pp[1]) | |
525 if pp[0] == revlog.nullid: | |
526 break | |
527 if chlog.rev(pp[0]) < revnum: | |
528 break | |
529 n = pp[0] | |
530 if n == rev: | |
531 break | |
532 r = chlog.reachable(h, rev) | |
533 if rev not in r: | |
534 saveheads.append(h) | |
535 for x in r: | |
536 if chlog.rev(x) > revnum: | |
537 savebases[x] = 1 | |
1810
7596611ab3d5
Whitespace, tab and formatting cleanups, mainly in mq.py
Thomas Arendsen Hein <thomas@intevation.de>
parents:
1808
diff
changeset
|
538 |
1808 | 539 # create a changegroup for all the branches we need to keep |
540 if backup is "all": | |
541 backupch = repo.changegroupsubset([rev], chlog.heads(), 'strip') | |
542 bundle(backupch) | |
543 if saveheads: | |
544 backupch = repo.changegroupsubset(savebases.keys(), saveheads, 'strip') | |
545 chgrpfile = bundle(backupch) | |
546 | |
547 stripall(rev, revnum) | |
548 | |
549 change = chlog.read(rev) | |
550 repo.manifest.strip(repo.manifest.rev(change[0]), revnum) | |
551 chlog.strip(revnum, revnum) | |
552 if saveheads: | |
553 self.ui.status("adding branch\n") | |
554 commands.unbundle(self.ui, repo, chgrpfile, update=False) | |
555 if backup is not "strip": | |
556 os.unlink(chgrpfile) | |
1810
7596611ab3d5
Whitespace, tab and formatting cleanups, mainly in mq.py
Thomas Arendsen Hein <thomas@intevation.de>
parents:
1808
diff
changeset
|
557 |
1808 | 558 def isapplied(self, patch): |
559 """returns (index, rev, patch)""" | |
560 for i in xrange(len(self.applied)): | |
561 p = self.applied[i] | |
562 a = p.split(':') | |
563 if a[1] == patch: | |
564 return (i, a[0], a[1]) | |
565 return None | |
566 | |
567 def lookup(self, patch): | |
568 if patch == None: | |
569 return None | |
570 if patch in self.series: | |
571 return patch | |
572 if not os.path.isfile(os.path.join(self.path, patch)): | |
573 try: | |
574 sno = int(patch) | |
575 except(ValueError, OverflowError): | |
576 self.ui.warn("patch %s not in series\n" % patch) | |
577 sys.exit(1) | |
578 if sno >= len(self.series): | |
579 self.ui.warn("patch number %d is out of range\n" % sno) | |
580 sys.exit(1) | |
581 patch = self.series[sno] | |
582 else: | |
583 self.ui.warn("patch %s not in series\n" % patch) | |
584 sys.exit(1) | |
585 return patch | |
586 | |
1810
7596611ab3d5
Whitespace, tab and formatting cleanups, mainly in mq.py
Thomas Arendsen Hein <thomas@intevation.de>
parents:
1808
diff
changeset
|
587 def push(self, repo, patch=None, force=False, list=False, |
1808 | 588 mergeq=None, wlock=None): |
589 if not wlock: | |
590 wlock = repo.wlock() | |
1810
7596611ab3d5
Whitespace, tab and formatting cleanups, mainly in mq.py
Thomas Arendsen Hein <thomas@intevation.de>
parents:
1808
diff
changeset
|
591 patch = self.lookup(patch) |
1808 | 592 if patch and self.isapplied(patch): |
593 self.ui.warn("patch %s is already applied\n" % patch) | |
594 sys.exit(1) | |
595 if self.series_end() == len(self.series): | |
596 self.ui.warn("File series fully applied\n") | |
597 sys.exit(1) | |
598 if not force: | |
599 self.check_localchanges(repo) | |
1810
7596611ab3d5
Whitespace, tab and formatting cleanups, mainly in mq.py
Thomas Arendsen Hein <thomas@intevation.de>
parents:
1808
diff
changeset
|
600 |
1808 | 601 self.applied_dirty = 1; |
602 start = self.series_end() | |
603 if start > 0: | |
604 self.check_toppatch(repo) | |
605 if not patch: | |
606 patch = self.series[start] | |
607 end = start + 1 | |
608 else: | |
609 end = self.series.index(patch, start) + 1 | |
610 s = self.series[start:end] | |
611 if mergeq: | |
612 ret = self.mergepatch(repo, mergeq, s, wlock) | |
613 else: | |
614 ret = self.apply(repo, s, list, wlock=wlock) | |
615 top = self.applied[-1].split(':')[1] | |
616 if ret[0]: | |
1810
7596611ab3d5
Whitespace, tab and formatting cleanups, mainly in mq.py
Thomas Arendsen Hein <thomas@intevation.de>
parents:
1808
diff
changeset
|
617 self.ui.write("Errors during apply, please fix and refresh %s\n" % |
1808 | 618 top) |
619 else: | |
620 self.ui.write("Now at: %s\n" % top) | |
621 return ret[0] | |
622 | |
623 def pop(self, repo, patch=None, force=False, update=True, wlock=None): | |
624 def getfile(f, rev): | |
625 t = repo.file(f).read(rev) | |
626 try: | |
627 repo.wfile(f, "w").write(t) | |
628 except IOError: | |
2086
8742352db413
mq: do not fail if directory to create exists
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
2047
diff
changeset
|
629 try: |
8742352db413
mq: do not fail if directory to create exists
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
2047
diff
changeset
|
630 os.makedirs(os.path.dirname(repo.wjoin(f))) |
8742352db413
mq: do not fail if directory to create exists
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
2047
diff
changeset
|
631 except OSError, err: |
8742352db413
mq: do not fail if directory to create exists
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
2047
diff
changeset
|
632 if err.errno != errno.EEXIST: raise |
1808 | 633 repo.wfile(f, "w").write(t) |
634 | |
635 if not wlock: | |
636 wlock = repo.wlock() | |
637 if patch: | |
638 # index, rev, patch | |
639 info = self.isapplied(patch) | |
640 if not info: | |
641 patch = self.lookup(patch) | |
642 info = self.isapplied(patch) | |
643 if not info: | |
644 self.ui.warn("patch %s is not applied\n" % patch) | |
645 sys.exit(1) | |
646 if len(self.applied) == 0: | |
647 self.ui.warn("No patches applied\n") | |
648 sys.exit(1) | |
649 | |
650 if not update: | |
651 parents = repo.dirstate.parents() | |
652 rr = [ revlog.bin(x.split(':')[0]) for x in self.applied ] | |
653 for p in parents: | |
654 if p in rr: | |
655 self.ui.warn("qpop: forcing dirstate update\n") | |
656 update = True | |
657 | |
658 if not force and update: | |
659 self.check_localchanges(repo) | |
660 | |
661 self.applied_dirty = 1; | |
662 end = len(self.applied) | |
663 if not patch: | |
664 info = [len(self.applied) - 1] + self.applied[-1].split(':') | |
665 start = info[0] | |
666 rev = revlog.bin(info[1]) | |
667 | |
668 # we know there are no local changes, so we can make a simplified | |
669 # form of hg.update. | |
670 if update: | |
671 top = self.check_toppatch(repo) | |
672 qp = self.qparents(repo, rev) | |
673 changes = repo.changelog.read(qp) | |
674 mf1 = repo.manifest.readflags(changes[0]) | |
675 mmap = repo.manifest.read(changes[0]) | |
676 (c, a, r, d, u) = repo.changes(qp, top) | |
677 if d: | |
678 raise util.Abort("deletions found between repo revs") | |
679 for f in c: | |
680 getfile(f, mmap[f]) | |
681 for f in r: | |
682 getfile(f, mmap[f]) | |
683 util.set_exec(repo.wjoin(f), mf1[f]) | |
684 repo.dirstate.update(c + r, 'n') | |
685 for f in a: | |
686 try: os.unlink(repo.wjoin(f)) | |
687 except: raise | |
688 try: os.removedirs(os.path.dirname(repo.wjoin(f))) | |
689 except: pass | |
690 if a: | |
691 repo.dirstate.forget(a) | |
692 repo.dirstate.setparents(qp, revlog.nullid) | |
693 self.strip(repo, rev, update=False, backup='strip', wlock=wlock) | |
694 del self.applied[start:end] | |
695 if len(self.applied): | |
696 self.ui.write("Now at: %s\n" % self.applied[-1].split(':')[1]) | |
697 else: | |
698 self.ui.write("Patch queue now empty\n") | |
699 | |
700 def diff(self, repo, files): | |
701 top = self.check_toppatch(repo) | |
702 if not top: | |
703 self.ui.write("No patches applied\n") | |
704 return | |
705 qp = self.qparents(repo, top) | |
706 commands.dodiff(sys.stdout, self.ui, repo, qp, None, files) | |
707 | |
708 def refresh(self, repo, short=False): | |
709 if len(self.applied) == 0: | |
710 self.ui.write("No patches applied\n") | |
711 return | |
712 wlock = repo.wlock() | |
713 self.check_toppatch(repo) | |
714 qp = self.qparents(repo) | |
715 (top, patch) = self.applied[-1].split(':') | |
716 top = revlog.bin(top) | |
717 cparents = repo.changelog.parents(top) | |
718 patchparent = self.qparents(repo, top) | |
719 message, comments, user, patchfound = self.readheaders(patch) | |
720 | |
1852
fdf9cbf56ec7
Fix mq's usage of opener, which don't allow absolute paths now.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
1839
diff
changeset
|
721 patchf = self.opener(patch, "w") |
1808 | 722 if comments: |
723 comments = "\n".join(comments) + '\n\n' | |
724 patchf.write(comments) | |
725 | |
726 tip = repo.changelog.tip() | |
727 if top == tip: | |
1810
7596611ab3d5
Whitespace, tab and formatting cleanups, mainly in mq.py
Thomas Arendsen Hein <thomas@intevation.de>
parents:
1808
diff
changeset
|
728 # if the top of our patch queue is also the tip, there is an |
1808 | 729 # optimization here. We update the dirstate in place and strip |
730 # off the tip commit. Then just commit the current directory | |
731 # tree. We can also send repo.commit the list of files | |
732 # changed to speed up the diff | |
733 # | |
1810
7596611ab3d5
Whitespace, tab and formatting cleanups, mainly in mq.py
Thomas Arendsen Hein <thomas@intevation.de>
parents:
1808
diff
changeset
|
734 # in short mode, we only diff the files included in the |
1808 | 735 # patch already |
736 # | |
737 # this should really read: | |
738 #(cc, dd, aa, aa2, uu) = repo.changes(tip, patchparent) | |
739 # but we do it backwards to take advantage of manifest/chlog | |
740 # caching against the next repo.changes call | |
1810
7596611ab3d5
Whitespace, tab and formatting cleanups, mainly in mq.py
Thomas Arendsen Hein <thomas@intevation.de>
parents:
1808
diff
changeset
|
741 # |
1808 | 742 (cc, aa, dd, aa2, uu) = repo.changes(patchparent, tip) |
743 if short: | |
744 filelist = cc + aa + dd | |
745 else: | |
746 filelist = None | |
747 (c, a, r, d, u) = repo.changes(None, None, filelist) | |
748 | |
749 # we might end up with files that were added between tip and | |
750 # the dirstate parent, but then changed in the local dirstate. | |
751 # in this case, we want them to only show up in the added section | |
752 for x in c: | |
753 if x not in aa: | |
754 cc.append(x) | |
755 # we might end up with files added by the local dirstate that | |
756 # were deleted by the patch. In this case, they should only | |
757 # show up in the changed section. | |
758 for x in a: | |
759 if x in dd: | |
760 del dd[dd.index(x)] | |
761 cc.append(x) | |
762 else: | |
763 aa.append(x) | |
764 # make sure any files deleted in the local dirstate | |
765 # are not in the add or change column of the patch | |
766 forget = [] | |
767 for x in d + r: | |
768 if x in aa: | |
769 del aa[aa.index(x)] | |
770 forget.append(x) | |
771 continue | |
772 elif x in cc: | |
773 del cc[cc.index(x)] | |
774 dd.append(x) | |
775 | |
776 c = list(util.unique(cc)) | |
777 r = list(util.unique(dd)) | |
778 a = list(util.unique(aa)) | |
779 filelist = list(util.unique(c + r + a )) | |
1810
7596611ab3d5
Whitespace, tab and formatting cleanups, mainly in mq.py
Thomas Arendsen Hein <thomas@intevation.de>
parents:
1808
diff
changeset
|
780 commands.dodiff(patchf, self.ui, repo, patchparent, None, |
1808 | 781 filelist, changes=(c, a, r, [], u)) |
782 patchf.close() | |
783 | |
784 changes = repo.changelog.read(tip) | |
785 repo.dirstate.setparents(*cparents) | |
786 repo.dirstate.update(a, 'a') | |
787 repo.dirstate.update(r, 'r') | |
1810
7596611ab3d5
Whitespace, tab and formatting cleanups, mainly in mq.py
Thomas Arendsen Hein <thomas@intevation.de>
parents:
1808
diff
changeset
|
788 repo.dirstate.update(c, 'n') |
1808 | 789 repo.dirstate.forget(forget) |
790 | |
791 if not message: | |
792 message = "patch queue: %s\n" % patch | |
793 else: | |
794 message = "\n".join(message) | |
795 self.strip(repo, top, update=False, backup='strip', wlock=wlock) | |
796 n = repo.commit(filelist, message, changes[1], force=1, wlock=wlock) | |
797 self.applied[-1] = revlog.hex(n) + ':' + patch | |
798 self.applied_dirty = 1 | |
799 else: | |
800 commands.dodiff(patchf, self.ui, repo, patchparent, None) | |
801 patchf.close() | |
802 self.pop(repo, force=True, wlock=wlock) | |
803 self.push(repo, force=True, wlock=wlock) | |
804 | |
805 def init(self, repo, create=False): | |
806 if os.path.isdir(self.path): | |
807 raise util.Abort("patch queue directory already exists") | |
808 os.mkdir(self.path) | |
809 if create: | |
810 return self.qrepo(create=True) | |
811 | |
812 def unapplied(self, repo, patch=None): | |
813 if patch and patch not in self.series: | |
814 self.ui.warn("%s not in the series file\n" % patch) | |
815 sys.exit(1) | |
816 if not patch: | |
817 start = self.series_end() | |
818 else: | |
819 start = self.series.index(patch) + 1 | |
820 for p in self.series[start:]: | |
821 self.ui.write("%s\n" % p) | |
1810
7596611ab3d5
Whitespace, tab and formatting cleanups, mainly in mq.py
Thomas Arendsen Hein <thomas@intevation.de>
parents:
1808
diff
changeset
|
822 |
1808 | 823 def qseries(self, repo, missing=None): |
824 start = self.series_end() | |
825 if not missing: | |
826 for p in self.series[:start]: | |
827 if self.ui.verbose: | |
828 self.ui.write("%d A " % self.series.index(p)) | |
829 self.ui.write("%s\n" % p) | |
830 for p in self.series[start:]: | |
831 if self.ui.verbose: | |
832 self.ui.write("%d U " % self.series.index(p)) | |
833 self.ui.write("%s\n" % p) | |
834 else: | |
835 list = [] | |
836 for root, dirs, files in os.walk(self.path): | |
837 d = root[len(self.path) + 1:] | |
838 for f in files: | |
839 fl = os.path.join(d, f) | |
1852
fdf9cbf56ec7
Fix mq's usage of opener, which don't allow absolute paths now.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
1839
diff
changeset
|
840 if (fl not in self.series and |
fdf9cbf56ec7
Fix mq's usage of opener, which don't allow absolute paths now.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
1839
diff
changeset
|
841 fl not in (self.status_path, self.series_path) |
fdf9cbf56ec7
Fix mq's usage of opener, which don't allow absolute paths now.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
1839
diff
changeset
|
842 and not fl.startswith('.')): |
1808 | 843 list.append(fl) |
844 list.sort() | |
845 if list: | |
1810
7596611ab3d5
Whitespace, tab and formatting cleanups, mainly in mq.py
Thomas Arendsen Hein <thomas@intevation.de>
parents:
1808
diff
changeset
|
846 for x in list: |
1808 | 847 if self.ui.verbose: |
848 self.ui.write("D ") | |
849 self.ui.write("%s\n" % x) | |
850 | |
851 def issaveline(self, l): | |
852 name = l.split(':')[1] | |
853 if name == '.hg.patches.save.line': | |
854 return True | |
855 | |
856 def qrepo(self, create=False): | |
857 if create or os.path.isdir(os.path.join(self.path, ".hg")): | |
1839
876e4e6ad82b
Create local ui object per repository, so .hg/hgrc don't get mixed.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
1810
diff
changeset
|
858 return hg.repository(self.ui, path=self.path, create=create) |
1808 | 859 |
860 def restore(self, repo, rev, delete=None, qupdate=None): | |
861 c = repo.changelog.read(rev) | |
862 desc = c[4].strip() | |
863 lines = desc.splitlines() | |
864 i = 0 | |
865 datastart = None | |
866 series = [] | |
867 applied = [] | |
868 qpp = None | |
869 for i in xrange(0, len(lines)): | |
870 if lines[i] == 'Patch Data:': | |
871 datastart = i + 1 | |
872 elif lines[i].startswith('Dirstate:'): | |
873 l = lines[i].rstrip() | |
874 l = l[10:].split(' ') | |
875 qpp = [ hg.bin(x) for x in l ] | |
876 elif datastart != None: | |
877 l = lines[i].rstrip() | |
878 index = l.index(':') | |
879 id = l[:index] | |
880 file = l[index + 1:] | |
881 if id: | |
882 applied.append(l) | |
883 series.append(file) | |
884 if datastart == None: | |
885 self.ui.warn("No saved patch data found\n") | |
886 return 1 | |
887 self.ui.warn("restoring status: %s\n" % lines[0]) | |
888 self.full_series = series | |
889 self.applied = applied | |
890 self.read_series(self.full_series) | |
891 self.series_dirty = 1 | |
892 self.applied_dirty = 1 | |
893 heads = repo.changelog.heads() | |
894 if delete: | |
895 if rev not in heads: | |
896 self.ui.warn("save entry has children, leaving it alone\n") | |
897 else: | |
898 self.ui.warn("removing save entry %s\n" % hg.short(rev)) | |
899 pp = repo.dirstate.parents() | |
900 if rev in pp: | |
901 update = True | |
902 else: | |
903 update = False | |
904 self.strip(repo, rev, update=update, backup='strip') | |
905 if qpp: | |
1810
7596611ab3d5
Whitespace, tab and formatting cleanups, mainly in mq.py
Thomas Arendsen Hein <thomas@intevation.de>
parents:
1808
diff
changeset
|
906 self.ui.warn("saved queue repository parents: %s %s\n" % |
1808 | 907 (hg.short(qpp[0]), hg.short(qpp[1]))) |
908 if qupdate: | |
909 print "queue directory updating" | |
910 r = self.qrepo() | |
911 if not r: | |
912 self.ui.warn("Unable to load queue repository\n") | |
913 return 1 | |
914 r.update(qpp[0], allow=False, force=True) | |
915 | |
916 def save(self, repo, msg=None): | |
917 if len(self.applied) == 0: | |
918 self.ui.warn("save: no patches applied, exiting\n") | |
919 return 1 | |
920 if self.issaveline(self.applied[-1]): | |
921 self.ui.warn("status is already saved\n") | |
922 return 1 | |
1810
7596611ab3d5
Whitespace, tab and formatting cleanups, mainly in mq.py
Thomas Arendsen Hein <thomas@intevation.de>
parents:
1808
diff
changeset
|
923 |
1808 | 924 ar = [ ':' + x for x in self.full_series ] |
925 if not msg: | |
926 msg = "hg patches saved state" | |
927 else: | |
928 msg = "hg patches: " + msg.rstrip('\r\n') | |
929 r = self.qrepo() | |
930 if r: | |
931 pp = r.dirstate.parents() | |
932 msg += "\nDirstate: %s %s" % (hg.hex(pp[0]), hg.hex(pp[1])) | |
933 msg += "\n\nPatch Data:\n" | |
1810
7596611ab3d5
Whitespace, tab and formatting cleanups, mainly in mq.py
Thomas Arendsen Hein <thomas@intevation.de>
parents:
1808
diff
changeset
|
934 text = msg + "\n".join(self.applied) + '\n' + (ar and "\n".join(ar) |
7596611ab3d5
Whitespace, tab and formatting cleanups, mainly in mq.py
Thomas Arendsen Hein <thomas@intevation.de>
parents:
1808
diff
changeset
|
935 + '\n' or "") |
1808 | 936 n = repo.commit(None, text, user=None, force=1) |
937 if not n: | |
938 self.ui.warn("repo commit failed\n") | |
939 return 1 | |
940 self.applied.append(revlog.hex(n) + ":" + '.hg.patches.save.line') | |
941 self.applied_dirty = 1 | |
942 | |
943 def series_end(self): | |
944 end = 0 | |
945 if len(self.applied) > 0: | |
946 (top, p) = self.applied[-1].split(':') | |
947 try: | |
948 end = self.series.index(p) | |
949 except ValueError: | |
950 return 0 | |
951 return end + 1 | |
952 return end | |
953 | |
954 def qapplied(self, repo, patch=None): | |
955 if patch and patch not in self.series: | |
956 self.ui.warn("%s not in the series file\n" % patch) | |
957 sys.exit(1) | |
958 if not patch: | |
959 end = len(self.applied) | |
960 else: | |
961 end = self.series.index(patch) + 1 | |
962 for x in xrange(end): | |
963 p = self.appliedname(x) | |
964 self.ui.write("%s\n" % p) | |
965 | |
966 def appliedname(self, index): | |
967 p = self.applied[index] | |
968 if not self.ui.verbose: | |
969 p = p.split(':')[1] | |
970 return p | |
1810
7596611ab3d5
Whitespace, tab and formatting cleanups, mainly in mq.py
Thomas Arendsen Hein <thomas@intevation.de>
parents:
1808
diff
changeset
|
971 |
1808 | 972 def top(self, repo): |
973 if len(self.applied): | |
974 p = self.appliedname(-1) | |
975 self.ui.write(p + '\n') | |
976 else: | |
977 self.ui.write("No patches applied\n") | |
978 | |
979 def next(self, repo): | |
980 end = self.series_end() | |
981 if end == len(self.series): | |
982 self.ui.write("All patches applied\n") | |
983 else: | |
984 self.ui.write(self.series[end] + '\n') | |
985 | |
986 def prev(self, repo): | |
987 if len(self.applied) > 1: | |
988 p = self.appliedname(-2) | |
989 self.ui.write(p + '\n') | |
990 elif len(self.applied) == 1: | |
991 self.ui.write("Only one patch applied\n") | |
992 else: | |
993 self.ui.write("No patches applied\n") | |
994 | |
995 def qimport(self, repo, files, patch=None, existing=None, force=None): | |
996 if len(files) > 1 and patch: | |
997 self.ui.warn("-n option not valid when importing multiple files\n") | |
998 sys.exit(1) | |
999 i = 0 | |
1000 for filename in files: | |
1001 if existing: | |
1810
7596611ab3d5
Whitespace, tab and formatting cleanups, mainly in mq.py
Thomas Arendsen Hein <thomas@intevation.de>
parents:
1808
diff
changeset
|
1002 if not patch: |
1808 | 1003 patch = filename |
1004 if not os.path.isfile(os.path.join(self.path, patch)): | |
1005 self.ui.warn("patch %s does not exist\n" % patch) | |
1006 sys.exit(1) | |
1007 else: | |
1008 try: | |
1009 text = file(filename).read() | |
1010 except IOError: | |
1011 self.ui.warn("Unable to read %s\n" % patch) | |
1012 sys.exit(1) | |
1013 if not patch: | |
1014 patch = os.path.split(filename)[1] | |
1015 if not force and os.path.isfile(os.path.join(self.path, patch)): | |
1016 self.ui.warn("patch %s already exists\n" % patch) | |
1017 sys.exit(1) | |
1852
fdf9cbf56ec7
Fix mq's usage of opener, which don't allow absolute paths now.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
1839
diff
changeset
|
1018 patchf = self.opener(patch, "w") |
1808 | 1019 patchf.write(text) |
1020 if patch in self.series: | |
1021 self.ui.warn("patch %s is already in the series file\n" % patch) | |
1022 sys.exit(1) | |
1023 index = self.series_end() + i | |
1024 self.full_series[index:index] = [patch] | |
1025 self.read_series(self.full_series) | |
1026 self.ui.warn("adding %s to series file\n" % patch) | |
1027 i += 1 | |
1028 patch = None | |
1029 self.series_dirty = 1 | |
1030 | |
1031 def delete(ui, repo, patch, **opts): | |
1032 """remove a patch from the series file""" | |
1033 q = repomap[repo] | |
1034 q.delete(repo, patch) | |
1035 q.save_dirty() | |
1036 return 0 | |
1037 | |
1038 def applied(ui, repo, patch=None, **opts): | |
1039 """print the patches already applied""" | |
1040 repomap[repo].qapplied(repo, patch) | |
1041 return 0 | |
1042 | |
1043 def unapplied(ui, repo, patch=None, **opts): | |
1044 """print the patches not yet applied""" | |
1045 repomap[repo].unapplied(repo, patch) | |
1046 return 0 | |
1047 | |
1048 def qimport(ui, repo, *filename, **opts): | |
1049 """import a patch""" | |
1050 q = repomap[repo] | |
1810
7596611ab3d5
Whitespace, tab and formatting cleanups, mainly in mq.py
Thomas Arendsen Hein <thomas@intevation.de>
parents:
1808
diff
changeset
|
1051 q.qimport(repo, filename, patch=opts['name'], |
7596611ab3d5
Whitespace, tab and formatting cleanups, mainly in mq.py
Thomas Arendsen Hein <thomas@intevation.de>
parents:
1808
diff
changeset
|
1052 existing=opts['existing'], force=opts['force']) |
1808 | 1053 q.save_dirty() |
1054 return 0 | |
1055 | |
1056 def init(ui, repo, **opts): | |
1057 """init a new queue repository""" | |
1058 q = repomap[repo] | |
1059 r = q.init(repo, create=opts['create_repo']) | |
1060 q.save_dirty() | |
1061 if r: | |
1062 fp = r.wopener('.hgignore', 'w') | |
1063 print >> fp, 'syntax: glob' | |
1064 print >> fp, 'status' | |
1065 fp.close() | |
1066 r.wopener('series', 'w').close() | |
1067 r.add(['.hgignore', 'series']) | |
1068 return 0 | |
1069 | |
1070 def commit(ui, repo, *pats, **opts): | |
1071 q = repomap[repo] | |
1072 r = q.qrepo() | |
1073 if not r: raise util.Abort('no queue repository') | |
1074 commands.commit(r.ui, r, *pats, **opts) | |
1075 | |
1076 def series(ui, repo, **opts): | |
1077 """print the entire series file""" | |
1078 repomap[repo].qseries(repo, missing=opts['missing']) | |
1079 return 0 | |
1080 | |
1081 def top(ui, repo, **opts): | |
1082 """print the name of the current patch""" | |
1083 repomap[repo].top(repo) | |
1084 return 0 | |
1085 | |
1086 def next(ui, repo, **opts): | |
1087 """print the name of the next patch""" | |
1088 repomap[repo].next(repo) | |
1089 return 0 | |
1090 | |
1091 def prev(ui, repo, **opts): | |
1092 """print the name of the previous patch""" | |
1093 repomap[repo].prev(repo) | |
1094 return 0 | |
1095 | |
1096 def new(ui, repo, patch, **opts): | |
1097 """create a new patch""" | |
1098 q = repomap[repo] | |
1099 q.new(repo, patch, msg=opts['message'], force=opts['force']) | |
1100 q.save_dirty() | |
1101 return 0 | |
1102 | |
1103 def refresh(ui, repo, **opts): | |
1104 """update the current patch""" | |
1105 q = repomap[repo] | |
1106 q.refresh(repo, short=opts['short']) | |
1107 q.save_dirty() | |
1108 return 0 | |
1109 | |
1110 def diff(ui, repo, *files, **opts): | |
1111 """diff of the current patch""" | |
2097
4d2c2597876f
Fix hg qdiff <file>
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents:
2086
diff
changeset
|
1112 # deep in the dirstate code, the walkhelper method wants a list, not a tuple |
4d2c2597876f
Fix hg qdiff <file>
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents:
2086
diff
changeset
|
1113 repomap[repo].diff(repo, list(files)) |
1808 | 1114 return 0 |
1115 | |
1116 def lastsavename(path): | |
1117 (dir, base) = os.path.split(path) | |
1118 names = os.listdir(dir) | |
1119 namere = re.compile("%s.([0-9]+)" % base) | |
1120 max = None | |
1121 maxname = None | |
1122 for f in names: | |
1123 m = namere.match(f) | |
1124 if m: | |
1125 index = int(m.group(1)) | |
1126 if max == None or index > max: | |
1127 max = index | |
1128 maxname = f | |
1129 if maxname: | |
1130 return (os.path.join(dir, maxname), max) | |
1131 return (None, None) | |
1810
7596611ab3d5
Whitespace, tab and formatting cleanups, mainly in mq.py
Thomas Arendsen Hein <thomas@intevation.de>
parents:
1808
diff
changeset
|
1132 |
1808 | 1133 def savename(path): |
1134 (last, index) = lastsavename(path) | |
1135 if last is None: | |
1136 index = 0 | |
1137 newpath = path + ".%d" % (index + 1) | |
1138 return newpath | |
1139 | |
1140 def push(ui, repo, patch=None, **opts): | |
1141 """push the next patch onto the stack""" | |
1142 q = repomap[repo] | |
1143 mergeq = None | |
1810
7596611ab3d5
Whitespace, tab and formatting cleanups, mainly in mq.py
Thomas Arendsen Hein <thomas@intevation.de>
parents:
1808
diff
changeset
|
1144 |
1808 | 1145 if opts['all']: |
1146 patch = q.series[-1] | |
1147 if opts['merge']: | |
1148 if opts['name']: | |
1149 newpath = opts['name'] | |
1150 else: | |
1810
7596611ab3d5
Whitespace, tab and formatting cleanups, mainly in mq.py
Thomas Arendsen Hein <thomas@intevation.de>
parents:
1808
diff
changeset
|
1151 newpath, i = lastsavename(q.path) |
1808 | 1152 if not newpath: |
1153 ui.warn("no saved queues found, please use -n\n") | |
1154 return 1 | |
1155 mergeq = queue(ui, repo.join(""), newpath) | |
1156 ui.warn("merging with queue at: %s\n" % mergeq.path) | |
1810
7596611ab3d5
Whitespace, tab and formatting cleanups, mainly in mq.py
Thomas Arendsen Hein <thomas@intevation.de>
parents:
1808
diff
changeset
|
1157 ret = q.push(repo, patch, force=opts['force'], list=opts['list'], |
1808 | 1158 mergeq=mergeq) |
1159 q.save_dirty() | |
1160 return ret | |
1161 | |
1162 def pop(ui, repo, patch=None, **opts): | |
1163 """pop the current patch off the stack""" | |
1164 localupdate = True | |
1165 if opts['name']: | |
1166 q = queue(ui, repo.join(""), repo.join(opts['name'])) | |
1167 ui.warn('using patch queue: %s\n' % q.path) | |
1168 localupdate = False | |
1169 else: | |
1170 q = repomap[repo] | |
1171 if opts['all'] and len(q.applied) > 0: | |
1172 patch = q.applied[0].split(':')[1] | |
1173 q.pop(repo, patch, force=opts['force'], update=localupdate) | |
1174 q.save_dirty() | |
1175 return 0 | |
1176 | |
1177 def restore(ui, repo, rev, **opts): | |
1178 """restore the queue state saved by a rev""" | |
1179 rev = repo.lookup(rev) | |
1180 q = repomap[repo] | |
1181 q.restore(repo, rev, delete=opts['delete'], | |
1810
7596611ab3d5
Whitespace, tab and formatting cleanups, mainly in mq.py
Thomas Arendsen Hein <thomas@intevation.de>
parents:
1808
diff
changeset
|
1182 qupdate=opts['update']) |
1808 | 1183 q.save_dirty() |
1184 return 0 | |
1185 | |
1186 def save(ui, repo, **opts): | |
1187 """save current queue state""" | |
1188 q = repomap[repo] | |
1189 ret = q.save(repo, msg=opts['message']) | |
1190 if ret: | |
1191 return ret | |
1192 q.save_dirty() | |
1193 if opts['copy']: | |
1194 path = q.path | |
1195 if opts['name']: | |
1196 newpath = os.path.join(q.basepath, opts['name']) | |
1197 if os.path.exists(newpath): | |
1198 if not os.path.isdir(newpath): | |
1199 ui.warn("destination %s exists and is not a directory\n" % | |
1810
7596611ab3d5
Whitespace, tab and formatting cleanups, mainly in mq.py
Thomas Arendsen Hein <thomas@intevation.de>
parents:
1808
diff
changeset
|
1200 newpath) |
1808 | 1201 sys.exit(1) |
1202 if not opts['force']: | |
1203 ui.warn("destination %s exists, use -f to force\n" % | |
1810
7596611ab3d5
Whitespace, tab and formatting cleanups, mainly in mq.py
Thomas Arendsen Hein <thomas@intevation.de>
parents:
1808
diff
changeset
|
1204 newpath) |
1808 | 1205 sys.exit(1) |
1206 else: | |
1207 newpath = savename(path) | |
1208 ui.warn("copy %s to %s\n" % (path, newpath)) | |
1209 util.copyfiles(path, newpath) | |
1210 if opts['empty']: | |
1211 try: | |
1852
fdf9cbf56ec7
Fix mq's usage of opener, which don't allow absolute paths now.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
1839
diff
changeset
|
1212 os.unlink(os.path.join(q.path, q.status_path)) |
1808 | 1213 except: |
1214 pass | |
1215 return 0 | |
1810
7596611ab3d5
Whitespace, tab and formatting cleanups, mainly in mq.py
Thomas Arendsen Hein <thomas@intevation.de>
parents:
1808
diff
changeset
|
1216 |
1808 | 1217 def strip(ui, repo, rev, **opts): |
1218 """strip a revision and all later revs on the same branch""" | |
1219 rev = repo.lookup(rev) | |
1220 backup = 'all' | |
1221 if opts['backup']: | |
1222 backup = 'strip' | |
1223 elif opts['nobackup']: | |
1224 backup = 'none' | |
1225 repomap[repo].strip(repo, rev, backup=backup) | |
1226 return 0 | |
1227 | |
1228 def version(ui, q=None): | |
1229 """print the version number""" | |
1230 ui.write("mq version %s\n" % versionstr) | |
1231 return 0 | |
1232 | |
1233 def reposetup(ui, repo): | |
1234 repomap[repo] = queue(ui, repo.join("")) | |
1235 | |
1236 cmdtable = { | |
2185
5acd648770d0
Better help for mq: Corrected synopses, get qcommit options from commands.py.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
2097
diff
changeset
|
1237 "qapplied": (applied, [], 'hg qapplied [PATCH]'), |
1810
7596611ab3d5
Whitespace, tab and formatting cleanups, mainly in mq.py
Thomas Arendsen Hein <thomas@intevation.de>
parents:
1808
diff
changeset
|
1238 "qcommit|qci": |
7596611ab3d5
Whitespace, tab and formatting cleanups, mainly in mq.py
Thomas Arendsen Hein <thomas@intevation.de>
parents:
1808
diff
changeset
|
1239 (commit, |
2185
5acd648770d0
Better help for mq: Corrected synopses, get qcommit options from commands.py.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
2097
diff
changeset
|
1240 commands.table["^commit|ci"][1], |
5acd648770d0
Better help for mq: Corrected synopses, get qcommit options from commands.py.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
2097
diff
changeset
|
1241 'hg qcommit [OPTION]... [FILE]...'), |
5acd648770d0
Better help for mq: Corrected synopses, get qcommit options from commands.py.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
2097
diff
changeset
|
1242 "^qdiff": (diff, [], 'hg qdiff [FILE]...'), |
5acd648770d0
Better help for mq: Corrected synopses, get qcommit options from commands.py.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
2097
diff
changeset
|
1243 "qdelete": (delete, [], 'hg qdelete PATCH'), |
1810
7596611ab3d5
Whitespace, tab and formatting cleanups, mainly in mq.py
Thomas Arendsen Hein <thomas@intevation.de>
parents:
1808
diff
changeset
|
1244 "^qimport": |
7596611ab3d5
Whitespace, tab and formatting cleanups, mainly in mq.py
Thomas Arendsen Hein <thomas@intevation.de>
parents:
1808
diff
changeset
|
1245 (qimport, |
7596611ab3d5
Whitespace, tab and formatting cleanups, mainly in mq.py
Thomas Arendsen Hein <thomas@intevation.de>
parents:
1808
diff
changeset
|
1246 [('e', 'existing', None, 'import file in patch dir'), |
7596611ab3d5
Whitespace, tab and formatting cleanups, mainly in mq.py
Thomas Arendsen Hein <thomas@intevation.de>
parents:
1808
diff
changeset
|
1247 ('n', 'name', '', 'patch file name'), |
7596611ab3d5
Whitespace, tab and formatting cleanups, mainly in mq.py
Thomas Arendsen Hein <thomas@intevation.de>
parents:
1808
diff
changeset
|
1248 ('f', 'force', None, 'overwrite existing files')], |
2185
5acd648770d0
Better help for mq: Corrected synopses, get qcommit options from commands.py.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
2097
diff
changeset
|
1249 'hg qimport [-e] [-n NAME] [-f] FILE...'), |
1810
7596611ab3d5
Whitespace, tab and formatting cleanups, mainly in mq.py
Thomas Arendsen Hein <thomas@intevation.de>
parents:
1808
diff
changeset
|
1250 "^qinit": |
7596611ab3d5
Whitespace, tab and formatting cleanups, mainly in mq.py
Thomas Arendsen Hein <thomas@intevation.de>
parents:
1808
diff
changeset
|
1251 (init, |
7596611ab3d5
Whitespace, tab and formatting cleanups, mainly in mq.py
Thomas Arendsen Hein <thomas@intevation.de>
parents:
1808
diff
changeset
|
1252 [('c', 'create-repo', None, 'create patch repository')], |
2185
5acd648770d0
Better help for mq: Corrected synopses, get qcommit options from commands.py.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
2097
diff
changeset
|
1253 'hg qinit [-c]'), |
1810
7596611ab3d5
Whitespace, tab and formatting cleanups, mainly in mq.py
Thomas Arendsen Hein <thomas@intevation.de>
parents:
1808
diff
changeset
|
1254 "qnew": |
7596611ab3d5
Whitespace, tab and formatting cleanups, mainly in mq.py
Thomas Arendsen Hein <thomas@intevation.de>
parents:
1808
diff
changeset
|
1255 (new, |
7596611ab3d5
Whitespace, tab and formatting cleanups, mainly in mq.py
Thomas Arendsen Hein <thomas@intevation.de>
parents:
1808
diff
changeset
|
1256 [('m', 'message', '', 'commit message'), |
7596611ab3d5
Whitespace, tab and formatting cleanups, mainly in mq.py
Thomas Arendsen Hein <thomas@intevation.de>
parents:
1808
diff
changeset
|
1257 ('f', 'force', None, 'force')], |
2185
5acd648770d0
Better help for mq: Corrected synopses, get qcommit options from commands.py.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
2097
diff
changeset
|
1258 'hg qnew [-m TEXT] [-f] PATCH'), |
1810
7596611ab3d5
Whitespace, tab and formatting cleanups, mainly in mq.py
Thomas Arendsen Hein <thomas@intevation.de>
parents:
1808
diff
changeset
|
1259 "qnext": (next, [], 'hg qnext'), |
7596611ab3d5
Whitespace, tab and formatting cleanups, mainly in mq.py
Thomas Arendsen Hein <thomas@intevation.de>
parents:
1808
diff
changeset
|
1260 "qprev": (prev, [], 'hg qprev'), |
7596611ab3d5
Whitespace, tab and formatting cleanups, mainly in mq.py
Thomas Arendsen Hein <thomas@intevation.de>
parents:
1808
diff
changeset
|
1261 "^qpop": |
7596611ab3d5
Whitespace, tab and formatting cleanups, mainly in mq.py
Thomas Arendsen Hein <thomas@intevation.de>
parents:
1808
diff
changeset
|
1262 (pop, |
7596611ab3d5
Whitespace, tab and formatting cleanups, mainly in mq.py
Thomas Arendsen Hein <thomas@intevation.de>
parents:
1808
diff
changeset
|
1263 [('a', 'all', None, 'pop all patches'), |
7596611ab3d5
Whitespace, tab and formatting cleanups, mainly in mq.py
Thomas Arendsen Hein <thomas@intevation.de>
parents:
1808
diff
changeset
|
1264 ('n', 'name', '', 'queue name to pop'), |
7596611ab3d5
Whitespace, tab and formatting cleanups, mainly in mq.py
Thomas Arendsen Hein <thomas@intevation.de>
parents:
1808
diff
changeset
|
1265 ('f', 'force', None, 'forget any local changes')], |
2185
5acd648770d0
Better help for mq: Corrected synopses, get qcommit options from commands.py.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
2097
diff
changeset
|
1266 'hg qpop [-a] [-n NAME] [-f] [PATCH | INDEX]'), |
1810
7596611ab3d5
Whitespace, tab and formatting cleanups, mainly in mq.py
Thomas Arendsen Hein <thomas@intevation.de>
parents:
1808
diff
changeset
|
1267 "^qpush": |
7596611ab3d5
Whitespace, tab and formatting cleanups, mainly in mq.py
Thomas Arendsen Hein <thomas@intevation.de>
parents:
1808
diff
changeset
|
1268 (push, |
7596611ab3d5
Whitespace, tab and formatting cleanups, mainly in mq.py
Thomas Arendsen Hein <thomas@intevation.de>
parents:
1808
diff
changeset
|
1269 [('f', 'force', None, 'apply if the patch has rejects'), |
7596611ab3d5
Whitespace, tab and formatting cleanups, mainly in mq.py
Thomas Arendsen Hein <thomas@intevation.de>
parents:
1808
diff
changeset
|
1270 ('l', 'list', None, 'list patch name in commit text'), |
7596611ab3d5
Whitespace, tab and formatting cleanups, mainly in mq.py
Thomas Arendsen Hein <thomas@intevation.de>
parents:
1808
diff
changeset
|
1271 ('a', 'all', None, 'apply all patches'), |
7596611ab3d5
Whitespace, tab and formatting cleanups, mainly in mq.py
Thomas Arendsen Hein <thomas@intevation.de>
parents:
1808
diff
changeset
|
1272 ('m', 'merge', None, 'merge from another queue'), |
7596611ab3d5
Whitespace, tab and formatting cleanups, mainly in mq.py
Thomas Arendsen Hein <thomas@intevation.de>
parents:
1808
diff
changeset
|
1273 ('n', 'name', '', 'merge queue name')], |
2185
5acd648770d0
Better help for mq: Corrected synopses, get qcommit options from commands.py.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
2097
diff
changeset
|
1274 'hg qpush [-f] [-l] [-a] [-m] [-n NAME] [PATCH | INDEX]'), |
1810
7596611ab3d5
Whitespace, tab and formatting cleanups, mainly in mq.py
Thomas Arendsen Hein <thomas@intevation.de>
parents:
1808
diff
changeset
|
1275 "^qrefresh": |
7596611ab3d5
Whitespace, tab and formatting cleanups, mainly in mq.py
Thomas Arendsen Hein <thomas@intevation.de>
parents:
1808
diff
changeset
|
1276 (refresh, |
7596611ab3d5
Whitespace, tab and formatting cleanups, mainly in mq.py
Thomas Arendsen Hein <thomas@intevation.de>
parents:
1808
diff
changeset
|
1277 [('s', 'short', None, 'short refresh')], |
2185
5acd648770d0
Better help for mq: Corrected synopses, get qcommit options from commands.py.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
2097
diff
changeset
|
1278 'hg qrefresh [-s]'), |
1810
7596611ab3d5
Whitespace, tab and formatting cleanups, mainly in mq.py
Thomas Arendsen Hein <thomas@intevation.de>
parents:
1808
diff
changeset
|
1279 "qrestore": |
7596611ab3d5
Whitespace, tab and formatting cleanups, mainly in mq.py
Thomas Arendsen Hein <thomas@intevation.de>
parents:
1808
diff
changeset
|
1280 (restore, |
7596611ab3d5
Whitespace, tab and formatting cleanups, mainly in mq.py
Thomas Arendsen Hein <thomas@intevation.de>
parents:
1808
diff
changeset
|
1281 [('d', 'delete', None, 'delete save entry'), |
7596611ab3d5
Whitespace, tab and formatting cleanups, mainly in mq.py
Thomas Arendsen Hein <thomas@intevation.de>
parents:
1808
diff
changeset
|
1282 ('u', 'update', None, 'update queue working dir')], |
2185
5acd648770d0
Better help for mq: Corrected synopses, get qcommit options from commands.py.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
2097
diff
changeset
|
1283 'hg qrestore [-d] [-u] REV'), |
1810
7596611ab3d5
Whitespace, tab and formatting cleanups, mainly in mq.py
Thomas Arendsen Hein <thomas@intevation.de>
parents:
1808
diff
changeset
|
1284 "qsave": |
7596611ab3d5
Whitespace, tab and formatting cleanups, mainly in mq.py
Thomas Arendsen Hein <thomas@intevation.de>
parents:
1808
diff
changeset
|
1285 (save, |
7596611ab3d5
Whitespace, tab and formatting cleanups, mainly in mq.py
Thomas Arendsen Hein <thomas@intevation.de>
parents:
1808
diff
changeset
|
1286 [('m', 'message', '', 'commit message'), |
7596611ab3d5
Whitespace, tab and formatting cleanups, mainly in mq.py
Thomas Arendsen Hein <thomas@intevation.de>
parents:
1808
diff
changeset
|
1287 ('c', 'copy', None, 'copy patch directory'), |
7596611ab3d5
Whitespace, tab and formatting cleanups, mainly in mq.py
Thomas Arendsen Hein <thomas@intevation.de>
parents:
1808
diff
changeset
|
1288 ('n', 'name', '', 'copy directory name'), |
7596611ab3d5
Whitespace, tab and formatting cleanups, mainly in mq.py
Thomas Arendsen Hein <thomas@intevation.de>
parents:
1808
diff
changeset
|
1289 ('e', 'empty', None, 'clear queue status file'), |
7596611ab3d5
Whitespace, tab and formatting cleanups, mainly in mq.py
Thomas Arendsen Hein <thomas@intevation.de>
parents:
1808
diff
changeset
|
1290 ('f', 'force', None, 'force copy')], |
2185
5acd648770d0
Better help for mq: Corrected synopses, get qcommit options from commands.py.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
2097
diff
changeset
|
1291 'hg qsave [-m TEXT] [-c] [-n NAME] [-e] [-f]'), |
1810
7596611ab3d5
Whitespace, tab and formatting cleanups, mainly in mq.py
Thomas Arendsen Hein <thomas@intevation.de>
parents:
1808
diff
changeset
|
1292 "qseries": |
7596611ab3d5
Whitespace, tab and formatting cleanups, mainly in mq.py
Thomas Arendsen Hein <thomas@intevation.de>
parents:
1808
diff
changeset
|
1293 (series, |
7596611ab3d5
Whitespace, tab and formatting cleanups, mainly in mq.py
Thomas Arendsen Hein <thomas@intevation.de>
parents:
1808
diff
changeset
|
1294 [('m', 'missing', None, 'print patches not in series')], |
2185
5acd648770d0
Better help for mq: Corrected synopses, get qcommit options from commands.py.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
2097
diff
changeset
|
1295 'hg qseries [-m]'), |
1810
7596611ab3d5
Whitespace, tab and formatting cleanups, mainly in mq.py
Thomas Arendsen Hein <thomas@intevation.de>
parents:
1808
diff
changeset
|
1296 "^strip": |
7596611ab3d5
Whitespace, tab and formatting cleanups, mainly in mq.py
Thomas Arendsen Hein <thomas@intevation.de>
parents:
1808
diff
changeset
|
1297 (strip, |
7596611ab3d5
Whitespace, tab and formatting cleanups, mainly in mq.py
Thomas Arendsen Hein <thomas@intevation.de>
parents:
1808
diff
changeset
|
1298 [('f', 'force', None, 'force multi-head removal'), |
7596611ab3d5
Whitespace, tab and formatting cleanups, mainly in mq.py
Thomas Arendsen Hein <thomas@intevation.de>
parents:
1808
diff
changeset
|
1299 ('b', 'backup', None, 'bundle unrelated changesets'), |
7596611ab3d5
Whitespace, tab and formatting cleanups, mainly in mq.py
Thomas Arendsen Hein <thomas@intevation.de>
parents:
1808
diff
changeset
|
1300 ('n', 'nobackup', None, 'no backups')], |
2185
5acd648770d0
Better help for mq: Corrected synopses, get qcommit options from commands.py.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
2097
diff
changeset
|
1301 'hg strip [-f] [-b] [-n] REV'), |
1810
7596611ab3d5
Whitespace, tab and formatting cleanups, mainly in mq.py
Thomas Arendsen Hein <thomas@intevation.de>
parents:
1808
diff
changeset
|
1302 "qtop": (top, [], 'hg qtop'), |
2185
5acd648770d0
Better help for mq: Corrected synopses, get qcommit options from commands.py.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
2097
diff
changeset
|
1303 "qunapplied": (unapplied, [], 'hg qunapplied [PATCH]'), |
1810
7596611ab3d5
Whitespace, tab and formatting cleanups, mainly in mq.py
Thomas Arendsen Hein <thomas@intevation.de>
parents:
1808
diff
changeset
|
1304 "qversion": (version, [], 'hg qversion') |
1808 | 1305 } |
1306 |