##// END OF EJS Templates
MQ: tidy up if a qpush is interrupted....
Bryan O'Sullivan -
r4418:0532491f default
parent child Browse files
Show More
@@ -1,2205 +1,2238
1 # queue.py - patch queues for mercurial
1 # queue.py - patch queues for mercurial
2 #
2 #
3 # Copyright 2005, 2006 Chris Mason <mason@suse.com>
3 # Copyright 2005, 2006 Chris Mason <mason@suse.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 '''patch management and development
8 '''patch management and development
9
9
10 This extension lets you work with a stack of patches in a Mercurial
10 This extension lets you work with a stack of patches in a Mercurial
11 repository. It manages two stacks of patches - all known patches, and
11 repository. It manages two stacks of patches - all known patches, and
12 applied patches (subset of known patches).
12 applied patches (subset of known patches).
13
13
14 Known patches are represented as patch files in the .hg/patches
14 Known patches are represented as patch files in the .hg/patches
15 directory. Applied patches are both patch files and changesets.
15 directory. Applied patches are both patch files and changesets.
16
16
17 Common tasks (use "hg help command" for more details):
17 Common tasks (use "hg help command" for more details):
18
18
19 prepare repository to work with patches qinit
19 prepare repository to work with patches qinit
20 create new patch qnew
20 create new patch qnew
21 import existing patch qimport
21 import existing patch qimport
22
22
23 print patch series qseries
23 print patch series qseries
24 print applied patches qapplied
24 print applied patches qapplied
25 print name of top applied patch qtop
25 print name of top applied patch qtop
26
26
27 add known patch to applied stack qpush
27 add known patch to applied stack qpush
28 remove patch from applied stack qpop
28 remove patch from applied stack qpop
29 refresh contents of top applied patch qrefresh
29 refresh contents of top applied patch qrefresh
30 '''
30 '''
31
31
32 from mercurial.demandload import *
32 from mercurial.demandload import *
33 from mercurial.i18n import gettext as _
33 from mercurial.i18n import gettext as _
34 from mercurial import commands
34 from mercurial import commands
35 demandload(globals(), "os sys re struct traceback errno bz2")
35 demandload(globals(), "os sys re struct traceback errno bz2")
36 demandload(globals(), "mercurial:cmdutil,hg,patch,revlog,util,changegroup")
36 demandload(globals(), "mercurial:cmdutil,hg,patch,revlog,util,changegroup")
37
37
38 commands.norepo += " qclone qversion"
38 commands.norepo += " qclone qversion"
39
39
40 class statusentry:
40 class statusentry:
41 def __init__(self, rev, name=None):
41 def __init__(self, rev, name=None):
42 if not name:
42 if not name:
43 fields = rev.split(':', 1)
43 fields = rev.split(':', 1)
44 if len(fields) == 2:
44 if len(fields) == 2:
45 self.rev, self.name = fields
45 self.rev, self.name = fields
46 else:
46 else:
47 self.rev, self.name = None, None
47 self.rev, self.name = None, None
48 else:
48 else:
49 self.rev, self.name = rev, name
49 self.rev, self.name = rev, name
50
50
51 def __str__(self):
51 def __str__(self):
52 return self.rev + ':' + self.name
52 return self.rev + ':' + self.name
53
53
54 class queue:
54 class queue:
55 def __init__(self, ui, path, patchdir=None):
55 def __init__(self, ui, path, patchdir=None):
56 self.basepath = path
56 self.basepath = path
57 self.path = patchdir or os.path.join(path, "patches")
57 self.path = patchdir or os.path.join(path, "patches")
58 self.opener = util.opener(self.path)
58 self.opener = util.opener(self.path)
59 self.ui = ui
59 self.ui = ui
60 self.applied = []
60 self.applied = []
61 self.full_series = []
61 self.full_series = []
62 self.applied_dirty = 0
62 self.applied_dirty = 0
63 self.series_dirty = 0
63 self.series_dirty = 0
64 self.series_path = "series"
64 self.series_path = "series"
65 self.status_path = "status"
65 self.status_path = "status"
66 self.guards_path = "guards"
66 self.guards_path = "guards"
67 self.active_guards = None
67 self.active_guards = None
68 self.guards_dirty = False
68 self.guards_dirty = False
69 self._diffopts = None
69 self._diffopts = None
70
70
71 if os.path.exists(self.join(self.series_path)):
71 if os.path.exists(self.join(self.series_path)):
72 self.full_series = self.opener(self.series_path).read().splitlines()
72 self.full_series = self.opener(self.series_path).read().splitlines()
73 self.parse_series()
73 self.parse_series()
74
74
75 if os.path.exists(self.join(self.status_path)):
75 if os.path.exists(self.join(self.status_path)):
76 lines = self.opener(self.status_path).read().splitlines()
76 lines = self.opener(self.status_path).read().splitlines()
77 self.applied = [statusentry(l) for l in lines]
77 self.applied = [statusentry(l) for l in lines]
78
78
79 def diffopts(self):
79 def diffopts(self):
80 if self._diffopts is None:
80 if self._diffopts is None:
81 self._diffopts = patch.diffopts(self.ui)
81 self._diffopts = patch.diffopts(self.ui)
82 return self._diffopts
82 return self._diffopts
83
83
84 def join(self, *p):
84 def join(self, *p):
85 return os.path.join(self.path, *p)
85 return os.path.join(self.path, *p)
86
86
87 def find_series(self, patch):
87 def find_series(self, patch):
88 pre = re.compile("(\s*)([^#]+)")
88 pre = re.compile("(\s*)([^#]+)")
89 index = 0
89 index = 0
90 for l in self.full_series:
90 for l in self.full_series:
91 m = pre.match(l)
91 m = pre.match(l)
92 if m:
92 if m:
93 s = m.group(2)
93 s = m.group(2)
94 s = s.rstrip()
94 s = s.rstrip()
95 if s == patch:
95 if s == patch:
96 return index
96 return index
97 index += 1
97 index += 1
98 return None
98 return None
99
99
100 guard_re = re.compile(r'\s?#([-+][^-+# \t\r\n\f][^# \t\r\n\f]*)')
100 guard_re = re.compile(r'\s?#([-+][^-+# \t\r\n\f][^# \t\r\n\f]*)')
101
101
102 def parse_series(self):
102 def parse_series(self):
103 self.series = []
103 self.series = []
104 self.series_guards = []
104 self.series_guards = []
105 for l in self.full_series:
105 for l in self.full_series:
106 h = l.find('#')
106 h = l.find('#')
107 if h == -1:
107 if h == -1:
108 patch = l
108 patch = l
109 comment = ''
109 comment = ''
110 elif h == 0:
110 elif h == 0:
111 continue
111 continue
112 else:
112 else:
113 patch = l[:h]
113 patch = l[:h]
114 comment = l[h:]
114 comment = l[h:]
115 patch = patch.strip()
115 patch = patch.strip()
116 if patch:
116 if patch:
117 if patch in self.series:
117 if patch in self.series:
118 raise util.Abort(_('%s appears more than once in %s') %
118 raise util.Abort(_('%s appears more than once in %s') %
119 (patch, self.join(self.series_path)))
119 (patch, self.join(self.series_path)))
120 self.series.append(patch)
120 self.series.append(patch)
121 self.series_guards.append(self.guard_re.findall(comment))
121 self.series_guards.append(self.guard_re.findall(comment))
122
122
123 def check_guard(self, guard):
123 def check_guard(self, guard):
124 bad_chars = '# \t\r\n\f'
124 bad_chars = '# \t\r\n\f'
125 first = guard[0]
125 first = guard[0]
126 for c in '-+':
126 for c in '-+':
127 if first == c:
127 if first == c:
128 return (_('guard %r starts with invalid character: %r') %
128 return (_('guard %r starts with invalid character: %r') %
129 (guard, c))
129 (guard, c))
130 for c in bad_chars:
130 for c in bad_chars:
131 if c in guard:
131 if c in guard:
132 return _('invalid character in guard %r: %r') % (guard, c)
132 return _('invalid character in guard %r: %r') % (guard, c)
133
133
134 def set_active(self, guards):
134 def set_active(self, guards):
135 for guard in guards:
135 for guard in guards:
136 bad = self.check_guard(guard)
136 bad = self.check_guard(guard)
137 if bad:
137 if bad:
138 raise util.Abort(bad)
138 raise util.Abort(bad)
139 guards = dict.fromkeys(guards).keys()
139 guards = dict.fromkeys(guards).keys()
140 guards.sort()
140 guards.sort()
141 self.ui.debug('active guards: %s\n' % ' '.join(guards))
141 self.ui.debug('active guards: %s\n' % ' '.join(guards))
142 self.active_guards = guards
142 self.active_guards = guards
143 self.guards_dirty = True
143 self.guards_dirty = True
144
144
145 def active(self):
145 def active(self):
146 if self.active_guards is None:
146 if self.active_guards is None:
147 self.active_guards = []
147 self.active_guards = []
148 try:
148 try:
149 guards = self.opener(self.guards_path).read().split()
149 guards = self.opener(self.guards_path).read().split()
150 except IOError, err:
150 except IOError, err:
151 if err.errno != errno.ENOENT: raise
151 if err.errno != errno.ENOENT: raise
152 guards = []
152 guards = []
153 for i, guard in enumerate(guards):
153 for i, guard in enumerate(guards):
154 bad = self.check_guard(guard)
154 bad = self.check_guard(guard)
155 if bad:
155 if bad:
156 self.ui.warn('%s:%d: %s\n' %
156 self.ui.warn('%s:%d: %s\n' %
157 (self.join(self.guards_path), i + 1, bad))
157 (self.join(self.guards_path), i + 1, bad))
158 else:
158 else:
159 self.active_guards.append(guard)
159 self.active_guards.append(guard)
160 return self.active_guards
160 return self.active_guards
161
161
162 def set_guards(self, idx, guards):
162 def set_guards(self, idx, guards):
163 for g in guards:
163 for g in guards:
164 if len(g) < 2:
164 if len(g) < 2:
165 raise util.Abort(_('guard %r too short') % g)
165 raise util.Abort(_('guard %r too short') % g)
166 if g[0] not in '-+':
166 if g[0] not in '-+':
167 raise util.Abort(_('guard %r starts with invalid char') % g)
167 raise util.Abort(_('guard %r starts with invalid char') % g)
168 bad = self.check_guard(g[1:])
168 bad = self.check_guard(g[1:])
169 if bad:
169 if bad:
170 raise util.Abort(bad)
170 raise util.Abort(bad)
171 drop = self.guard_re.sub('', self.full_series[idx])
171 drop = self.guard_re.sub('', self.full_series[idx])
172 self.full_series[idx] = drop + ''.join([' #' + g for g in guards])
172 self.full_series[idx] = drop + ''.join([' #' + g for g in guards])
173 self.parse_series()
173 self.parse_series()
174 self.series_dirty = True
174 self.series_dirty = True
175
175
176 def pushable(self, idx):
176 def pushable(self, idx):
177 if isinstance(idx, str):
177 if isinstance(idx, str):
178 idx = self.series.index(idx)
178 idx = self.series.index(idx)
179 patchguards = self.series_guards[idx]
179 patchguards = self.series_guards[idx]
180 if not patchguards:
180 if not patchguards:
181 return True, None
181 return True, None
182 default = False
182 default = False
183 guards = self.active()
183 guards = self.active()
184 exactneg = [g for g in patchguards if g[0] == '-' and g[1:] in guards]
184 exactneg = [g for g in patchguards if g[0] == '-' and g[1:] in guards]
185 if exactneg:
185 if exactneg:
186 return False, exactneg[0]
186 return False, exactneg[0]
187 pos = [g for g in patchguards if g[0] == '+']
187 pos = [g for g in patchguards if g[0] == '+']
188 exactpos = [g for g in pos if g[1:] in guards]
188 exactpos = [g for g in pos if g[1:] in guards]
189 if pos:
189 if pos:
190 if exactpos:
190 if exactpos:
191 return True, exactpos[0]
191 return True, exactpos[0]
192 return False, pos
192 return False, pos
193 return True, ''
193 return True, ''
194
194
195 def explain_pushable(self, idx, all_patches=False):
195 def explain_pushable(self, idx, all_patches=False):
196 write = all_patches and self.ui.write or self.ui.warn
196 write = all_patches and self.ui.write or self.ui.warn
197 if all_patches or self.ui.verbose:
197 if all_patches or self.ui.verbose:
198 if isinstance(idx, str):
198 if isinstance(idx, str):
199 idx = self.series.index(idx)
199 idx = self.series.index(idx)
200 pushable, why = self.pushable(idx)
200 pushable, why = self.pushable(idx)
201 if all_patches and pushable:
201 if all_patches and pushable:
202 if why is None:
202 if why is None:
203 write(_('allowing %s - no guards in effect\n') %
203 write(_('allowing %s - no guards in effect\n') %
204 self.series[idx])
204 self.series[idx])
205 else:
205 else:
206 if not why:
206 if not why:
207 write(_('allowing %s - no matching negative guards\n') %
207 write(_('allowing %s - no matching negative guards\n') %
208 self.series[idx])
208 self.series[idx])
209 else:
209 else:
210 write(_('allowing %s - guarded by %r\n') %
210 write(_('allowing %s - guarded by %r\n') %
211 (self.series[idx], why))
211 (self.series[idx], why))
212 if not pushable:
212 if not pushable:
213 if why:
213 if why:
214 write(_('skipping %s - guarded by %r\n') %
214 write(_('skipping %s - guarded by %r\n') %
215 (self.series[idx], why))
215 (self.series[idx], why))
216 else:
216 else:
217 write(_('skipping %s - no matching guards\n') %
217 write(_('skipping %s - no matching guards\n') %
218 self.series[idx])
218 self.series[idx])
219
219
220 def save_dirty(self):
220 def save_dirty(self):
221 def write_list(items, path):
221 def write_list(items, path):
222 fp = self.opener(path, 'w')
222 fp = self.opener(path, 'w')
223 for i in items:
223 for i in items:
224 print >> fp, i
224 print >> fp, i
225 fp.close()
225 fp.close()
226 if self.applied_dirty: write_list(map(str, self.applied), self.status_path)
226 if self.applied_dirty: write_list(map(str, self.applied), self.status_path)
227 if self.series_dirty: write_list(self.full_series, self.series_path)
227 if self.series_dirty: write_list(self.full_series, self.series_path)
228 if self.guards_dirty: write_list(self.active_guards, self.guards_path)
228 if self.guards_dirty: write_list(self.active_guards, self.guards_path)
229
229
230 def readheaders(self, patch):
230 def readheaders(self, patch):
231 def eatdiff(lines):
231 def eatdiff(lines):
232 while lines:
232 while lines:
233 l = lines[-1]
233 l = lines[-1]
234 if (l.startswith("diff -") or
234 if (l.startswith("diff -") or
235 l.startswith("Index:") or
235 l.startswith("Index:") or
236 l.startswith("===========")):
236 l.startswith("===========")):
237 del lines[-1]
237 del lines[-1]
238 else:
238 else:
239 break
239 break
240 def eatempty(lines):
240 def eatempty(lines):
241 while lines:
241 while lines:
242 l = lines[-1]
242 l = lines[-1]
243 if re.match('\s*$', l):
243 if re.match('\s*$', l):
244 del lines[-1]
244 del lines[-1]
245 else:
245 else:
246 break
246 break
247
247
248 pf = self.join(patch)
248 pf = self.join(patch)
249 message = []
249 message = []
250 comments = []
250 comments = []
251 user = None
251 user = None
252 date = None
252 date = None
253 format = None
253 format = None
254 subject = None
254 subject = None
255 diffstart = 0
255 diffstart = 0
256
256
257 for line in file(pf):
257 for line in file(pf):
258 line = line.rstrip()
258 line = line.rstrip()
259 if line.startswith('diff --git'):
259 if line.startswith('diff --git'):
260 diffstart = 2
260 diffstart = 2
261 break
261 break
262 if diffstart:
262 if diffstart:
263 if line.startswith('+++ '):
263 if line.startswith('+++ '):
264 diffstart = 2
264 diffstart = 2
265 break
265 break
266 if line.startswith("--- "):
266 if line.startswith("--- "):
267 diffstart = 1
267 diffstart = 1
268 continue
268 continue
269 elif format == "hgpatch":
269 elif format == "hgpatch":
270 # parse values when importing the result of an hg export
270 # parse values when importing the result of an hg export
271 if line.startswith("# User "):
271 if line.startswith("# User "):
272 user = line[7:]
272 user = line[7:]
273 elif line.startswith("# Date "):
273 elif line.startswith("# Date "):
274 date = line[7:]
274 date = line[7:]
275 elif not line.startswith("# ") and line:
275 elif not line.startswith("# ") and line:
276 message.append(line)
276 message.append(line)
277 format = None
277 format = None
278 elif line == '# HG changeset patch':
278 elif line == '# HG changeset patch':
279 format = "hgpatch"
279 format = "hgpatch"
280 elif (format != "tagdone" and (line.startswith("Subject: ") or
280 elif (format != "tagdone" and (line.startswith("Subject: ") or
281 line.startswith("subject: "))):
281 line.startswith("subject: "))):
282 subject = line[9:]
282 subject = line[9:]
283 format = "tag"
283 format = "tag"
284 elif (format != "tagdone" and (line.startswith("From: ") or
284 elif (format != "tagdone" and (line.startswith("From: ") or
285 line.startswith("from: "))):
285 line.startswith("from: "))):
286 user = line[6:]
286 user = line[6:]
287 format = "tag"
287 format = "tag"
288 elif format == "tag" and line == "":
288 elif format == "tag" and line == "":
289 # when looking for tags (subject: from: etc) they
289 # when looking for tags (subject: from: etc) they
290 # end once you find a blank line in the source
290 # end once you find a blank line in the source
291 format = "tagdone"
291 format = "tagdone"
292 elif message or line:
292 elif message or line:
293 message.append(line)
293 message.append(line)
294 comments.append(line)
294 comments.append(line)
295
295
296 eatdiff(message)
296 eatdiff(message)
297 eatdiff(comments)
297 eatdiff(comments)
298 eatempty(message)
298 eatempty(message)
299 eatempty(comments)
299 eatempty(comments)
300
300
301 # make sure message isn't empty
301 # make sure message isn't empty
302 if format and format.startswith("tag") and subject:
302 if format and format.startswith("tag") and subject:
303 message.insert(0, "")
303 message.insert(0, "")
304 message.insert(0, subject)
304 message.insert(0, subject)
305 return (message, comments, user, date, diffstart > 1)
305 return (message, comments, user, date, diffstart > 1)
306
306
307 def printdiff(self, repo, node1, node2=None, files=None,
307 def printdiff(self, repo, node1, node2=None, files=None,
308 fp=None, changes=None, opts={}):
308 fp=None, changes=None, opts={}):
309 fns, matchfn, anypats = cmdutil.matchpats(repo, files, opts)
309 fns, matchfn, anypats = cmdutil.matchpats(repo, files, opts)
310
310
311 patch.diff(repo, node1, node2, fns, match=matchfn,
311 patch.diff(repo, node1, node2, fns, match=matchfn,
312 fp=fp, changes=changes, opts=self.diffopts())
312 fp=fp, changes=changes, opts=self.diffopts())
313
313
314 def mergeone(self, repo, mergeq, head, patch, rev, wlock):
314 def mergeone(self, repo, mergeq, head, patch, rev, wlock):
315 # first try just applying the patch
315 # first try just applying the patch
316 (err, n) = self.apply(repo, [ patch ], update_status=False,
316 (err, n) = self.apply(repo, [ patch ], update_status=False,
317 strict=True, merge=rev, wlock=wlock)
317 strict=True, merge=rev, wlock=wlock)
318
318
319 if err == 0:
319 if err == 0:
320 return (err, n)
320 return (err, n)
321
321
322 if n is None:
322 if n is None:
323 raise util.Abort(_("apply failed for patch %s") % patch)
323 raise util.Abort(_("apply failed for patch %s") % patch)
324
324
325 self.ui.warn("patch didn't work out, merging %s\n" % patch)
325 self.ui.warn("patch didn't work out, merging %s\n" % patch)
326
326
327 # apply failed, strip away that rev and merge.
327 # apply failed, strip away that rev and merge.
328 hg.clean(repo, head, wlock=wlock)
328 hg.clean(repo, head, wlock=wlock)
329 self.strip(repo, n, update=False, backup='strip', wlock=wlock)
329 self.strip(repo, n, update=False, backup='strip', wlock=wlock)
330
330
331 c = repo.changelog.read(rev)
331 c = repo.changelog.read(rev)
332 ret = hg.merge(repo, rev, wlock=wlock)
332 ret = hg.merge(repo, rev, wlock=wlock)
333 if ret:
333 if ret:
334 raise util.Abort(_("update returned %d") % ret)
334 raise util.Abort(_("update returned %d") % ret)
335 n = repo.commit(None, c[4], c[1], force=1, wlock=wlock)
335 n = repo.commit(None, c[4], c[1], force=1, wlock=wlock)
336 if n == None:
336 if n == None:
337 raise util.Abort(_("repo commit failed"))
337 raise util.Abort(_("repo commit failed"))
338 try:
338 try:
339 message, comments, user, date, patchfound = mergeq.readheaders(patch)
339 message, comments, user, date, patchfound = mergeq.readheaders(patch)
340 except:
340 except:
341 raise util.Abort(_("unable to read %s") % patch)
341 raise util.Abort(_("unable to read %s") % patch)
342
342
343 patchf = self.opener(patch, "w")
343 patchf = self.opener(patch, "w")
344 if comments:
344 if comments:
345 comments = "\n".join(comments) + '\n\n'
345 comments = "\n".join(comments) + '\n\n'
346 patchf.write(comments)
346 patchf.write(comments)
347 self.printdiff(repo, head, n, fp=patchf)
347 self.printdiff(repo, head, n, fp=patchf)
348 patchf.close()
348 patchf.close()
349 return (0, n)
349 return (0, n)
350
350
351 def qparents(self, repo, rev=None):
351 def qparents(self, repo, rev=None):
352 if rev is None:
352 if rev is None:
353 (p1, p2) = repo.dirstate.parents()
353 (p1, p2) = repo.dirstate.parents()
354 if p2 == revlog.nullid:
354 if p2 == revlog.nullid:
355 return p1
355 return p1
356 if len(self.applied) == 0:
356 if len(self.applied) == 0:
357 return None
357 return None
358 return revlog.bin(self.applied[-1].rev)
358 return revlog.bin(self.applied[-1].rev)
359 pp = repo.changelog.parents(rev)
359 pp = repo.changelog.parents(rev)
360 if pp[1] != revlog.nullid:
360 if pp[1] != revlog.nullid:
361 arevs = [ x.rev for x in self.applied ]
361 arevs = [ x.rev for x in self.applied ]
362 p0 = revlog.hex(pp[0])
362 p0 = revlog.hex(pp[0])
363 p1 = revlog.hex(pp[1])
363 p1 = revlog.hex(pp[1])
364 if p0 in arevs:
364 if p0 in arevs:
365 return pp[0]
365 return pp[0]
366 if p1 in arevs:
366 if p1 in arevs:
367 return pp[1]
367 return pp[1]
368 return pp[0]
368 return pp[0]
369
369
370 def mergepatch(self, repo, mergeq, series, wlock):
370 def mergepatch(self, repo, mergeq, series, wlock):
371 if len(self.applied) == 0:
371 if len(self.applied) == 0:
372 # each of the patches merged in will have two parents. This
372 # each of the patches merged in will have two parents. This
373 # can confuse the qrefresh, qdiff, and strip code because it
373 # can confuse the qrefresh, qdiff, and strip code because it
374 # needs to know which parent is actually in the patch queue.
374 # needs to know which parent is actually in the patch queue.
375 # so, we insert a merge marker with only one parent. This way
375 # so, we insert a merge marker with only one parent. This way
376 # the first patch in the queue is never a merge patch
376 # the first patch in the queue is never a merge patch
377 #
377 #
378 pname = ".hg.patches.merge.marker"
378 pname = ".hg.patches.merge.marker"
379 n = repo.commit(None, '[mq]: merge marker', user=None, force=1,
379 n = repo.commit(None, '[mq]: merge marker', user=None, force=1,
380 wlock=wlock)
380 wlock=wlock)
381 self.applied.append(statusentry(revlog.hex(n), pname))
381 self.applied.append(statusentry(revlog.hex(n), pname))
382 self.applied_dirty = 1
382 self.applied_dirty = 1
383
383
384 head = self.qparents(repo)
384 head = self.qparents(repo)
385
385
386 for patch in series:
386 for patch in series:
387 patch = mergeq.lookup(patch, strict=True)
387 patch = mergeq.lookup(patch, strict=True)
388 if not patch:
388 if not patch:
389 self.ui.warn("patch %s does not exist\n" % patch)
389 self.ui.warn("patch %s does not exist\n" % patch)
390 return (1, None)
390 return (1, None)
391 pushable, reason = self.pushable(patch)
391 pushable, reason = self.pushable(patch)
392 if not pushable:
392 if not pushable:
393 self.explain_pushable(patch, all_patches=True)
393 self.explain_pushable(patch, all_patches=True)
394 continue
394 continue
395 info = mergeq.isapplied(patch)
395 info = mergeq.isapplied(patch)
396 if not info:
396 if not info:
397 self.ui.warn("patch %s is not applied\n" % patch)
397 self.ui.warn("patch %s is not applied\n" % patch)
398 return (1, None)
398 return (1, None)
399 rev = revlog.bin(info[1])
399 rev = revlog.bin(info[1])
400 (err, head) = self.mergeone(repo, mergeq, head, patch, rev, wlock)
400 (err, head) = self.mergeone(repo, mergeq, head, patch, rev, wlock)
401 if head:
401 if head:
402 self.applied.append(statusentry(revlog.hex(head), patch))
402 self.applied.append(statusentry(revlog.hex(head), patch))
403 self.applied_dirty = 1
403 self.applied_dirty = 1
404 if err:
404 if err:
405 return (err, head)
405 return (err, head)
406 return (0, head)
406 return (0, head)
407
407
408 def patch(self, repo, patchfile):
408 def patch(self, repo, patchfile):
409 '''Apply patchfile to the working directory.
409 '''Apply patchfile to the working directory.
410 patchfile: file name of patch'''
410 patchfile: file name of patch'''
411 files = {}
411 files = {}
412 try:
412 try:
413 fuzz = patch.patch(patchfile, self.ui, strip=1, cwd=repo.root,
413 fuzz = patch.patch(patchfile, self.ui, strip=1, cwd=repo.root,
414 files=files)
414 files=files)
415 except Exception, inst:
415 except Exception, inst:
416 self.ui.note(str(inst) + '\n')
416 self.ui.note(str(inst) + '\n')
417 if not self.ui.verbose:
417 if not self.ui.verbose:
418 self.ui.warn("patch failed, unable to continue (try -v)\n")
418 self.ui.warn("patch failed, unable to continue (try -v)\n")
419 return (False, files, False)
419 return (False, files, False)
420
420
421 return (True, files, fuzz)
421 return (True, files, fuzz)
422
422
423 def apply(self, repo, series, list=False, update_status=True,
423 def apply(self, repo, series, list=False, update_status=True,
424 strict=False, patchdir=None, merge=None, wlock=None):
424 strict=False, patchdir=None, merge=None, wlock=None,
425 all_files={}):
426 tr = repo.transaction()
427 try:
428 ret = self._apply(tr, repo, series, list, update_status,
429 strict, patchdir, merge, wlock,
430 all_files=all_files)
431 tr.close()
432 self.save_dirty()
433 return ret
434 except:
435 try:
436 tr.abort()
437 finally:
438 repo.reload()
439 repo.wreload()
440 raise
441
442 def _apply(self, tr, repo, series, list=False, update_status=True,
443 strict=False, patchdir=None, merge=None, wlock=None,
444 all_files={}):
425 # TODO unify with commands.py
445 # TODO unify with commands.py
426 if not patchdir:
446 if not patchdir:
427 patchdir = self.path
447 patchdir = self.path
428 err = 0
448 err = 0
429 if not wlock:
449 if not wlock:
430 wlock = repo.wlock()
450 wlock = repo.wlock()
431 lock = repo.lock()
451 lock = repo.lock()
432 tr = repo.transaction()
433 n = None
452 n = None
434 for patchname in series:
453 for patchname in series:
435 pushable, reason = self.pushable(patchname)
454 pushable, reason = self.pushable(patchname)
436 if not pushable:
455 if not pushable:
437 self.explain_pushable(patchname, all_patches=True)
456 self.explain_pushable(patchname, all_patches=True)
438 continue
457 continue
439 self.ui.warn("applying %s\n" % patchname)
458 self.ui.warn("applying %s\n" % patchname)
440 pf = os.path.join(patchdir, patchname)
459 pf = os.path.join(patchdir, patchname)
441
460
442 try:
461 try:
443 message, comments, user, date, patchfound = self.readheaders(patchname)
462 message, comments, user, date, patchfound = self.readheaders(patchname)
444 except:
463 except:
445 self.ui.warn("Unable to read %s\n" % patchname)
464 self.ui.warn("Unable to read %s\n" % patchname)
446 err = 1
465 err = 1
447 break
466 break
448
467
449 if not message:
468 if not message:
450 message = "imported patch %s\n" % patchname
469 message = "imported patch %s\n" % patchname
451 else:
470 else:
452 if list:
471 if list:
453 message.append("\nimported patch %s" % patchname)
472 message.append("\nimported patch %s" % patchname)
454 message = '\n'.join(message)
473 message = '\n'.join(message)
455
474
456 (patcherr, files, fuzz) = self.patch(repo, pf)
475 (patcherr, files, fuzz) = self.patch(repo, pf)
476 all_files.update(files)
457 patcherr = not patcherr
477 patcherr = not patcherr
458
478
459 if merge and files:
479 if merge and files:
460 # Mark as removed/merged and update dirstate parent info
480 # Mark as removed/merged and update dirstate parent info
461 removed = []
481 removed = []
462 merged = []
482 merged = []
463 for f in files:
483 for f in files:
464 if os.path.exists(repo.dirstate.wjoin(f)):
484 if os.path.exists(repo.dirstate.wjoin(f)):
465 merged.append(f)
485 merged.append(f)
466 else:
486 else:
467 removed.append(f)
487 removed.append(f)
468 repo.dirstate.update(repo.dirstate.filterfiles(removed), 'r')
488 repo.dirstate.update(repo.dirstate.filterfiles(removed), 'r')
469 repo.dirstate.update(repo.dirstate.filterfiles(merged), 'm')
489 repo.dirstate.update(repo.dirstate.filterfiles(merged), 'm')
470 p1, p2 = repo.dirstate.parents()
490 p1, p2 = repo.dirstate.parents()
471 repo.dirstate.setparents(p1, merge)
491 repo.dirstate.setparents(p1, merge)
472 files = patch.updatedir(self.ui, repo, files, wlock=wlock)
492 files = patch.updatedir(self.ui, repo, files, wlock=wlock)
473 n = repo.commit(files, message, user, date, force=1, lock=lock,
493 n = repo.commit(files, message, user, date, force=1, lock=lock,
474 wlock=wlock)
494 wlock=wlock)
475
495
476 if n == None:
496 if n == None:
477 raise util.Abort(_("repo commit failed"))
497 raise util.Abort(_("repo commit failed"))
478
498
479 if update_status:
499 if update_status:
480 self.applied.append(statusentry(revlog.hex(n), patchname))
500 self.applied.append(statusentry(revlog.hex(n), patchname))
481
501
482 if patcherr:
502 if patcherr:
483 if not patchfound:
503 if not patchfound:
484 self.ui.warn("patch %s is empty\n" % patchname)
504 self.ui.warn("patch %s is empty\n" % patchname)
485 err = 0
505 err = 0
486 else:
506 else:
487 self.ui.warn("patch failed, rejects left in working dir\n")
507 self.ui.warn("patch failed, rejects left in working dir\n")
488 err = 1
508 err = 1
489 break
509 break
490
510
491 if fuzz and strict:
511 if fuzz and strict:
492 self.ui.warn("fuzz found when applying patch, stopping\n")
512 self.ui.warn("fuzz found when applying patch, stopping\n")
493 err = 1
513 err = 1
494 break
514 break
495 tr.close()
496 return (err, n)
515 return (err, n)
497
516
498 def delete(self, repo, patches, opts):
517 def delete(self, repo, patches, opts):
499 realpatches = []
518 realpatches = []
500 for patch in patches:
519 for patch in patches:
501 patch = self.lookup(patch, strict=True)
520 patch = self.lookup(patch, strict=True)
502 info = self.isapplied(patch)
521 info = self.isapplied(patch)
503 if info:
522 if info:
504 raise util.Abort(_("cannot delete applied patch %s") % patch)
523 raise util.Abort(_("cannot delete applied patch %s") % patch)
505 if patch not in self.series:
524 if patch not in self.series:
506 raise util.Abort(_("patch %s not in series file") % patch)
525 raise util.Abort(_("patch %s not in series file") % patch)
507 realpatches.append(patch)
526 realpatches.append(patch)
508
527
509 appliedbase = 0
528 appliedbase = 0
510 if opts.get('rev'):
529 if opts.get('rev'):
511 if not self.applied:
530 if not self.applied:
512 raise util.Abort(_('no patches applied'))
531 raise util.Abort(_('no patches applied'))
513 revs = cmdutil.revrange(repo, opts['rev'])
532 revs = cmdutil.revrange(repo, opts['rev'])
514 if len(revs) > 1 and revs[0] > revs[1]:
533 if len(revs) > 1 and revs[0] > revs[1]:
515 revs.reverse()
534 revs.reverse()
516 for rev in revs:
535 for rev in revs:
517 if appliedbase >= len(self.applied):
536 if appliedbase >= len(self.applied):
518 raise util.Abort(_("revision %d is not managed") % rev)
537 raise util.Abort(_("revision %d is not managed") % rev)
519
538
520 base = revlog.bin(self.applied[appliedbase].rev)
539 base = revlog.bin(self.applied[appliedbase].rev)
521 node = repo.changelog.node(rev)
540 node = repo.changelog.node(rev)
522 if node != base:
541 if node != base:
523 raise util.Abort(_("cannot delete revision %d above "
542 raise util.Abort(_("cannot delete revision %d above "
524 "applied patches") % rev)
543 "applied patches") % rev)
525 realpatches.append(self.applied[appliedbase].name)
544 realpatches.append(self.applied[appliedbase].name)
526 appliedbase += 1
545 appliedbase += 1
527
546
528 if not opts.get('keep'):
547 if not opts.get('keep'):
529 r = self.qrepo()
548 r = self.qrepo()
530 if r:
549 if r:
531 r.remove(realpatches, True)
550 r.remove(realpatches, True)
532 else:
551 else:
533 for p in realpatches:
552 for p in realpatches:
534 os.unlink(self.join(p))
553 os.unlink(self.join(p))
535
554
536 if appliedbase:
555 if appliedbase:
537 del self.applied[:appliedbase]
556 del self.applied[:appliedbase]
538 self.applied_dirty = 1
557 self.applied_dirty = 1
539 indices = [self.find_series(p) for p in realpatches]
558 indices = [self.find_series(p) for p in realpatches]
540 indices.sort()
559 indices.sort()
541 for i in indices[-1::-1]:
560 for i in indices[-1::-1]:
542 del self.full_series[i]
561 del self.full_series[i]
543 self.parse_series()
562 self.parse_series()
544 self.series_dirty = 1
563 self.series_dirty = 1
545
564
546 def check_toppatch(self, repo):
565 def check_toppatch(self, repo):
547 if len(self.applied) > 0:
566 if len(self.applied) > 0:
548 top = revlog.bin(self.applied[-1].rev)
567 top = revlog.bin(self.applied[-1].rev)
549 pp = repo.dirstate.parents()
568 pp = repo.dirstate.parents()
550 if top not in pp:
569 if top not in pp:
551 raise util.Abort(_("queue top not at same revision as working directory"))
570 raise util.Abort(_("queue top not at same revision as working directory"))
552 return top
571 return top
553 return None
572 return None
554 def check_localchanges(self, repo, force=False, refresh=True):
573 def check_localchanges(self, repo, force=False, refresh=True):
555 m, a, r, d = repo.status()[:4]
574 m, a, r, d = repo.status()[:4]
556 if m or a or r or d:
575 if m or a or r or d:
557 if not force:
576 if not force:
558 if refresh:
577 if refresh:
559 raise util.Abort(_("local changes found, refresh first"))
578 raise util.Abort(_("local changes found, refresh first"))
560 else:
579 else:
561 raise util.Abort(_("local changes found"))
580 raise util.Abort(_("local changes found"))
562 return m, a, r, d
581 return m, a, r, d
563 def new(self, repo, patch, msg=None, force=None):
582 def new(self, repo, patch, msg=None, force=None):
564 if os.path.exists(self.join(patch)):
583 if os.path.exists(self.join(patch)):
565 raise util.Abort(_('patch "%s" already exists') % patch)
584 raise util.Abort(_('patch "%s" already exists') % patch)
566 m, a, r, d = self.check_localchanges(repo, force)
585 m, a, r, d = self.check_localchanges(repo, force)
567 commitfiles = m + a + r
586 commitfiles = m + a + r
568 self.check_toppatch(repo)
587 self.check_toppatch(repo)
569 wlock = repo.wlock()
588 wlock = repo.wlock()
570 insert = self.full_series_end()
589 insert = self.full_series_end()
571 if msg:
590 if msg:
572 n = repo.commit(commitfiles, "[mq]: %s" % msg, force=True,
591 n = repo.commit(commitfiles, "[mq]: %s" % msg, force=True,
573 wlock=wlock)
592 wlock=wlock)
574 else:
593 else:
575 n = repo.commit(commitfiles,
594 n = repo.commit(commitfiles,
576 "New patch: %s" % patch, force=True, wlock=wlock)
595 "New patch: %s" % patch, force=True, wlock=wlock)
577 if n == None:
596 if n == None:
578 raise util.Abort(_("repo commit failed"))
597 raise util.Abort(_("repo commit failed"))
579 self.full_series[insert:insert] = [patch]
598 self.full_series[insert:insert] = [patch]
580 self.applied.append(statusentry(revlog.hex(n), patch))
599 self.applied.append(statusentry(revlog.hex(n), patch))
581 self.parse_series()
600 self.parse_series()
582 self.series_dirty = 1
601 self.series_dirty = 1
583 self.applied_dirty = 1
602 self.applied_dirty = 1
584 p = self.opener(patch, "w")
603 p = self.opener(patch, "w")
585 if msg:
604 if msg:
586 msg = msg + "\n"
605 msg = msg + "\n"
587 p.write(msg)
606 p.write(msg)
588 p.close()
607 p.close()
589 wlock = None
608 wlock = None
590 r = self.qrepo()
609 r = self.qrepo()
591 if r: r.add([patch])
610 if r: r.add([patch])
592 if commitfiles:
611 if commitfiles:
593 self.refresh(repo, short=True)
612 self.refresh(repo, short=True)
594
613
595 def strip(self, repo, rev, update=True, backup="all", wlock=None):
614 def strip(self, repo, rev, update=True, backup="all", wlock=None):
596 def limitheads(chlog, stop):
615 def limitheads(chlog, stop):
597 """return the list of all nodes that have no children"""
616 """return the list of all nodes that have no children"""
598 p = {}
617 p = {}
599 h = []
618 h = []
600 stoprev = 0
619 stoprev = 0
601 if stop in chlog.nodemap:
620 if stop in chlog.nodemap:
602 stoprev = chlog.rev(stop)
621 stoprev = chlog.rev(stop)
603
622
604 for r in xrange(chlog.count() - 1, -1, -1):
623 for r in xrange(chlog.count() - 1, -1, -1):
605 n = chlog.node(r)
624 n = chlog.node(r)
606 if n not in p:
625 if n not in p:
607 h.append(n)
626 h.append(n)
608 if n == stop:
627 if n == stop:
609 break
628 break
610 if r < stoprev:
629 if r < stoprev:
611 break
630 break
612 for pn in chlog.parents(n):
631 for pn in chlog.parents(n):
613 p[pn] = 1
632 p[pn] = 1
614 return h
633 return h
615
634
616 def bundle(cg):
635 def bundle(cg):
617 backupdir = repo.join("strip-backup")
636 backupdir = repo.join("strip-backup")
618 if not os.path.isdir(backupdir):
637 if not os.path.isdir(backupdir):
619 os.mkdir(backupdir)
638 os.mkdir(backupdir)
620 name = os.path.join(backupdir, "%s" % revlog.short(rev))
639 name = os.path.join(backupdir, "%s" % revlog.short(rev))
621 name = savename(name)
640 name = savename(name)
622 self.ui.warn("saving bundle to %s\n" % name)
641 self.ui.warn("saving bundle to %s\n" % name)
623 return changegroup.writebundle(cg, name, "HG10BZ")
642 return changegroup.writebundle(cg, name, "HG10BZ")
624
643
625 def stripall(rev, revnum):
644 def stripall(rev, revnum):
626 cl = repo.changelog
645 cl = repo.changelog
627 c = cl.read(rev)
646 c = cl.read(rev)
628 mm = repo.manifest.read(c[0])
647 mm = repo.manifest.read(c[0])
629 seen = {}
648 seen = {}
630
649
631 for x in xrange(revnum, cl.count()):
650 for x in xrange(revnum, cl.count()):
632 c = cl.read(cl.node(x))
651 c = cl.read(cl.node(x))
633 for f in c[3]:
652 for f in c[3]:
634 if f in seen:
653 if f in seen:
635 continue
654 continue
636 seen[f] = 1
655 seen[f] = 1
637 if f in mm:
656 if f in mm:
638 filerev = mm[f]
657 filerev = mm[f]
639 else:
658 else:
640 filerev = 0
659 filerev = 0
641 seen[f] = filerev
660 seen[f] = filerev
642 # we go in two steps here so the strip loop happens in a
661 # we go in two steps here so the strip loop happens in a
643 # sensible order. When stripping many files, this helps keep
662 # sensible order. When stripping many files, this helps keep
644 # our disk access patterns under control.
663 # our disk access patterns under control.
645 seen_list = seen.keys()
664 seen_list = seen.keys()
646 seen_list.sort()
665 seen_list.sort()
647 for f in seen_list:
666 for f in seen_list:
648 ff = repo.file(f)
667 ff = repo.file(f)
649 filerev = seen[f]
668 filerev = seen[f]
650 if filerev != 0:
669 if filerev != 0:
651 if filerev in ff.nodemap:
670 if filerev in ff.nodemap:
652 filerev = ff.rev(filerev)
671 filerev = ff.rev(filerev)
653 else:
672 else:
654 filerev = 0
673 filerev = 0
655 ff.strip(filerev, revnum)
674 ff.strip(filerev, revnum)
656
675
657 if not wlock:
676 if not wlock:
658 wlock = repo.wlock()
677 wlock = repo.wlock()
659 lock = repo.lock()
678 lock = repo.lock()
660 chlog = repo.changelog
679 chlog = repo.changelog
661 # TODO delete the undo files, and handle undo of merge sets
680 # TODO delete the undo files, and handle undo of merge sets
662 pp = chlog.parents(rev)
681 pp = chlog.parents(rev)
663 revnum = chlog.rev(rev)
682 revnum = chlog.rev(rev)
664
683
665 if update:
684 if update:
666 self.check_localchanges(repo, refresh=False)
685 self.check_localchanges(repo, refresh=False)
667 urev = self.qparents(repo, rev)
686 urev = self.qparents(repo, rev)
668 hg.clean(repo, urev, wlock=wlock)
687 hg.clean(repo, urev, wlock=wlock)
669 repo.dirstate.write()
688 repo.dirstate.write()
670
689
671 # save is a list of all the branches we are truncating away
690 # save is a list of all the branches we are truncating away
672 # that we actually want to keep. changegroup will be used
691 # that we actually want to keep. changegroup will be used
673 # to preserve them and add them back after the truncate
692 # to preserve them and add them back after the truncate
674 saveheads = []
693 saveheads = []
675 savebases = {}
694 savebases = {}
676
695
677 heads = limitheads(chlog, rev)
696 heads = limitheads(chlog, rev)
678 seen = {}
697 seen = {}
679
698
680 # search through all the heads, finding those where the revision
699 # search through all the heads, finding those where the revision
681 # we want to strip away is an ancestor. Also look for merges
700 # we want to strip away is an ancestor. Also look for merges
682 # that might be turned into new heads by the strip.
701 # that might be turned into new heads by the strip.
683 while heads:
702 while heads:
684 h = heads.pop()
703 h = heads.pop()
685 n = h
704 n = h
686 while True:
705 while True:
687 seen[n] = 1
706 seen[n] = 1
688 pp = chlog.parents(n)
707 pp = chlog.parents(n)
689 if pp[1] != revlog.nullid:
708 if pp[1] != revlog.nullid:
690 for p in pp:
709 for p in pp:
691 if chlog.rev(p) > revnum and p not in seen:
710 if chlog.rev(p) > revnum and p not in seen:
692 heads.append(p)
711 heads.append(p)
693 if pp[0] == revlog.nullid:
712 if pp[0] == revlog.nullid:
694 break
713 break
695 if chlog.rev(pp[0]) < revnum:
714 if chlog.rev(pp[0]) < revnum:
696 break
715 break
697 n = pp[0]
716 n = pp[0]
698 if n == rev:
717 if n == rev:
699 break
718 break
700 r = chlog.reachable(h, rev)
719 r = chlog.reachable(h, rev)
701 if rev not in r:
720 if rev not in r:
702 saveheads.append(h)
721 saveheads.append(h)
703 for x in r:
722 for x in r:
704 if chlog.rev(x) > revnum:
723 if chlog.rev(x) > revnum:
705 savebases[x] = 1
724 savebases[x] = 1
706
725
707 # create a changegroup for all the branches we need to keep
726 # create a changegroup for all the branches we need to keep
708 if backup == "all":
727 if backup == "all":
709 backupch = repo.changegroupsubset([rev], chlog.heads(), 'strip')
728 backupch = repo.changegroupsubset([rev], chlog.heads(), 'strip')
710 bundle(backupch)
729 bundle(backupch)
711 if saveheads:
730 if saveheads:
712 backupch = repo.changegroupsubset(savebases.keys(), saveheads, 'strip')
731 backupch = repo.changegroupsubset(savebases.keys(), saveheads, 'strip')
713 chgrpfile = bundle(backupch)
732 chgrpfile = bundle(backupch)
714
733
715 stripall(rev, revnum)
734 stripall(rev, revnum)
716
735
717 change = chlog.read(rev)
736 change = chlog.read(rev)
718 chlog.strip(revnum, revnum)
737 chlog.strip(revnum, revnum)
719 repo.manifest.strip(repo.manifest.rev(change[0]), revnum)
738 repo.manifest.strip(repo.manifest.rev(change[0]), revnum)
720 if saveheads:
739 if saveheads:
721 self.ui.status("adding branch\n")
740 self.ui.status("adding branch\n")
722 commands.unbundle(self.ui, repo, "file:%s" % chgrpfile,
741 commands.unbundle(self.ui, repo, "file:%s" % chgrpfile,
723 update=False)
742 update=False)
724 if backup != "strip":
743 if backup != "strip":
725 os.unlink(chgrpfile)
744 os.unlink(chgrpfile)
726
745
727 def isapplied(self, patch):
746 def isapplied(self, patch):
728 """returns (index, rev, patch)"""
747 """returns (index, rev, patch)"""
729 for i in xrange(len(self.applied)):
748 for i in xrange(len(self.applied)):
730 a = self.applied[i]
749 a = self.applied[i]
731 if a.name == patch:
750 if a.name == patch:
732 return (i, a.rev, a.name)
751 return (i, a.rev, a.name)
733 return None
752 return None
734
753
735 # if the exact patch name does not exist, we try a few
754 # if the exact patch name does not exist, we try a few
736 # variations. If strict is passed, we try only #1
755 # variations. If strict is passed, we try only #1
737 #
756 #
738 # 1) a number to indicate an offset in the series file
757 # 1) a number to indicate an offset in the series file
739 # 2) a unique substring of the patch name was given
758 # 2) a unique substring of the patch name was given
740 # 3) patchname[-+]num to indicate an offset in the series file
759 # 3) patchname[-+]num to indicate an offset in the series file
741 def lookup(self, patch, strict=False):
760 def lookup(self, patch, strict=False):
742 patch = patch and str(patch)
761 patch = patch and str(patch)
743
762
744 def partial_name(s):
763 def partial_name(s):
745 if s in self.series:
764 if s in self.series:
746 return s
765 return s
747 matches = [x for x in self.series if s in x]
766 matches = [x for x in self.series if s in x]
748 if len(matches) > 1:
767 if len(matches) > 1:
749 self.ui.warn(_('patch name "%s" is ambiguous:\n') % s)
768 self.ui.warn(_('patch name "%s" is ambiguous:\n') % s)
750 for m in matches:
769 for m in matches:
751 self.ui.warn(' %s\n' % m)
770 self.ui.warn(' %s\n' % m)
752 return None
771 return None
753 if matches:
772 if matches:
754 return matches[0]
773 return matches[0]
755 if len(self.series) > 0 and len(self.applied) > 0:
774 if len(self.series) > 0 and len(self.applied) > 0:
756 if s == 'qtip':
775 if s == 'qtip':
757 return self.series[self.series_end(True)-1]
776 return self.series[self.series_end(True)-1]
758 if s == 'qbase':
777 if s == 'qbase':
759 return self.series[0]
778 return self.series[0]
760 return None
779 return None
761 if patch == None:
780 if patch == None:
762 return None
781 return None
763
782
764 # we don't want to return a partial match until we make
783 # we don't want to return a partial match until we make
765 # sure the file name passed in does not exist (checked below)
784 # sure the file name passed in does not exist (checked below)
766 res = partial_name(patch)
785 res = partial_name(patch)
767 if res and res == patch:
786 if res and res == patch:
768 return res
787 return res
769
788
770 if not os.path.isfile(self.join(patch)):
789 if not os.path.isfile(self.join(patch)):
771 try:
790 try:
772 sno = int(patch)
791 sno = int(patch)
773 except(ValueError, OverflowError):
792 except(ValueError, OverflowError):
774 pass
793 pass
775 else:
794 else:
776 if sno < len(self.series):
795 if sno < len(self.series):
777 return self.series[sno]
796 return self.series[sno]
778 if not strict:
797 if not strict:
779 # return any partial match made above
798 # return any partial match made above
780 if res:
799 if res:
781 return res
800 return res
782 minus = patch.rfind('-')
801 minus = patch.rfind('-')
783 if minus >= 0:
802 if minus >= 0:
784 res = partial_name(patch[:minus])
803 res = partial_name(patch[:minus])
785 if res:
804 if res:
786 i = self.series.index(res)
805 i = self.series.index(res)
787 try:
806 try:
788 off = int(patch[minus+1:] or 1)
807 off = int(patch[minus+1:] or 1)
789 except(ValueError, OverflowError):
808 except(ValueError, OverflowError):
790 pass
809 pass
791 else:
810 else:
792 if i - off >= 0:
811 if i - off >= 0:
793 return self.series[i - off]
812 return self.series[i - off]
794 plus = patch.rfind('+')
813 plus = patch.rfind('+')
795 if plus >= 0:
814 if plus >= 0:
796 res = partial_name(patch[:plus])
815 res = partial_name(patch[:plus])
797 if res:
816 if res:
798 i = self.series.index(res)
817 i = self.series.index(res)
799 try:
818 try:
800 off = int(patch[plus+1:] or 1)
819 off = int(patch[plus+1:] or 1)
801 except(ValueError, OverflowError):
820 except(ValueError, OverflowError):
802 pass
821 pass
803 else:
822 else:
804 if i + off < len(self.series):
823 if i + off < len(self.series):
805 return self.series[i + off]
824 return self.series[i + off]
806 raise util.Abort(_("patch %s not in series") % patch)
825 raise util.Abort(_("patch %s not in series") % patch)
807
826
808 def push(self, repo, patch=None, force=False, list=False,
827 def push(self, repo, patch=None, force=False, list=False,
809 mergeq=None, wlock=None):
828 mergeq=None, wlock=None):
810 if not wlock:
829 if not wlock:
811 wlock = repo.wlock()
830 wlock = repo.wlock()
812 patch = self.lookup(patch)
831 patch = self.lookup(patch)
813 if patch and self.isapplied(patch):
832 if patch and self.isapplied(patch):
814 raise util.Abort(_("patch %s is already applied") % patch)
833 raise util.Abort(_("patch %s is already applied") % patch)
815 if self.series_end() == len(self.series):
834 if self.series_end() == len(self.series):
816 raise util.Abort(_("patch series fully applied"))
835 raise util.Abort(_("patch series fully applied"))
817 if not force:
836 if not force:
818 self.check_localchanges(repo)
837 self.check_localchanges(repo)
819
838
820 self.applied_dirty = 1;
839 self.applied_dirty = 1;
821 start = self.series_end()
840 start = self.series_end()
822 if start > 0:
841 if start > 0:
823 self.check_toppatch(repo)
842 self.check_toppatch(repo)
824 if not patch:
843 if not patch:
825 patch = self.series[start]
844 patch = self.series[start]
826 end = start + 1
845 end = start + 1
827 else:
846 else:
828 end = self.series.index(patch, start) + 1
847 end = self.series.index(patch, start) + 1
829 s = self.series[start:end]
848 s = self.series[start:end]
849 all_files = {}
850 try:
830 if mergeq:
851 if mergeq:
831 ret = self.mergepatch(repo, mergeq, s, wlock)
852 ret = self.mergepatch(repo, mergeq, s, wlock)
832 else:
853 else:
833 ret = self.apply(repo, s, list, wlock=wlock)
854 ret = self.apply(repo, s, list, wlock=wlock,
855 all_files=all_files)
856 except:
857 self.ui.warn(_('cleaning up working directory...'))
858 node = repo.dirstate.parents()[0]
859 hg.revert(repo, node, None, wlock)
860 unknown = repo.status(wlock=wlock)[4]
861 # only remove unknown files that we know we touched or
862 # created while patching
863 for f in unknown:
864 if f in all_files:
865 util.unlink(repo.wjoin(f))
866 self.ui.warn(_('done\n'))
867 raise
834 top = self.applied[-1].name
868 top = self.applied[-1].name
835 if ret[0]:
869 if ret[0]:
836 self.ui.write("Errors during apply, please fix and refresh %s\n" %
870 self.ui.write("Errors during apply, please fix and refresh %s\n" %
837 top)
871 top)
838 else:
872 else:
839 self.ui.write("Now at: %s\n" % top)
873 self.ui.write("Now at: %s\n" % top)
840 return ret[0]
874 return ret[0]
841
875
842 def pop(self, repo, patch=None, force=False, update=True, all=False,
876 def pop(self, repo, patch=None, force=False, update=True, all=False,
843 wlock=None):
877 wlock=None):
844 def getfile(f, rev):
878 def getfile(f, rev):
845 t = repo.file(f).read(rev)
879 t = repo.file(f).read(rev)
846 try:
880 try:
847 repo.wfile(f, "w").write(t)
881 repo.wfile(f, "w").write(t)
848 except IOError:
882 except IOError:
849 try:
883 try:
850 os.makedirs(os.path.dirname(repo.wjoin(f)))
884 os.makedirs(os.path.dirname(repo.wjoin(f)))
851 except OSError, err:
885 except OSError, err:
852 if err.errno != errno.EEXIST: raise
886 if err.errno != errno.EEXIST: raise
853 repo.wfile(f, "w").write(t)
887 repo.wfile(f, "w").write(t)
854
888
855 if not wlock:
889 if not wlock:
856 wlock = repo.wlock()
890 wlock = repo.wlock()
857 if patch:
891 if patch:
858 # index, rev, patch
892 # index, rev, patch
859 info = self.isapplied(patch)
893 info = self.isapplied(patch)
860 if not info:
894 if not info:
861 patch = self.lookup(patch)
895 patch = self.lookup(patch)
862 info = self.isapplied(patch)
896 info = self.isapplied(patch)
863 if not info:
897 if not info:
864 raise util.Abort(_("patch %s is not applied") % patch)
898 raise util.Abort(_("patch %s is not applied") % patch)
865 if len(self.applied) == 0:
899 if len(self.applied) == 0:
866 raise util.Abort(_("no patches applied"))
900 raise util.Abort(_("no patches applied"))
867
901
868 if not update:
902 if not update:
869 parents = repo.dirstate.parents()
903 parents = repo.dirstate.parents()
870 rr = [ revlog.bin(x.rev) for x in self.applied ]
904 rr = [ revlog.bin(x.rev) for x in self.applied ]
871 for p in parents:
905 for p in parents:
872 if p in rr:
906 if p in rr:
873 self.ui.warn("qpop: forcing dirstate update\n")
907 self.ui.warn("qpop: forcing dirstate update\n")
874 update = True
908 update = True
875
909
876 if not force and update:
910 if not force and update:
877 self.check_localchanges(repo)
911 self.check_localchanges(repo)
878
912
879 self.applied_dirty = 1;
913 self.applied_dirty = 1;
880 end = len(self.applied)
914 end = len(self.applied)
881 if not patch:
915 if not patch:
882 if all:
916 if all:
883 popi = 0
917 popi = 0
884 else:
918 else:
885 popi = len(self.applied) - 1
919 popi = len(self.applied) - 1
886 else:
920 else:
887 popi = info[0] + 1
921 popi = info[0] + 1
888 if popi >= end:
922 if popi >= end:
889 self.ui.warn("qpop: %s is already at the top\n" % patch)
923 self.ui.warn("qpop: %s is already at the top\n" % patch)
890 return
924 return
891 info = [ popi ] + [self.applied[popi].rev, self.applied[popi].name]
925 info = [ popi ] + [self.applied[popi].rev, self.applied[popi].name]
892
926
893 start = info[0]
927 start = info[0]
894 rev = revlog.bin(info[1])
928 rev = revlog.bin(info[1])
895
929
896 # we know there are no local changes, so we can make a simplified
930 # we know there are no local changes, so we can make a simplified
897 # form of hg.update.
931 # form of hg.update.
898 if update:
932 if update:
899 top = self.check_toppatch(repo)
933 top = self.check_toppatch(repo)
900 qp = self.qparents(repo, rev)
934 qp = self.qparents(repo, rev)
901 changes = repo.changelog.read(qp)
935 changes = repo.changelog.read(qp)
902 mmap = repo.manifest.read(changes[0])
936 mmap = repo.manifest.read(changes[0])
903 m, a, r, d, u = repo.status(qp, top)[:5]
937 m, a, r, d, u = repo.status(qp, top)[:5]
904 if d:
938 if d:
905 raise util.Abort("deletions found between repo revs")
939 raise util.Abort("deletions found between repo revs")
906 for f in m:
940 for f in m:
907 getfile(f, mmap[f])
941 getfile(f, mmap[f])
908 for f in r:
942 for f in r:
909 getfile(f, mmap[f])
943 getfile(f, mmap[f])
910 util.set_exec(repo.wjoin(f), mmap.execf(f))
944 util.set_exec(repo.wjoin(f), mmap.execf(f))
911 repo.dirstate.update(m + r, 'n')
945 repo.dirstate.update(m + r, 'n')
912 for f in a:
946 for f in a:
913 try:
947 try:
914 os.unlink(repo.wjoin(f))
948 os.unlink(repo.wjoin(f))
915 except OSError, e:
949 except OSError, e:
916 if e.errno != errno.ENOENT:
950 if e.errno != errno.ENOENT:
917 raise
951 raise
918 try: os.removedirs(os.path.dirname(repo.wjoin(f)))
952 try: os.removedirs(os.path.dirname(repo.wjoin(f)))
919 except: pass
953 except: pass
920 if a:
954 if a:
921 repo.dirstate.forget(a)
955 repo.dirstate.forget(a)
922 repo.dirstate.setparents(qp, revlog.nullid)
956 repo.dirstate.setparents(qp, revlog.nullid)
923 self.strip(repo, rev, update=False, backup='strip', wlock=wlock)
957 self.strip(repo, rev, update=False, backup='strip', wlock=wlock)
924 del self.applied[start:end]
958 del self.applied[start:end]
925 if len(self.applied):
959 if len(self.applied):
926 self.ui.write("Now at: %s\n" % self.applied[-1].name)
960 self.ui.write("Now at: %s\n" % self.applied[-1].name)
927 else:
961 else:
928 self.ui.write("Patch queue now empty\n")
962 self.ui.write("Patch queue now empty\n")
929
963
930 def diff(self, repo, pats, opts):
964 def diff(self, repo, pats, opts):
931 top = self.check_toppatch(repo)
965 top = self.check_toppatch(repo)
932 if not top:
966 if not top:
933 self.ui.write("No patches applied\n")
967 self.ui.write("No patches applied\n")
934 return
968 return
935 qp = self.qparents(repo, top)
969 qp = self.qparents(repo, top)
936 if opts.get('git'):
970 if opts.get('git'):
937 self.diffopts().git = True
971 self.diffopts().git = True
938 self.printdiff(repo, qp, files=pats, opts=opts)
972 self.printdiff(repo, qp, files=pats, opts=opts)
939
973
940 def refresh(self, repo, pats=None, **opts):
974 def refresh(self, repo, pats=None, **opts):
941 if len(self.applied) == 0:
975 if len(self.applied) == 0:
942 self.ui.write("No patches applied\n")
976 self.ui.write("No patches applied\n")
943 return 1
977 return 1
944 wlock = repo.wlock()
978 wlock = repo.wlock()
945 self.check_toppatch(repo)
979 self.check_toppatch(repo)
946 (top, patchfn) = (self.applied[-1].rev, self.applied[-1].name)
980 (top, patchfn) = (self.applied[-1].rev, self.applied[-1].name)
947 top = revlog.bin(top)
981 top = revlog.bin(top)
948 cparents = repo.changelog.parents(top)
982 cparents = repo.changelog.parents(top)
949 patchparent = self.qparents(repo, top)
983 patchparent = self.qparents(repo, top)
950 message, comments, user, date, patchfound = self.readheaders(patchfn)
984 message, comments, user, date, patchfound = self.readheaders(patchfn)
951
985
952 patchf = self.opener(patchfn, "w")
986 patchf = self.opener(patchfn, "w")
953 msg = opts.get('msg', '').rstrip()
987 msg = opts.get('msg', '').rstrip()
954 if msg:
988 if msg:
955 if comments:
989 if comments:
956 # Remove existing message.
990 # Remove existing message.
957 ci = 0
991 ci = 0
958 for mi in xrange(len(message)):
992 for mi in xrange(len(message)):
959 while message[mi] != comments[ci]:
993 while message[mi] != comments[ci]:
960 ci += 1
994 ci += 1
961 del comments[ci]
995 del comments[ci]
962 comments.append(msg)
996 comments.append(msg)
963 if comments:
997 if comments:
964 comments = "\n".join(comments) + '\n\n'
998 comments = "\n".join(comments) + '\n\n'
965 patchf.write(comments)
999 patchf.write(comments)
966
1000
967 if opts.get('git'):
1001 if opts.get('git'):
968 self.diffopts().git = True
1002 self.diffopts().git = True
969 fns, matchfn, anypats = cmdutil.matchpats(repo, pats, opts)
1003 fns, matchfn, anypats = cmdutil.matchpats(repo, pats, opts)
970 tip = repo.changelog.tip()
1004 tip = repo.changelog.tip()
971 if top == tip:
1005 if top == tip:
972 # if the top of our patch queue is also the tip, there is an
1006 # if the top of our patch queue is also the tip, there is an
973 # optimization here. We update the dirstate in place and strip
1007 # optimization here. We update the dirstate in place and strip
974 # off the tip commit. Then just commit the current directory
1008 # off the tip commit. Then just commit the current directory
975 # tree. We can also send repo.commit the list of files
1009 # tree. We can also send repo.commit the list of files
976 # changed to speed up the diff
1010 # changed to speed up the diff
977 #
1011 #
978 # in short mode, we only diff the files included in the
1012 # in short mode, we only diff the files included in the
979 # patch already
1013 # patch already
980 #
1014 #
981 # this should really read:
1015 # this should really read:
982 # mm, dd, aa, aa2, uu = repo.status(tip, patchparent)[:5]
1016 # mm, dd, aa, aa2, uu = repo.status(tip, patchparent)[:5]
983 # but we do it backwards to take advantage of manifest/chlog
1017 # but we do it backwards to take advantage of manifest/chlog
984 # caching against the next repo.status call
1018 # caching against the next repo.status call
985 #
1019 #
986 mm, aa, dd, aa2, uu = repo.status(patchparent, tip)[:5]
1020 mm, aa, dd, aa2, uu = repo.status(patchparent, tip)[:5]
987 changes = repo.changelog.read(tip)
1021 changes = repo.changelog.read(tip)
988 man = repo.manifest.read(changes[0])
1022 man = repo.manifest.read(changes[0])
989 aaa = aa[:]
1023 aaa = aa[:]
990 if opts.get('short'):
1024 if opts.get('short'):
991 filelist = mm + aa + dd
1025 filelist = mm + aa + dd
992 else:
1026 else:
993 filelist = None
1027 filelist = None
994 m, a, r, d, u = repo.status(files=filelist)[:5]
1028 m, a, r, d, u = repo.status(files=filelist)[:5]
995
1029
996 # we might end up with files that were added between tip and
1030 # we might end up with files that were added between tip and
997 # the dirstate parent, but then changed in the local dirstate.
1031 # the dirstate parent, but then changed in the local dirstate.
998 # in this case, we want them to only show up in the added section
1032 # in this case, we want them to only show up in the added section
999 for x in m:
1033 for x in m:
1000 if x not in aa:
1034 if x not in aa:
1001 mm.append(x)
1035 mm.append(x)
1002 # we might end up with files added by the local dirstate that
1036 # we might end up with files added by the local dirstate that
1003 # were deleted by the patch. In this case, they should only
1037 # were deleted by the patch. In this case, they should only
1004 # show up in the changed section.
1038 # show up in the changed section.
1005 for x in a:
1039 for x in a:
1006 if x in dd:
1040 if x in dd:
1007 del dd[dd.index(x)]
1041 del dd[dd.index(x)]
1008 mm.append(x)
1042 mm.append(x)
1009 else:
1043 else:
1010 aa.append(x)
1044 aa.append(x)
1011 # make sure any files deleted in the local dirstate
1045 # make sure any files deleted in the local dirstate
1012 # are not in the add or change column of the patch
1046 # are not in the add or change column of the patch
1013 forget = []
1047 forget = []
1014 for x in d + r:
1048 for x in d + r:
1015 if x in aa:
1049 if x in aa:
1016 del aa[aa.index(x)]
1050 del aa[aa.index(x)]
1017 forget.append(x)
1051 forget.append(x)
1018 continue
1052 continue
1019 elif x in mm:
1053 elif x in mm:
1020 del mm[mm.index(x)]
1054 del mm[mm.index(x)]
1021 dd.append(x)
1055 dd.append(x)
1022
1056
1023 m = util.unique(mm)
1057 m = util.unique(mm)
1024 r = util.unique(dd)
1058 r = util.unique(dd)
1025 a = util.unique(aa)
1059 a = util.unique(aa)
1026 c = [filter(matchfn, l) for l in (m, a, r, [], u)]
1060 c = [filter(matchfn, l) for l in (m, a, r, [], u)]
1027 filelist = util.unique(c[0] + c[1] + c[2])
1061 filelist = util.unique(c[0] + c[1] + c[2])
1028 patch.diff(repo, patchparent, files=filelist, match=matchfn,
1062 patch.diff(repo, patchparent, files=filelist, match=matchfn,
1029 fp=patchf, changes=c, opts=self.diffopts())
1063 fp=patchf, changes=c, opts=self.diffopts())
1030 patchf.close()
1064 patchf.close()
1031
1065
1032 repo.dirstate.setparents(*cparents)
1066 repo.dirstate.setparents(*cparents)
1033 copies = {}
1067 copies = {}
1034 for dst in a:
1068 for dst in a:
1035 src = repo.dirstate.copied(dst)
1069 src = repo.dirstate.copied(dst)
1036 if src is None:
1070 if src is None:
1037 continue
1071 continue
1038 copies.setdefault(src, []).append(dst)
1072 copies.setdefault(src, []).append(dst)
1039 repo.dirstate.update(a, 'a')
1073 repo.dirstate.update(a, 'a')
1040 # remember the copies between patchparent and tip
1074 # remember the copies between patchparent and tip
1041 # this may be slow, so don't do it if we're not tracking copies
1075 # this may be slow, so don't do it if we're not tracking copies
1042 if self.diffopts().git:
1076 if self.diffopts().git:
1043 for dst in aaa:
1077 for dst in aaa:
1044 f = repo.file(dst)
1078 f = repo.file(dst)
1045 src = f.renamed(man[dst])
1079 src = f.renamed(man[dst])
1046 if src:
1080 if src:
1047 copies[src[0]] = copies.get(dst, [])
1081 copies[src[0]] = copies.get(dst, [])
1048 if dst in a:
1082 if dst in a:
1049 copies[src[0]].append(dst)
1083 copies[src[0]].append(dst)
1050 # we can't copy a file created by the patch itself
1084 # we can't copy a file created by the patch itself
1051 if dst in copies:
1085 if dst in copies:
1052 del copies[dst]
1086 del copies[dst]
1053 for src, dsts in copies.iteritems():
1087 for src, dsts in copies.iteritems():
1054 for dst in dsts:
1088 for dst in dsts:
1055 repo.dirstate.copy(src, dst)
1089 repo.dirstate.copy(src, dst)
1056 repo.dirstate.update(r, 'r')
1090 repo.dirstate.update(r, 'r')
1057 # if the patch excludes a modified file, mark that file with mtime=0
1091 # if the patch excludes a modified file, mark that file with mtime=0
1058 # so status can see it.
1092 # so status can see it.
1059 mm = []
1093 mm = []
1060 for i in xrange(len(m)-1, -1, -1):
1094 for i in xrange(len(m)-1, -1, -1):
1061 if not matchfn(m[i]):
1095 if not matchfn(m[i]):
1062 mm.append(m[i])
1096 mm.append(m[i])
1063 del m[i]
1097 del m[i]
1064 repo.dirstate.update(m, 'n')
1098 repo.dirstate.update(m, 'n')
1065 repo.dirstate.update(mm, 'n', st_mtime=0)
1099 repo.dirstate.update(mm, 'n', st_mtime=0)
1066 repo.dirstate.forget(forget)
1100 repo.dirstate.forget(forget)
1067
1101
1068 if not msg:
1102 if not msg:
1069 if not message:
1103 if not message:
1070 message = "patch queue: %s\n" % patchfn
1104 message = "patch queue: %s\n" % patchfn
1071 else:
1105 else:
1072 message = "\n".join(message)
1106 message = "\n".join(message)
1073 else:
1107 else:
1074 message = msg
1108 message = msg
1075
1109
1076 self.strip(repo, top, update=False, backup='strip', wlock=wlock)
1110 self.strip(repo, top, update=False, backup='strip', wlock=wlock)
1077 n = repo.commit(filelist, message, changes[1], match=matchfn,
1111 n = repo.commit(filelist, message, changes[1], match=matchfn,
1078 force=1, wlock=wlock)
1112 force=1, wlock=wlock)
1079 self.applied[-1] = statusentry(revlog.hex(n), patchfn)
1113 self.applied[-1] = statusentry(revlog.hex(n), patchfn)
1080 self.applied_dirty = 1
1114 self.applied_dirty = 1
1081 else:
1115 else:
1082 self.printdiff(repo, patchparent, fp=patchf)
1116 self.printdiff(repo, patchparent, fp=patchf)
1083 patchf.close()
1117 patchf.close()
1084 added = repo.status()[1]
1118 added = repo.status()[1]
1085 for a in added:
1119 for a in added:
1086 f = repo.wjoin(a)
1120 f = repo.wjoin(a)
1087 try:
1121 try:
1088 os.unlink(f)
1122 os.unlink(f)
1089 except OSError, e:
1123 except OSError, e:
1090 if e.errno != errno.ENOENT:
1124 if e.errno != errno.ENOENT:
1091 raise
1125 raise
1092 try: os.removedirs(os.path.dirname(f))
1126 try: os.removedirs(os.path.dirname(f))
1093 except: pass
1127 except: pass
1094 # forget the file copies in the dirstate
1128 # forget the file copies in the dirstate
1095 # push should readd the files later on
1129 # push should readd the files later on
1096 repo.dirstate.forget(added)
1130 repo.dirstate.forget(added)
1097 self.pop(repo, force=True, wlock=wlock)
1131 self.pop(repo, force=True, wlock=wlock)
1098 self.push(repo, force=True, wlock=wlock)
1132 self.push(repo, force=True, wlock=wlock)
1099
1133
1100 def init(self, repo, create=False):
1134 def init(self, repo, create=False):
1101 if os.path.isdir(self.path):
1135 if os.path.isdir(self.path):
1102 raise util.Abort(_("patch queue directory already exists"))
1136 raise util.Abort(_("patch queue directory already exists"))
1103 os.mkdir(self.path)
1137 os.mkdir(self.path)
1104 if create:
1138 if create:
1105 return self.qrepo(create=True)
1139 return self.qrepo(create=True)
1106
1140
1107 def unapplied(self, repo, patch=None):
1141 def unapplied(self, repo, patch=None):
1108 if patch and patch not in self.series:
1142 if patch and patch not in self.series:
1109 raise util.Abort(_("patch %s is not in series file") % patch)
1143 raise util.Abort(_("patch %s is not in series file") % patch)
1110 if not patch:
1144 if not patch:
1111 start = self.series_end()
1145 start = self.series_end()
1112 else:
1146 else:
1113 start = self.series.index(patch) + 1
1147 start = self.series.index(patch) + 1
1114 unapplied = []
1148 unapplied = []
1115 for i in xrange(start, len(self.series)):
1149 for i in xrange(start, len(self.series)):
1116 pushable, reason = self.pushable(i)
1150 pushable, reason = self.pushable(i)
1117 if pushable:
1151 if pushable:
1118 unapplied.append((i, self.series[i]))
1152 unapplied.append((i, self.series[i]))
1119 self.explain_pushable(i)
1153 self.explain_pushable(i)
1120 return unapplied
1154 return unapplied
1121
1155
1122 def qseries(self, repo, missing=None, start=0, length=None, status=None,
1156 def qseries(self, repo, missing=None, start=0, length=None, status=None,
1123 summary=False):
1157 summary=False):
1124 def displayname(patchname):
1158 def displayname(patchname):
1125 if summary:
1159 if summary:
1126 msg = self.readheaders(patchname)[0]
1160 msg = self.readheaders(patchname)[0]
1127 msg = msg and ': ' + msg[0] or ': '
1161 msg = msg and ': ' + msg[0] or ': '
1128 else:
1162 else:
1129 msg = ''
1163 msg = ''
1130 return '%s%s' % (patchname, msg)
1164 return '%s%s' % (patchname, msg)
1131
1165
1132 applied = dict.fromkeys([p.name for p in self.applied])
1166 applied = dict.fromkeys([p.name for p in self.applied])
1133 if length is None:
1167 if length is None:
1134 length = len(self.series) - start
1168 length = len(self.series) - start
1135 if not missing:
1169 if not missing:
1136 for i in xrange(start, start+length):
1170 for i in xrange(start, start+length):
1137 patch = self.series[i]
1171 patch = self.series[i]
1138 if patch in applied:
1172 if patch in applied:
1139 stat = 'A'
1173 stat = 'A'
1140 elif self.pushable(i)[0]:
1174 elif self.pushable(i)[0]:
1141 stat = 'U'
1175 stat = 'U'
1142 else:
1176 else:
1143 stat = 'G'
1177 stat = 'G'
1144 pfx = ''
1178 pfx = ''
1145 if self.ui.verbose:
1179 if self.ui.verbose:
1146 pfx = '%d %s ' % (i, stat)
1180 pfx = '%d %s ' % (i, stat)
1147 elif status and status != stat:
1181 elif status and status != stat:
1148 continue
1182 continue
1149 self.ui.write('%s%s\n' % (pfx, displayname(patch)))
1183 self.ui.write('%s%s\n' % (pfx, displayname(patch)))
1150 else:
1184 else:
1151 msng_list = []
1185 msng_list = []
1152 for root, dirs, files in os.walk(self.path):
1186 for root, dirs, files in os.walk(self.path):
1153 d = root[len(self.path) + 1:]
1187 d = root[len(self.path) + 1:]
1154 for f in files:
1188 for f in files:
1155 fl = os.path.join(d, f)
1189 fl = os.path.join(d, f)
1156 if (fl not in self.series and
1190 if (fl not in self.series and
1157 fl not in (self.status_path, self.series_path,
1191 fl not in (self.status_path, self.series_path,
1158 self.guards_path)
1192 self.guards_path)
1159 and not fl.startswith('.')):
1193 and not fl.startswith('.')):
1160 msng_list.append(fl)
1194 msng_list.append(fl)
1161 msng_list.sort()
1195 msng_list.sort()
1162 for x in msng_list:
1196 for x in msng_list:
1163 pfx = self.ui.verbose and ('D ') or ''
1197 pfx = self.ui.verbose and ('D ') or ''
1164 self.ui.write("%s%s\n" % (pfx, displayname(x)))
1198 self.ui.write("%s%s\n" % (pfx, displayname(x)))
1165
1199
1166 def issaveline(self, l):
1200 def issaveline(self, l):
1167 if l.name == '.hg.patches.save.line':
1201 if l.name == '.hg.patches.save.line':
1168 return True
1202 return True
1169
1203
1170 def qrepo(self, create=False):
1204 def qrepo(self, create=False):
1171 if create or os.path.isdir(self.join(".hg")):
1205 if create or os.path.isdir(self.join(".hg")):
1172 return hg.repository(self.ui, path=self.path, create=create)
1206 return hg.repository(self.ui, path=self.path, create=create)
1173
1207
1174 def restore(self, repo, rev, delete=None, qupdate=None):
1208 def restore(self, repo, rev, delete=None, qupdate=None):
1175 c = repo.changelog.read(rev)
1209 c = repo.changelog.read(rev)
1176 desc = c[4].strip()
1210 desc = c[4].strip()
1177 lines = desc.splitlines()
1211 lines = desc.splitlines()
1178 i = 0
1212 i = 0
1179 datastart = None
1213 datastart = None
1180 series = []
1214 series = []
1181 applied = []
1215 applied = []
1182 qpp = None
1216 qpp = None
1183 for i in xrange(0, len(lines)):
1217 for i in xrange(0, len(lines)):
1184 if lines[i] == 'Patch Data:':
1218 if lines[i] == 'Patch Data:':
1185 datastart = i + 1
1219 datastart = i + 1
1186 elif lines[i].startswith('Dirstate:'):
1220 elif lines[i].startswith('Dirstate:'):
1187 l = lines[i].rstrip()
1221 l = lines[i].rstrip()
1188 l = l[10:].split(' ')
1222 l = l[10:].split(' ')
1189 qpp = [ hg.bin(x) for x in l ]
1223 qpp = [ hg.bin(x) for x in l ]
1190 elif datastart != None:
1224 elif datastart != None:
1191 l = lines[i].rstrip()
1225 l = lines[i].rstrip()
1192 se = statusentry(l)
1226 se = statusentry(l)
1193 file_ = se.name
1227 file_ = se.name
1194 if se.rev:
1228 if se.rev:
1195 applied.append(se)
1229 applied.append(se)
1196 else:
1230 else:
1197 series.append(file_)
1231 series.append(file_)
1198 if datastart == None:
1232 if datastart == None:
1199 self.ui.warn("No saved patch data found\n")
1233 self.ui.warn("No saved patch data found\n")
1200 return 1
1234 return 1
1201 self.ui.warn("restoring status: %s\n" % lines[0])
1235 self.ui.warn("restoring status: %s\n" % lines[0])
1202 self.full_series = series
1236 self.full_series = series
1203 self.applied = applied
1237 self.applied = applied
1204 self.parse_series()
1238 self.parse_series()
1205 self.series_dirty = 1
1239 self.series_dirty = 1
1206 self.applied_dirty = 1
1240 self.applied_dirty = 1
1207 heads = repo.changelog.heads()
1241 heads = repo.changelog.heads()
1208 if delete:
1242 if delete:
1209 if rev not in heads:
1243 if rev not in heads:
1210 self.ui.warn("save entry has children, leaving it alone\n")
1244 self.ui.warn("save entry has children, leaving it alone\n")
1211 else:
1245 else:
1212 self.ui.warn("removing save entry %s\n" % hg.short(rev))
1246 self.ui.warn("removing save entry %s\n" % hg.short(rev))
1213 pp = repo.dirstate.parents()
1247 pp = repo.dirstate.parents()
1214 if rev in pp:
1248 if rev in pp:
1215 update = True
1249 update = True
1216 else:
1250 else:
1217 update = False
1251 update = False
1218 self.strip(repo, rev, update=update, backup='strip')
1252 self.strip(repo, rev, update=update, backup='strip')
1219 if qpp:
1253 if qpp:
1220 self.ui.warn("saved queue repository parents: %s %s\n" %
1254 self.ui.warn("saved queue repository parents: %s %s\n" %
1221 (hg.short(qpp[0]), hg.short(qpp[1])))
1255 (hg.short(qpp[0]), hg.short(qpp[1])))
1222 if qupdate:
1256 if qupdate:
1223 print "queue directory updating"
1257 print "queue directory updating"
1224 r = self.qrepo()
1258 r = self.qrepo()
1225 if not r:
1259 if not r:
1226 self.ui.warn("Unable to load queue repository\n")
1260 self.ui.warn("Unable to load queue repository\n")
1227 return 1
1261 return 1
1228 hg.clean(r, qpp[0])
1262 hg.clean(r, qpp[0])
1229
1263
1230 def save(self, repo, msg=None):
1264 def save(self, repo, msg=None):
1231 if len(self.applied) == 0:
1265 if len(self.applied) == 0:
1232 self.ui.warn("save: no patches applied, exiting\n")
1266 self.ui.warn("save: no patches applied, exiting\n")
1233 return 1
1267 return 1
1234 if self.issaveline(self.applied[-1]):
1268 if self.issaveline(self.applied[-1]):
1235 self.ui.warn("status is already saved\n")
1269 self.ui.warn("status is already saved\n")
1236 return 1
1270 return 1
1237
1271
1238 ar = [ ':' + x for x in self.full_series ]
1272 ar = [ ':' + x for x in self.full_series ]
1239 if not msg:
1273 if not msg:
1240 msg = "hg patches saved state"
1274 msg = "hg patches saved state"
1241 else:
1275 else:
1242 msg = "hg patches: " + msg.rstrip('\r\n')
1276 msg = "hg patches: " + msg.rstrip('\r\n')
1243 r = self.qrepo()
1277 r = self.qrepo()
1244 if r:
1278 if r:
1245 pp = r.dirstate.parents()
1279 pp = r.dirstate.parents()
1246 msg += "\nDirstate: %s %s" % (hg.hex(pp[0]), hg.hex(pp[1]))
1280 msg += "\nDirstate: %s %s" % (hg.hex(pp[0]), hg.hex(pp[1]))
1247 msg += "\n\nPatch Data:\n"
1281 msg += "\n\nPatch Data:\n"
1248 text = msg + "\n".join([str(x) for x in self.applied]) + '\n' + (ar and
1282 text = msg + "\n".join([str(x) for x in self.applied]) + '\n' + (ar and
1249 "\n".join(ar) + '\n' or "")
1283 "\n".join(ar) + '\n' or "")
1250 n = repo.commit(None, text, user=None, force=1)
1284 n = repo.commit(None, text, user=None, force=1)
1251 if not n:
1285 if not n:
1252 self.ui.warn("repo commit failed\n")
1286 self.ui.warn("repo commit failed\n")
1253 return 1
1287 return 1
1254 self.applied.append(statusentry(revlog.hex(n),'.hg.patches.save.line'))
1288 self.applied.append(statusentry(revlog.hex(n),'.hg.patches.save.line'))
1255 self.applied_dirty = 1
1289 self.applied_dirty = 1
1256
1290
1257 def full_series_end(self):
1291 def full_series_end(self):
1258 if len(self.applied) > 0:
1292 if len(self.applied) > 0:
1259 p = self.applied[-1].name
1293 p = self.applied[-1].name
1260 end = self.find_series(p)
1294 end = self.find_series(p)
1261 if end == None:
1295 if end == None:
1262 return len(self.full_series)
1296 return len(self.full_series)
1263 return end + 1
1297 return end + 1
1264 return 0
1298 return 0
1265
1299
1266 def series_end(self, all_patches=False):
1300 def series_end(self, all_patches=False):
1267 """If all_patches is False, return the index of the next pushable patch
1301 """If all_patches is False, return the index of the next pushable patch
1268 in the series, or the series length. If all_patches is True, return the
1302 in the series, or the series length. If all_patches is True, return the
1269 index of the first patch past the last applied one.
1303 index of the first patch past the last applied one.
1270 """
1304 """
1271 end = 0
1305 end = 0
1272 def next(start):
1306 def next(start):
1273 if all_patches:
1307 if all_patches:
1274 return start
1308 return start
1275 i = start
1309 i = start
1276 while i < len(self.series):
1310 while i < len(self.series):
1277 p, reason = self.pushable(i)
1311 p, reason = self.pushable(i)
1278 if p:
1312 if p:
1279 break
1313 break
1280 self.explain_pushable(i)
1314 self.explain_pushable(i)
1281 i += 1
1315 i += 1
1282 return i
1316 return i
1283 if len(self.applied) > 0:
1317 if len(self.applied) > 0:
1284 p = self.applied[-1].name
1318 p = self.applied[-1].name
1285 try:
1319 try:
1286 end = self.series.index(p)
1320 end = self.series.index(p)
1287 except ValueError:
1321 except ValueError:
1288 return 0
1322 return 0
1289 return next(end + 1)
1323 return next(end + 1)
1290 return next(end)
1324 return next(end)
1291
1325
1292 def appliedname(self, index):
1326 def appliedname(self, index):
1293 pname = self.applied[index].name
1327 pname = self.applied[index].name
1294 if not self.ui.verbose:
1328 if not self.ui.verbose:
1295 p = pname
1329 p = pname
1296 else:
1330 else:
1297 p = str(self.series.index(pname)) + " " + pname
1331 p = str(self.series.index(pname)) + " " + pname
1298 return p
1332 return p
1299
1333
1300 def qimport(self, repo, files, patchname=None, rev=None, existing=None,
1334 def qimport(self, repo, files, patchname=None, rev=None, existing=None,
1301 force=None, git=False):
1335 force=None, git=False):
1302 def checkseries(patchname):
1336 def checkseries(patchname):
1303 if patchname in self.series:
1337 if patchname in self.series:
1304 raise util.Abort(_('patch %s is already in the series file')
1338 raise util.Abort(_('patch %s is already in the series file')
1305 % patchname)
1339 % patchname)
1306 def checkfile(patchname):
1340 def checkfile(patchname):
1307 if not force and os.path.exists(self.join(patchname)):
1341 if not force and os.path.exists(self.join(patchname)):
1308 raise util.Abort(_('patch "%s" already exists')
1342 raise util.Abort(_('patch "%s" already exists')
1309 % patchname)
1343 % patchname)
1310
1344
1311 if rev:
1345 if rev:
1312 if files:
1346 if files:
1313 raise util.Abort(_('option "-r" not valid when importing '
1347 raise util.Abort(_('option "-r" not valid when importing '
1314 'files'))
1348 'files'))
1315 rev = cmdutil.revrange(repo, rev)
1349 rev = cmdutil.revrange(repo, rev)
1316 rev.sort(lambda x, y: cmp(y, x))
1350 rev.sort(lambda x, y: cmp(y, x))
1317 if (len(files) > 1 or len(rev) > 1) and patchname:
1351 if (len(files) > 1 or len(rev) > 1) and patchname:
1318 raise util.Abort(_('option "-n" not valid when importing multiple '
1352 raise util.Abort(_('option "-n" not valid when importing multiple '
1319 'patches'))
1353 'patches'))
1320 i = 0
1354 i = 0
1321 added = []
1355 added = []
1322 if rev:
1356 if rev:
1323 # If mq patches are applied, we can only import revisions
1357 # If mq patches are applied, we can only import revisions
1324 # that form a linear path to qbase.
1358 # that form a linear path to qbase.
1325 # Otherwise, they should form a linear path to a head.
1359 # Otherwise, they should form a linear path to a head.
1326 heads = repo.changelog.heads(repo.changelog.node(rev[-1]))
1360 heads = repo.changelog.heads(repo.changelog.node(rev[-1]))
1327 if len(heads) > 1:
1361 if len(heads) > 1:
1328 raise util.Abort(_('revision %d is the root of more than one '
1362 raise util.Abort(_('revision %d is the root of more than one '
1329 'branch') % rev[-1])
1363 'branch') % rev[-1])
1330 if self.applied:
1364 if self.applied:
1331 base = revlog.hex(repo.changelog.node(rev[0]))
1365 base = revlog.hex(repo.changelog.node(rev[0]))
1332 if base in [n.rev for n in self.applied]:
1366 if base in [n.rev for n in self.applied]:
1333 raise util.Abort(_('revision %d is already managed')
1367 raise util.Abort(_('revision %d is already managed')
1334 % rev[0])
1368 % rev[0])
1335 if heads != [revlog.bin(self.applied[-1].rev)]:
1369 if heads != [revlog.bin(self.applied[-1].rev)]:
1336 raise util.Abort(_('revision %d is not the parent of '
1370 raise util.Abort(_('revision %d is not the parent of '
1337 'the queue') % rev[0])
1371 'the queue') % rev[0])
1338 base = repo.changelog.rev(revlog.bin(self.applied[0].rev))
1372 base = repo.changelog.rev(revlog.bin(self.applied[0].rev))
1339 lastparent = repo.changelog.parentrevs(base)[0]
1373 lastparent = repo.changelog.parentrevs(base)[0]
1340 else:
1374 else:
1341 if heads != [repo.changelog.node(rev[0])]:
1375 if heads != [repo.changelog.node(rev[0])]:
1342 raise util.Abort(_('revision %d has unmanaged children')
1376 raise util.Abort(_('revision %d has unmanaged children')
1343 % rev[0])
1377 % rev[0])
1344 lastparent = None
1378 lastparent = None
1345
1379
1346 if git:
1380 if git:
1347 self.diffopts().git = True
1381 self.diffopts().git = True
1348
1382
1349 for r in rev:
1383 for r in rev:
1350 p1, p2 = repo.changelog.parentrevs(r)
1384 p1, p2 = repo.changelog.parentrevs(r)
1351 n = repo.changelog.node(r)
1385 n = repo.changelog.node(r)
1352 if p2 != revlog.nullrev:
1386 if p2 != revlog.nullrev:
1353 raise util.Abort(_('cannot import merge revision %d') % r)
1387 raise util.Abort(_('cannot import merge revision %d') % r)
1354 if lastparent and lastparent != r:
1388 if lastparent and lastparent != r:
1355 raise util.Abort(_('revision %d is not the parent of %d')
1389 raise util.Abort(_('revision %d is not the parent of %d')
1356 % (r, lastparent))
1390 % (r, lastparent))
1357 lastparent = p1
1391 lastparent = p1
1358
1392
1359 if not patchname:
1393 if not patchname:
1360 patchname = '%d.diff' % r
1394 patchname = '%d.diff' % r
1361 checkseries(patchname)
1395 checkseries(patchname)
1362 checkfile(patchname)
1396 checkfile(patchname)
1363 self.full_series.insert(0, patchname)
1397 self.full_series.insert(0, patchname)
1364
1398
1365 patchf = self.opener(patchname, "w")
1399 patchf = self.opener(patchname, "w")
1366 patch.export(repo, [n], fp=patchf, opts=self.diffopts())
1400 patch.export(repo, [n], fp=patchf, opts=self.diffopts())
1367 patchf.close()
1401 patchf.close()
1368
1402
1369 se = statusentry(revlog.hex(n), patchname)
1403 se = statusentry(revlog.hex(n), patchname)
1370 self.applied.insert(0, se)
1404 self.applied.insert(0, se)
1371
1405
1372 added.append(patchname)
1406 added.append(patchname)
1373 patchname = None
1407 patchname = None
1374 self.parse_series()
1408 self.parse_series()
1375 self.applied_dirty = 1
1409 self.applied_dirty = 1
1376
1410
1377 for filename in files:
1411 for filename in files:
1378 if existing:
1412 if existing:
1379 if filename == '-':
1413 if filename == '-':
1380 raise util.Abort(_('-e is incompatible with import from -'))
1414 raise util.Abort(_('-e is incompatible with import from -'))
1381 if not patchname:
1415 if not patchname:
1382 patchname = filename
1416 patchname = filename
1383 if not os.path.isfile(self.join(patchname)):
1417 if not os.path.isfile(self.join(patchname)):
1384 raise util.Abort(_("patch %s does not exist") % patchname)
1418 raise util.Abort(_("patch %s does not exist") % patchname)
1385 else:
1419 else:
1386 try:
1420 try:
1387 if filename == '-':
1421 if filename == '-':
1388 if not patchname:
1422 if not patchname:
1389 raise util.Abort(_('need --name to import a patch from -'))
1423 raise util.Abort(_('need --name to import a patch from -'))
1390 text = sys.stdin.read()
1424 text = sys.stdin.read()
1391 else:
1425 else:
1392 text = file(filename).read()
1426 text = file(filename).read()
1393 except IOError:
1427 except IOError:
1394 raise util.Abort(_("unable to read %s") % patchname)
1428 raise util.Abort(_("unable to read %s") % patchname)
1395 if not patchname:
1429 if not patchname:
1396 patchname = os.path.basename(filename)
1430 patchname = os.path.basename(filename)
1397 checkfile(patchname)
1431 checkfile(patchname)
1398 patchf = self.opener(patchname, "w")
1432 patchf = self.opener(patchname, "w")
1399 patchf.write(text)
1433 patchf.write(text)
1400 checkseries(patchname)
1434 checkseries(patchname)
1401 index = self.full_series_end() + i
1435 index = self.full_series_end() + i
1402 self.full_series[index:index] = [patchname]
1436 self.full_series[index:index] = [patchname]
1403 self.parse_series()
1437 self.parse_series()
1404 self.ui.warn("adding %s to series file\n" % patchname)
1438 self.ui.warn("adding %s to series file\n" % patchname)
1405 i += 1
1439 i += 1
1406 added.append(patchname)
1440 added.append(patchname)
1407 patchname = None
1441 patchname = None
1408 self.series_dirty = 1
1442 self.series_dirty = 1
1409 qrepo = self.qrepo()
1443 qrepo = self.qrepo()
1410 if qrepo:
1444 if qrepo:
1411 qrepo.add(added)
1445 qrepo.add(added)
1412
1446
1413 def delete(ui, repo, *patches, **opts):
1447 def delete(ui, repo, *patches, **opts):
1414 """remove patches from queue
1448 """remove patches from queue
1415
1449
1416 With --rev, mq will stop managing the named revisions. The
1450 With --rev, mq will stop managing the named revisions. The
1417 patches must be applied and at the base of the stack. This option
1451 patches must be applied and at the base of the stack. This option
1418 is useful when the patches have been applied upstream.
1452 is useful when the patches have been applied upstream.
1419
1453
1420 Otherwise, the patches must not be applied.
1454 Otherwise, the patches must not be applied.
1421
1455
1422 With --keep, the patch files are preserved in the patch directory."""
1456 With --keep, the patch files are preserved in the patch directory."""
1423 q = repo.mq
1457 q = repo.mq
1424 q.delete(repo, patches, opts)
1458 q.delete(repo, patches, opts)
1425 q.save_dirty()
1459 q.save_dirty()
1426 return 0
1460 return 0
1427
1461
1428 def applied(ui, repo, patch=None, **opts):
1462 def applied(ui, repo, patch=None, **opts):
1429 """print the patches already applied"""
1463 """print the patches already applied"""
1430 q = repo.mq
1464 q = repo.mq
1431 if patch:
1465 if patch:
1432 if patch not in q.series:
1466 if patch not in q.series:
1433 raise util.Abort(_("patch %s is not in series file") % patch)
1467 raise util.Abort(_("patch %s is not in series file") % patch)
1434 end = q.series.index(patch) + 1
1468 end = q.series.index(patch) + 1
1435 else:
1469 else:
1436 end = q.series_end(True)
1470 end = q.series_end(True)
1437 return q.qseries(repo, length=end, status='A', summary=opts.get('summary'))
1471 return q.qseries(repo, length=end, status='A', summary=opts.get('summary'))
1438
1472
1439 def unapplied(ui, repo, patch=None, **opts):
1473 def unapplied(ui, repo, patch=None, **opts):
1440 """print the patches not yet applied"""
1474 """print the patches not yet applied"""
1441 q = repo.mq
1475 q = repo.mq
1442 if patch:
1476 if patch:
1443 if patch not in q.series:
1477 if patch not in q.series:
1444 raise util.Abort(_("patch %s is not in series file") % patch)
1478 raise util.Abort(_("patch %s is not in series file") % patch)
1445 start = q.series.index(patch) + 1
1479 start = q.series.index(patch) + 1
1446 else:
1480 else:
1447 start = q.series_end(True)
1481 start = q.series_end(True)
1448 q.qseries(repo, start=start, status='U', summary=opts.get('summary'))
1482 q.qseries(repo, start=start, status='U', summary=opts.get('summary'))
1449
1483
1450 def qimport(ui, repo, *filename, **opts):
1484 def qimport(ui, repo, *filename, **opts):
1451 """import a patch
1485 """import a patch
1452
1486
1453 The patch will have the same name as its source file unless you
1487 The patch will have the same name as its source file unless you
1454 give it a new one with --name.
1488 give it a new one with --name.
1455
1489
1456 You can register an existing patch inside the patch directory
1490 You can register an existing patch inside the patch directory
1457 with the --existing flag.
1491 with the --existing flag.
1458
1492
1459 With --force, an existing patch of the same name will be overwritten.
1493 With --force, an existing patch of the same name will be overwritten.
1460
1494
1461 An existing changeset may be placed under mq control with --rev
1495 An existing changeset may be placed under mq control with --rev
1462 (e.g. qimport --rev tip -n patch will place tip under mq control).
1496 (e.g. qimport --rev tip -n patch will place tip under mq control).
1463 With --git, patches imported with --rev will use the git diff
1497 With --git, patches imported with --rev will use the git diff
1464 format.
1498 format.
1465 """
1499 """
1466 q = repo.mq
1500 q = repo.mq
1467 q.qimport(repo, filename, patchname=opts['name'],
1501 q.qimport(repo, filename, patchname=opts['name'],
1468 existing=opts['existing'], force=opts['force'], rev=opts['rev'],
1502 existing=opts['existing'], force=opts['force'], rev=opts['rev'],
1469 git=opts['git'])
1503 git=opts['git'])
1470 q.save_dirty()
1504 q.save_dirty()
1471 return 0
1505 return 0
1472
1506
1473 def init(ui, repo, **opts):
1507 def init(ui, repo, **opts):
1474 """init a new queue repository
1508 """init a new queue repository
1475
1509
1476 The queue repository is unversioned by default. If -c is
1510 The queue repository is unversioned by default. If -c is
1477 specified, qinit will create a separate nested repository
1511 specified, qinit will create a separate nested repository
1478 for patches. Use qcommit to commit changes to this queue
1512 for patches. Use qcommit to commit changes to this queue
1479 repository."""
1513 repository."""
1480 q = repo.mq
1514 q = repo.mq
1481 r = q.init(repo, create=opts['create_repo'])
1515 r = q.init(repo, create=opts['create_repo'])
1482 q.save_dirty()
1516 q.save_dirty()
1483 if r:
1517 if r:
1484 fp = r.wopener('.hgignore', 'w')
1518 fp = r.wopener('.hgignore', 'w')
1485 print >> fp, 'syntax: glob'
1519 print >> fp, 'syntax: glob'
1486 print >> fp, 'status'
1520 print >> fp, 'status'
1487 print >> fp, 'guards'
1521 print >> fp, 'guards'
1488 fp.close()
1522 fp.close()
1489 r.wopener('series', 'w').close()
1523 r.wopener('series', 'w').close()
1490 r.add(['.hgignore', 'series'])
1524 r.add(['.hgignore', 'series'])
1491 return 0
1525 return 0
1492
1526
1493 def clone(ui, source, dest=None, **opts):
1527 def clone(ui, source, dest=None, **opts):
1494 '''clone main and patch repository at same time
1528 '''clone main and patch repository at same time
1495
1529
1496 If source is local, destination will have no patches applied. If
1530 If source is local, destination will have no patches applied. If
1497 source is remote, this command can not check if patches are
1531 source is remote, this command can not check if patches are
1498 applied in source, so cannot guarantee that patches are not
1532 applied in source, so cannot guarantee that patches are not
1499 applied in destination. If you clone remote repository, be sure
1533 applied in destination. If you clone remote repository, be sure
1500 before that it has no patches applied.
1534 before that it has no patches applied.
1501
1535
1502 Source patch repository is looked for in <src>/.hg/patches by
1536 Source patch repository is looked for in <src>/.hg/patches by
1503 default. Use -p <url> to change.
1537 default. Use -p <url> to change.
1504 '''
1538 '''
1505 commands.setremoteconfig(ui, opts)
1539 commands.setremoteconfig(ui, opts)
1506 if dest is None:
1540 if dest is None:
1507 dest = hg.defaultdest(source)
1541 dest = hg.defaultdest(source)
1508 sr = hg.repository(ui, ui.expandpath(source))
1542 sr = hg.repository(ui, ui.expandpath(source))
1509 qbase, destrev = None, None
1543 qbase, destrev = None, None
1510 if sr.local():
1544 if sr.local():
1511 if sr.mq.applied:
1545 if sr.mq.applied:
1512 qbase = revlog.bin(sr.mq.applied[0].rev)
1546 qbase = revlog.bin(sr.mq.applied[0].rev)
1513 if not hg.islocal(dest):
1547 if not hg.islocal(dest):
1514 heads = dict.fromkeys(sr.heads())
1548 heads = dict.fromkeys(sr.heads())
1515 for h in sr.heads(qbase):
1549 for h in sr.heads(qbase):
1516 del heads[h]
1550 del heads[h]
1517 destrev = heads.keys()
1551 destrev = heads.keys()
1518 destrev.append(sr.changelog.parents(qbase)[0])
1552 destrev.append(sr.changelog.parents(qbase)[0])
1519 ui.note(_('cloning main repo\n'))
1553 ui.note(_('cloning main repo\n'))
1520 sr, dr = hg.clone(ui, sr, dest,
1554 sr, dr = hg.clone(ui, sr, dest,
1521 pull=opts['pull'],
1555 pull=opts['pull'],
1522 rev=destrev,
1556 rev=destrev,
1523 update=False,
1557 update=False,
1524 stream=opts['uncompressed'])
1558 stream=opts['uncompressed'])
1525 ui.note(_('cloning patch repo\n'))
1559 ui.note(_('cloning patch repo\n'))
1526 spr, dpr = hg.clone(ui, opts['patches'] or (sr.url() + '/.hg/patches'),
1560 spr, dpr = hg.clone(ui, opts['patches'] or (sr.url() + '/.hg/patches'),
1527 dr.url() + '/.hg/patches',
1561 dr.url() + '/.hg/patches',
1528 pull=opts['pull'],
1562 pull=opts['pull'],
1529 update=not opts['noupdate'],
1563 update=not opts['noupdate'],
1530 stream=opts['uncompressed'])
1564 stream=opts['uncompressed'])
1531 if dr.local():
1565 if dr.local():
1532 if qbase:
1566 if qbase:
1533 ui.note(_('stripping applied patches from destination repo\n'))
1567 ui.note(_('stripping applied patches from destination repo\n'))
1534 dr.mq.strip(dr, qbase, update=False, backup=None)
1568 dr.mq.strip(dr, qbase, update=False, backup=None)
1535 if not opts['noupdate']:
1569 if not opts['noupdate']:
1536 ui.note(_('updating destination repo\n'))
1570 ui.note(_('updating destination repo\n'))
1537 hg.update(dr, dr.changelog.tip())
1571 hg.update(dr, dr.changelog.tip())
1538
1572
1539 def commit(ui, repo, *pats, **opts):
1573 def commit(ui, repo, *pats, **opts):
1540 """commit changes in the queue repository"""
1574 """commit changes in the queue repository"""
1541 q = repo.mq
1575 q = repo.mq
1542 r = q.qrepo()
1576 r = q.qrepo()
1543 if not r: raise util.Abort('no queue repository')
1577 if not r: raise util.Abort('no queue repository')
1544 commands.commit(r.ui, r, *pats, **opts)
1578 commands.commit(r.ui, r, *pats, **opts)
1545
1579
1546 def series(ui, repo, **opts):
1580 def series(ui, repo, **opts):
1547 """print the entire series file"""
1581 """print the entire series file"""
1548 repo.mq.qseries(repo, missing=opts['missing'], summary=opts['summary'])
1582 repo.mq.qseries(repo, missing=opts['missing'], summary=opts['summary'])
1549 return 0
1583 return 0
1550
1584
1551 def top(ui, repo, **opts):
1585 def top(ui, repo, **opts):
1552 """print the name of the current patch"""
1586 """print the name of the current patch"""
1553 q = repo.mq
1587 q = repo.mq
1554 t = q.applied and q.series_end(True) or 0
1588 t = q.applied and q.series_end(True) or 0
1555 if t:
1589 if t:
1556 return q.qseries(repo, start=t-1, length=1, status='A',
1590 return q.qseries(repo, start=t-1, length=1, status='A',
1557 summary=opts.get('summary'))
1591 summary=opts.get('summary'))
1558 else:
1592 else:
1559 ui.write("No patches applied\n")
1593 ui.write("No patches applied\n")
1560 return 1
1594 return 1
1561
1595
1562 def next(ui, repo, **opts):
1596 def next(ui, repo, **opts):
1563 """print the name of the next patch"""
1597 """print the name of the next patch"""
1564 q = repo.mq
1598 q = repo.mq
1565 end = q.series_end()
1599 end = q.series_end()
1566 if end == len(q.series):
1600 if end == len(q.series):
1567 ui.write("All patches applied\n")
1601 ui.write("All patches applied\n")
1568 return 1
1602 return 1
1569 return q.qseries(repo, start=end, length=1, summary=opts.get('summary'))
1603 return q.qseries(repo, start=end, length=1, summary=opts.get('summary'))
1570
1604
1571 def prev(ui, repo, **opts):
1605 def prev(ui, repo, **opts):
1572 """print the name of the previous patch"""
1606 """print the name of the previous patch"""
1573 q = repo.mq
1607 q = repo.mq
1574 l = len(q.applied)
1608 l = len(q.applied)
1575 if l == 1:
1609 if l == 1:
1576 ui.write("Only one patch applied\n")
1610 ui.write("Only one patch applied\n")
1577 return 1
1611 return 1
1578 if not l:
1612 if not l:
1579 ui.write("No patches applied\n")
1613 ui.write("No patches applied\n")
1580 return 1
1614 return 1
1581 return q.qseries(repo, start=l-2, length=1, status='A',
1615 return q.qseries(repo, start=l-2, length=1, status='A',
1582 summary=opts.get('summary'))
1616 summary=opts.get('summary'))
1583
1617
1584 def new(ui, repo, patch, **opts):
1618 def new(ui, repo, patch, **opts):
1585 """create a new patch
1619 """create a new patch
1586
1620
1587 qnew creates a new patch on top of the currently-applied patch
1621 qnew creates a new patch on top of the currently-applied patch
1588 (if any). It will refuse to run if there are any outstanding
1622 (if any). It will refuse to run if there are any outstanding
1589 changes unless -f is specified, in which case the patch will
1623 changes unless -f is specified, in which case the patch will
1590 be initialised with them.
1624 be initialised with them.
1591
1625
1592 -e, -m or -l set the patch header as well as the commit message.
1626 -e, -m or -l set the patch header as well as the commit message.
1593 If none is specified, the patch header is empty and the
1627 If none is specified, the patch header is empty and the
1594 commit message is 'New patch: PATCH'"""
1628 commit message is 'New patch: PATCH'"""
1595 q = repo.mq
1629 q = repo.mq
1596 message = commands.logmessage(opts)
1630 message = commands.logmessage(opts)
1597 if opts['edit']:
1631 if opts['edit']:
1598 message = ui.edit(message, ui.username())
1632 message = ui.edit(message, ui.username())
1599 q.new(repo, patch, msg=message, force=opts['force'])
1633 q.new(repo, patch, msg=message, force=opts['force'])
1600 q.save_dirty()
1634 q.save_dirty()
1601 return 0
1635 return 0
1602
1636
1603 def refresh(ui, repo, *pats, **opts):
1637 def refresh(ui, repo, *pats, **opts):
1604 """update the current patch
1638 """update the current patch
1605
1639
1606 If any file patterns are provided, the refreshed patch will contain only
1640 If any file patterns are provided, the refreshed patch will contain only
1607 the modifications that match those patterns; the remaining modifications
1641 the modifications that match those patterns; the remaining modifications
1608 will remain in the working directory.
1642 will remain in the working directory.
1609 """
1643 """
1610 q = repo.mq
1644 q = repo.mq
1611 message = commands.logmessage(opts)
1645 message = commands.logmessage(opts)
1612 if opts['edit']:
1646 if opts['edit']:
1613 if message:
1647 if message:
1614 raise util.Abort(_('option "-e" incompatible with "-m" or "-l"'))
1648 raise util.Abort(_('option "-e" incompatible with "-m" or "-l"'))
1615 patch = q.applied[-1].name
1649 patch = q.applied[-1].name
1616 (message, comment, user, date, hasdiff) = q.readheaders(patch)
1650 (message, comment, user, date, hasdiff) = q.readheaders(patch)
1617 message = ui.edit('\n'.join(message), user or ui.username())
1651 message = ui.edit('\n'.join(message), user or ui.username())
1618 ret = q.refresh(repo, pats, msg=message, **opts)
1652 ret = q.refresh(repo, pats, msg=message, **opts)
1619 q.save_dirty()
1653 q.save_dirty()
1620 return ret
1654 return ret
1621
1655
1622 def diff(ui, repo, *pats, **opts):
1656 def diff(ui, repo, *pats, **opts):
1623 """diff of the current patch"""
1657 """diff of the current patch"""
1624 repo.mq.diff(repo, pats, opts)
1658 repo.mq.diff(repo, pats, opts)
1625 return 0
1659 return 0
1626
1660
1627 def fold(ui, repo, *files, **opts):
1661 def fold(ui, repo, *files, **opts):
1628 """fold the named patches into the current patch
1662 """fold the named patches into the current patch
1629
1663
1630 Patches must not yet be applied. Each patch will be successively
1664 Patches must not yet be applied. Each patch will be successively
1631 applied to the current patch in the order given. If all the
1665 applied to the current patch in the order given. If all the
1632 patches apply successfully, the current patch will be refreshed
1666 patches apply successfully, the current patch will be refreshed
1633 with the new cumulative patch, and the folded patches will
1667 with the new cumulative patch, and the folded patches will
1634 be deleted. With -k/--keep, the folded patch files will not
1668 be deleted. With -k/--keep, the folded patch files will not
1635 be removed afterwards.
1669 be removed afterwards.
1636
1670
1637 The header for each folded patch will be concatenated with
1671 The header for each folded patch will be concatenated with
1638 the current patch header, separated by a line of '* * *'."""
1672 the current patch header, separated by a line of '* * *'."""
1639
1673
1640 q = repo.mq
1674 q = repo.mq
1641
1675
1642 if not files:
1676 if not files:
1643 raise util.Abort(_('qfold requires at least one patch name'))
1677 raise util.Abort(_('qfold requires at least one patch name'))
1644 if not q.check_toppatch(repo):
1678 if not q.check_toppatch(repo):
1645 raise util.Abort(_('No patches applied'))
1679 raise util.Abort(_('No patches applied'))
1646
1680
1647 message = commands.logmessage(opts)
1681 message = commands.logmessage(opts)
1648 if opts['edit']:
1682 if opts['edit']:
1649 if message:
1683 if message:
1650 raise util.Abort(_('option "-e" incompatible with "-m" or "-l"'))
1684 raise util.Abort(_('option "-e" incompatible with "-m" or "-l"'))
1651
1685
1652 parent = q.lookup('qtip')
1686 parent = q.lookup('qtip')
1653 patches = []
1687 patches = []
1654 messages = []
1688 messages = []
1655 for f in files:
1689 for f in files:
1656 p = q.lookup(f)
1690 p = q.lookup(f)
1657 if p in patches or p == parent:
1691 if p in patches or p == parent:
1658 ui.warn(_('Skipping already folded patch %s') % p)
1692 ui.warn(_('Skipping already folded patch %s') % p)
1659 if q.isapplied(p):
1693 if q.isapplied(p):
1660 raise util.Abort(_('qfold cannot fold already applied patch %s') % p)
1694 raise util.Abort(_('qfold cannot fold already applied patch %s') % p)
1661 patches.append(p)
1695 patches.append(p)
1662
1696
1663 for p in patches:
1697 for p in patches:
1664 if not message:
1698 if not message:
1665 messages.append(q.readheaders(p)[0])
1699 messages.append(q.readheaders(p)[0])
1666 pf = q.join(p)
1700 pf = q.join(p)
1667 (patchsuccess, files, fuzz) = q.patch(repo, pf)
1701 (patchsuccess, files, fuzz) = q.patch(repo, pf)
1668 if not patchsuccess:
1702 if not patchsuccess:
1669 raise util.Abort(_('Error folding patch %s') % p)
1703 raise util.Abort(_('Error folding patch %s') % p)
1670 patch.updatedir(ui, repo, files)
1704 patch.updatedir(ui, repo, files)
1671
1705
1672 if not message:
1706 if not message:
1673 message, comments, user = q.readheaders(parent)[0:3]
1707 message, comments, user = q.readheaders(parent)[0:3]
1674 for msg in messages:
1708 for msg in messages:
1675 message.append('* * *')
1709 message.append('* * *')
1676 message.extend(msg)
1710 message.extend(msg)
1677 message = '\n'.join(message)
1711 message = '\n'.join(message)
1678
1712
1679 if opts['edit']:
1713 if opts['edit']:
1680 message = ui.edit(message, user or ui.username())
1714 message = ui.edit(message, user or ui.username())
1681
1715
1682 q.refresh(repo, msg=message)
1716 q.refresh(repo, msg=message)
1683 q.delete(repo, patches, opts)
1717 q.delete(repo, patches, opts)
1684 q.save_dirty()
1718 q.save_dirty()
1685
1719
1686 def guard(ui, repo, *args, **opts):
1720 def guard(ui, repo, *args, **opts):
1687 '''set or print guards for a patch
1721 '''set or print guards for a patch
1688
1722
1689 Guards control whether a patch can be pushed. A patch with no
1723 Guards control whether a patch can be pushed. A patch with no
1690 guards is always pushed. A patch with a positive guard ("+foo") is
1724 guards is always pushed. A patch with a positive guard ("+foo") is
1691 pushed only if the qselect command has activated it. A patch with
1725 pushed only if the qselect command has activated it. A patch with
1692 a negative guard ("-foo") is never pushed if the qselect command
1726 a negative guard ("-foo") is never pushed if the qselect command
1693 has activated it.
1727 has activated it.
1694
1728
1695 With no arguments, print the currently active guards.
1729 With no arguments, print the currently active guards.
1696 With arguments, set guards for the named patch.
1730 With arguments, set guards for the named patch.
1697
1731
1698 To set a negative guard "-foo" on topmost patch ("--" is needed so
1732 To set a negative guard "-foo" on topmost patch ("--" is needed so
1699 hg will not interpret "-foo" as an option):
1733 hg will not interpret "-foo" as an option):
1700 hg qguard -- -foo
1734 hg qguard -- -foo
1701
1735
1702 To set guards on another patch:
1736 To set guards on another patch:
1703 hg qguard other.patch +2.6.17 -stable
1737 hg qguard other.patch +2.6.17 -stable
1704 '''
1738 '''
1705 def status(idx):
1739 def status(idx):
1706 guards = q.series_guards[idx] or ['unguarded']
1740 guards = q.series_guards[idx] or ['unguarded']
1707 ui.write('%s: %s\n' % (q.series[idx], ' '.join(guards)))
1741 ui.write('%s: %s\n' % (q.series[idx], ' '.join(guards)))
1708 q = repo.mq
1742 q = repo.mq
1709 patch = None
1743 patch = None
1710 args = list(args)
1744 args = list(args)
1711 if opts['list']:
1745 if opts['list']:
1712 if args or opts['none']:
1746 if args or opts['none']:
1713 raise util.Abort(_('cannot mix -l/--list with options or arguments'))
1747 raise util.Abort(_('cannot mix -l/--list with options or arguments'))
1714 for i in xrange(len(q.series)):
1748 for i in xrange(len(q.series)):
1715 status(i)
1749 status(i)
1716 return
1750 return
1717 if not args or args[0][0:1] in '-+':
1751 if not args or args[0][0:1] in '-+':
1718 if not q.applied:
1752 if not q.applied:
1719 raise util.Abort(_('no patches applied'))
1753 raise util.Abort(_('no patches applied'))
1720 patch = q.applied[-1].name
1754 patch = q.applied[-1].name
1721 if patch is None and args[0][0:1] not in '-+':
1755 if patch is None and args[0][0:1] not in '-+':
1722 patch = args.pop(0)
1756 patch = args.pop(0)
1723 if patch is None:
1757 if patch is None:
1724 raise util.Abort(_('no patch to work with'))
1758 raise util.Abort(_('no patch to work with'))
1725 if args or opts['none']:
1759 if args or opts['none']:
1726 idx = q.find_series(patch)
1760 idx = q.find_series(patch)
1727 if idx is None:
1761 if idx is None:
1728 raise util.Abort(_('no patch named %s') % patch)
1762 raise util.Abort(_('no patch named %s') % patch)
1729 q.set_guards(idx, args)
1763 q.set_guards(idx, args)
1730 q.save_dirty()
1764 q.save_dirty()
1731 else:
1765 else:
1732 status(q.series.index(q.lookup(patch)))
1766 status(q.series.index(q.lookup(patch)))
1733
1767
1734 def header(ui, repo, patch=None):
1768 def header(ui, repo, patch=None):
1735 """Print the header of the topmost or specified patch"""
1769 """Print the header of the topmost or specified patch"""
1736 q = repo.mq
1770 q = repo.mq
1737
1771
1738 if patch:
1772 if patch:
1739 patch = q.lookup(patch)
1773 patch = q.lookup(patch)
1740 else:
1774 else:
1741 if not q.applied:
1775 if not q.applied:
1742 ui.write('No patches applied\n')
1776 ui.write('No patches applied\n')
1743 return 1
1777 return 1
1744 patch = q.lookup('qtip')
1778 patch = q.lookup('qtip')
1745 message = repo.mq.readheaders(patch)[0]
1779 message = repo.mq.readheaders(patch)[0]
1746
1780
1747 ui.write('\n'.join(message) + '\n')
1781 ui.write('\n'.join(message) + '\n')
1748
1782
1749 def lastsavename(path):
1783 def lastsavename(path):
1750 (directory, base) = os.path.split(path)
1784 (directory, base) = os.path.split(path)
1751 names = os.listdir(directory)
1785 names = os.listdir(directory)
1752 namere = re.compile("%s.([0-9]+)" % base)
1786 namere = re.compile("%s.([0-9]+)" % base)
1753 maxindex = None
1787 maxindex = None
1754 maxname = None
1788 maxname = None
1755 for f in names:
1789 for f in names:
1756 m = namere.match(f)
1790 m = namere.match(f)
1757 if m:
1791 if m:
1758 index = int(m.group(1))
1792 index = int(m.group(1))
1759 if maxindex == None or index > maxindex:
1793 if maxindex == None or index > maxindex:
1760 maxindex = index
1794 maxindex = index
1761 maxname = f
1795 maxname = f
1762 if maxname:
1796 if maxname:
1763 return (os.path.join(directory, maxname), maxindex)
1797 return (os.path.join(directory, maxname), maxindex)
1764 return (None, None)
1798 return (None, None)
1765
1799
1766 def savename(path):
1800 def savename(path):
1767 (last, index) = lastsavename(path)
1801 (last, index) = lastsavename(path)
1768 if last is None:
1802 if last is None:
1769 index = 0
1803 index = 0
1770 newpath = path + ".%d" % (index + 1)
1804 newpath = path + ".%d" % (index + 1)
1771 return newpath
1805 return newpath
1772
1806
1773 def push(ui, repo, patch=None, **opts):
1807 def push(ui, repo, patch=None, **opts):
1774 """push the next patch onto the stack"""
1808 """push the next patch onto the stack"""
1775 q = repo.mq
1809 q = repo.mq
1776 mergeq = None
1810 mergeq = None
1777
1811
1778 if opts['all']:
1812 if opts['all']:
1779 if not q.series:
1813 if not q.series:
1780 raise util.Abort(_('no patches in series'))
1814 raise util.Abort(_('no patches in series'))
1781 patch = q.series[-1]
1815 patch = q.series[-1]
1782 if opts['merge']:
1816 if opts['merge']:
1783 if opts['name']:
1817 if opts['name']:
1784 newpath = opts['name']
1818 newpath = opts['name']
1785 else:
1819 else:
1786 newpath, i = lastsavename(q.path)
1820 newpath, i = lastsavename(q.path)
1787 if not newpath:
1821 if not newpath:
1788 ui.warn("no saved queues found, please use -n\n")
1822 ui.warn("no saved queues found, please use -n\n")
1789 return 1
1823 return 1
1790 mergeq = queue(ui, repo.join(""), newpath)
1824 mergeq = queue(ui, repo.join(""), newpath)
1791 ui.warn("merging with queue at: %s\n" % mergeq.path)
1825 ui.warn("merging with queue at: %s\n" % mergeq.path)
1792 ret = q.push(repo, patch, force=opts['force'], list=opts['list'],
1826 ret = q.push(repo, patch, force=opts['force'], list=opts['list'],
1793 mergeq=mergeq)
1827 mergeq=mergeq)
1794 q.save_dirty()
1795 return ret
1828 return ret
1796
1829
1797 def pop(ui, repo, patch=None, **opts):
1830 def pop(ui, repo, patch=None, **opts):
1798 """pop the current patch off the stack"""
1831 """pop the current patch off the stack"""
1799 localupdate = True
1832 localupdate = True
1800 if opts['name']:
1833 if opts['name']:
1801 q = queue(ui, repo.join(""), repo.join(opts['name']))
1834 q = queue(ui, repo.join(""), repo.join(opts['name']))
1802 ui.warn('using patch queue: %s\n' % q.path)
1835 ui.warn('using patch queue: %s\n' % q.path)
1803 localupdate = False
1836 localupdate = False
1804 else:
1837 else:
1805 q = repo.mq
1838 q = repo.mq
1806 q.pop(repo, patch, force=opts['force'], update=localupdate, all=opts['all'])
1839 q.pop(repo, patch, force=opts['force'], update=localupdate, all=opts['all'])
1807 q.save_dirty()
1840 q.save_dirty()
1808 return 0
1841 return 0
1809
1842
1810 def rename(ui, repo, patch, name=None, **opts):
1843 def rename(ui, repo, patch, name=None, **opts):
1811 """rename a patch
1844 """rename a patch
1812
1845
1813 With one argument, renames the current patch to PATCH1.
1846 With one argument, renames the current patch to PATCH1.
1814 With two arguments, renames PATCH1 to PATCH2."""
1847 With two arguments, renames PATCH1 to PATCH2."""
1815
1848
1816 q = repo.mq
1849 q = repo.mq
1817
1850
1818 if not name:
1851 if not name:
1819 name = patch
1852 name = patch
1820 patch = None
1853 patch = None
1821
1854
1822 if patch:
1855 if patch:
1823 patch = q.lookup(patch)
1856 patch = q.lookup(patch)
1824 else:
1857 else:
1825 if not q.applied:
1858 if not q.applied:
1826 ui.write(_('No patches applied\n'))
1859 ui.write(_('No patches applied\n'))
1827 return
1860 return
1828 patch = q.lookup('qtip')
1861 patch = q.lookup('qtip')
1829 absdest = q.join(name)
1862 absdest = q.join(name)
1830 if os.path.isdir(absdest):
1863 if os.path.isdir(absdest):
1831 name = os.path.join(name, os.path.basename(patch))
1864 name = os.path.join(name, os.path.basename(patch))
1832 absdest = q.join(name)
1865 absdest = q.join(name)
1833 if os.path.exists(absdest):
1866 if os.path.exists(absdest):
1834 raise util.Abort(_('%s already exists') % absdest)
1867 raise util.Abort(_('%s already exists') % absdest)
1835
1868
1836 if name in q.series:
1869 if name in q.series:
1837 raise util.Abort(_('A patch named %s already exists in the series file') % name)
1870 raise util.Abort(_('A patch named %s already exists in the series file') % name)
1838
1871
1839 if ui.verbose:
1872 if ui.verbose:
1840 ui.write('Renaming %s to %s\n' % (patch, name))
1873 ui.write('Renaming %s to %s\n' % (patch, name))
1841 i = q.find_series(patch)
1874 i = q.find_series(patch)
1842 guards = q.guard_re.findall(q.full_series[i])
1875 guards = q.guard_re.findall(q.full_series[i])
1843 q.full_series[i] = name + ''.join([' #' + g for g in guards])
1876 q.full_series[i] = name + ''.join([' #' + g for g in guards])
1844 q.parse_series()
1877 q.parse_series()
1845 q.series_dirty = 1
1878 q.series_dirty = 1
1846
1879
1847 info = q.isapplied(patch)
1880 info = q.isapplied(patch)
1848 if info:
1881 if info:
1849 q.applied[info[0]] = statusentry(info[1], name)
1882 q.applied[info[0]] = statusentry(info[1], name)
1850 q.applied_dirty = 1
1883 q.applied_dirty = 1
1851
1884
1852 util.rename(q.join(patch), absdest)
1885 util.rename(q.join(patch), absdest)
1853 r = q.qrepo()
1886 r = q.qrepo()
1854 if r:
1887 if r:
1855 wlock = r.wlock()
1888 wlock = r.wlock()
1856 if r.dirstate.state(name) == 'r':
1889 if r.dirstate.state(name) == 'r':
1857 r.undelete([name], wlock)
1890 r.undelete([name], wlock)
1858 r.copy(patch, name, wlock)
1891 r.copy(patch, name, wlock)
1859 r.remove([patch], False, wlock)
1892 r.remove([patch], False, wlock)
1860
1893
1861 q.save_dirty()
1894 q.save_dirty()
1862
1895
1863 def restore(ui, repo, rev, **opts):
1896 def restore(ui, repo, rev, **opts):
1864 """restore the queue state saved by a rev"""
1897 """restore the queue state saved by a rev"""
1865 rev = repo.lookup(rev)
1898 rev = repo.lookup(rev)
1866 q = repo.mq
1899 q = repo.mq
1867 q.restore(repo, rev, delete=opts['delete'],
1900 q.restore(repo, rev, delete=opts['delete'],
1868 qupdate=opts['update'])
1901 qupdate=opts['update'])
1869 q.save_dirty()
1902 q.save_dirty()
1870 return 0
1903 return 0
1871
1904
1872 def save(ui, repo, **opts):
1905 def save(ui, repo, **opts):
1873 """save current queue state"""
1906 """save current queue state"""
1874 q = repo.mq
1907 q = repo.mq
1875 message = commands.logmessage(opts)
1908 message = commands.logmessage(opts)
1876 ret = q.save(repo, msg=message)
1909 ret = q.save(repo, msg=message)
1877 if ret:
1910 if ret:
1878 return ret
1911 return ret
1879 q.save_dirty()
1912 q.save_dirty()
1880 if opts['copy']:
1913 if opts['copy']:
1881 path = q.path
1914 path = q.path
1882 if opts['name']:
1915 if opts['name']:
1883 newpath = os.path.join(q.basepath, opts['name'])
1916 newpath = os.path.join(q.basepath, opts['name'])
1884 if os.path.exists(newpath):
1917 if os.path.exists(newpath):
1885 if not os.path.isdir(newpath):
1918 if not os.path.isdir(newpath):
1886 raise util.Abort(_('destination %s exists and is not '
1919 raise util.Abort(_('destination %s exists and is not '
1887 'a directory') % newpath)
1920 'a directory') % newpath)
1888 if not opts['force']:
1921 if not opts['force']:
1889 raise util.Abort(_('destination %s exists, '
1922 raise util.Abort(_('destination %s exists, '
1890 'use -f to force') % newpath)
1923 'use -f to force') % newpath)
1891 else:
1924 else:
1892 newpath = savename(path)
1925 newpath = savename(path)
1893 ui.warn("copy %s to %s\n" % (path, newpath))
1926 ui.warn("copy %s to %s\n" % (path, newpath))
1894 util.copyfiles(path, newpath)
1927 util.copyfiles(path, newpath)
1895 if opts['empty']:
1928 if opts['empty']:
1896 try:
1929 try:
1897 os.unlink(q.join(q.status_path))
1930 os.unlink(q.join(q.status_path))
1898 except:
1931 except:
1899 pass
1932 pass
1900 return 0
1933 return 0
1901
1934
1902 def strip(ui, repo, rev, **opts):
1935 def strip(ui, repo, rev, **opts):
1903 """strip a revision and all later revs on the same branch"""
1936 """strip a revision and all later revs on the same branch"""
1904 rev = repo.lookup(rev)
1937 rev = repo.lookup(rev)
1905 backup = 'all'
1938 backup = 'all'
1906 if opts['backup']:
1939 if opts['backup']:
1907 backup = 'strip'
1940 backup = 'strip'
1908 elif opts['nobackup']:
1941 elif opts['nobackup']:
1909 backup = 'none'
1942 backup = 'none'
1910 update = repo.dirstate.parents()[0] != revlog.nullid
1943 update = repo.dirstate.parents()[0] != revlog.nullid
1911 repo.mq.strip(repo, rev, backup=backup, update=update)
1944 repo.mq.strip(repo, rev, backup=backup, update=update)
1912 return 0
1945 return 0
1913
1946
1914 def select(ui, repo, *args, **opts):
1947 def select(ui, repo, *args, **opts):
1915 '''set or print guarded patches to push
1948 '''set or print guarded patches to push
1916
1949
1917 Use the qguard command to set or print guards on patch, then use
1950 Use the qguard command to set or print guards on patch, then use
1918 qselect to tell mq which guards to use. A patch will be pushed if it
1951 qselect to tell mq which guards to use. A patch will be pushed if it
1919 has no guards or any positive guards match the currently selected guard,
1952 has no guards or any positive guards match the currently selected guard,
1920 but will not be pushed if any negative guards match the current guard.
1953 but will not be pushed if any negative guards match the current guard.
1921 For example:
1954 For example:
1922
1955
1923 qguard foo.patch -stable (negative guard)
1956 qguard foo.patch -stable (negative guard)
1924 qguard bar.patch +stable (positive guard)
1957 qguard bar.patch +stable (positive guard)
1925 qselect stable
1958 qselect stable
1926
1959
1927 This activates the "stable" guard. mq will skip foo.patch (because
1960 This activates the "stable" guard. mq will skip foo.patch (because
1928 it has a negative match) but push bar.patch (because it
1961 it has a negative match) but push bar.patch (because it
1929 has a positive match).
1962 has a positive match).
1930
1963
1931 With no arguments, prints the currently active guards.
1964 With no arguments, prints the currently active guards.
1932 With one argument, sets the active guard.
1965 With one argument, sets the active guard.
1933
1966
1934 Use -n/--none to deactivate guards (no other arguments needed).
1967 Use -n/--none to deactivate guards (no other arguments needed).
1935 When no guards are active, patches with positive guards are skipped
1968 When no guards are active, patches with positive guards are skipped
1936 and patches with negative guards are pushed.
1969 and patches with negative guards are pushed.
1937
1970
1938 qselect can change the guards on applied patches. It does not pop
1971 qselect can change the guards on applied patches. It does not pop
1939 guarded patches by default. Use --pop to pop back to the last applied
1972 guarded patches by default. Use --pop to pop back to the last applied
1940 patch that is not guarded. Use --reapply (which implies --pop) to push
1973 patch that is not guarded. Use --reapply (which implies --pop) to push
1941 back to the current patch afterwards, but skip guarded patches.
1974 back to the current patch afterwards, but skip guarded patches.
1942
1975
1943 Use -s/--series to print a list of all guards in the series file (no
1976 Use -s/--series to print a list of all guards in the series file (no
1944 other arguments needed). Use -v for more information.'''
1977 other arguments needed). Use -v for more information.'''
1945
1978
1946 q = repo.mq
1979 q = repo.mq
1947 guards = q.active()
1980 guards = q.active()
1948 if args or opts['none']:
1981 if args or opts['none']:
1949 old_unapplied = q.unapplied(repo)
1982 old_unapplied = q.unapplied(repo)
1950 old_guarded = [i for i in xrange(len(q.applied)) if
1983 old_guarded = [i for i in xrange(len(q.applied)) if
1951 not q.pushable(i)[0]]
1984 not q.pushable(i)[0]]
1952 q.set_active(args)
1985 q.set_active(args)
1953 q.save_dirty()
1986 q.save_dirty()
1954 if not args:
1987 if not args:
1955 ui.status(_('guards deactivated\n'))
1988 ui.status(_('guards deactivated\n'))
1956 if not opts['pop'] and not opts['reapply']:
1989 if not opts['pop'] and not opts['reapply']:
1957 unapplied = q.unapplied(repo)
1990 unapplied = q.unapplied(repo)
1958 guarded = [i for i in xrange(len(q.applied))
1991 guarded = [i for i in xrange(len(q.applied))
1959 if not q.pushable(i)[0]]
1992 if not q.pushable(i)[0]]
1960 if len(unapplied) != len(old_unapplied):
1993 if len(unapplied) != len(old_unapplied):
1961 ui.status(_('number of unguarded, unapplied patches has '
1994 ui.status(_('number of unguarded, unapplied patches has '
1962 'changed from %d to %d\n') %
1995 'changed from %d to %d\n') %
1963 (len(old_unapplied), len(unapplied)))
1996 (len(old_unapplied), len(unapplied)))
1964 if len(guarded) != len(old_guarded):
1997 if len(guarded) != len(old_guarded):
1965 ui.status(_('number of guarded, applied patches has changed '
1998 ui.status(_('number of guarded, applied patches has changed '
1966 'from %d to %d\n') %
1999 'from %d to %d\n') %
1967 (len(old_guarded), len(guarded)))
2000 (len(old_guarded), len(guarded)))
1968 elif opts['series']:
2001 elif opts['series']:
1969 guards = {}
2002 guards = {}
1970 noguards = 0
2003 noguards = 0
1971 for gs in q.series_guards:
2004 for gs in q.series_guards:
1972 if not gs:
2005 if not gs:
1973 noguards += 1
2006 noguards += 1
1974 for g in gs:
2007 for g in gs:
1975 guards.setdefault(g, 0)
2008 guards.setdefault(g, 0)
1976 guards[g] += 1
2009 guards[g] += 1
1977 if ui.verbose:
2010 if ui.verbose:
1978 guards['NONE'] = noguards
2011 guards['NONE'] = noguards
1979 guards = guards.items()
2012 guards = guards.items()
1980 guards.sort(lambda a, b: cmp(a[0][1:], b[0][1:]))
2013 guards.sort(lambda a, b: cmp(a[0][1:], b[0][1:]))
1981 if guards:
2014 if guards:
1982 ui.note(_('guards in series file:\n'))
2015 ui.note(_('guards in series file:\n'))
1983 for guard, count in guards:
2016 for guard, count in guards:
1984 ui.note('%2d ' % count)
2017 ui.note('%2d ' % count)
1985 ui.write(guard, '\n')
2018 ui.write(guard, '\n')
1986 else:
2019 else:
1987 ui.note(_('no guards in series file\n'))
2020 ui.note(_('no guards in series file\n'))
1988 else:
2021 else:
1989 if guards:
2022 if guards:
1990 ui.note(_('active guards:\n'))
2023 ui.note(_('active guards:\n'))
1991 for g in guards:
2024 for g in guards:
1992 ui.write(g, '\n')
2025 ui.write(g, '\n')
1993 else:
2026 else:
1994 ui.write(_('no active guards\n'))
2027 ui.write(_('no active guards\n'))
1995 reapply = opts['reapply'] and q.applied and q.appliedname(-1)
2028 reapply = opts['reapply'] and q.applied and q.appliedname(-1)
1996 popped = False
2029 popped = False
1997 if opts['pop'] or opts['reapply']:
2030 if opts['pop'] or opts['reapply']:
1998 for i in xrange(len(q.applied)):
2031 for i in xrange(len(q.applied)):
1999 pushable, reason = q.pushable(i)
2032 pushable, reason = q.pushable(i)
2000 if not pushable:
2033 if not pushable:
2001 ui.status(_('popping guarded patches\n'))
2034 ui.status(_('popping guarded patches\n'))
2002 popped = True
2035 popped = True
2003 if i == 0:
2036 if i == 0:
2004 q.pop(repo, all=True)
2037 q.pop(repo, all=True)
2005 else:
2038 else:
2006 q.pop(repo, i-1)
2039 q.pop(repo, i-1)
2007 break
2040 break
2008 if popped:
2041 if popped:
2009 try:
2042 try:
2010 if reapply:
2043 if reapply:
2011 ui.status(_('reapplying unguarded patches\n'))
2044 ui.status(_('reapplying unguarded patches\n'))
2012 q.push(repo, reapply)
2045 q.push(repo, reapply)
2013 finally:
2046 finally:
2014 q.save_dirty()
2047 q.save_dirty()
2015
2048
2016 def reposetup(ui, repo):
2049 def reposetup(ui, repo):
2017 class mqrepo(repo.__class__):
2050 class mqrepo(repo.__class__):
2018 def abort_if_wdir_patched(self, errmsg, force=False):
2051 def abort_if_wdir_patched(self, errmsg, force=False):
2019 if self.mq.applied and not force:
2052 if self.mq.applied and not force:
2020 parent = revlog.hex(self.dirstate.parents()[0])
2053 parent = revlog.hex(self.dirstate.parents()[0])
2021 if parent in [s.rev for s in self.mq.applied]:
2054 if parent in [s.rev for s in self.mq.applied]:
2022 raise util.Abort(errmsg)
2055 raise util.Abort(errmsg)
2023
2056
2024 def commit(self, *args, **opts):
2057 def commit(self, *args, **opts):
2025 if len(args) >= 6:
2058 if len(args) >= 6:
2026 force = args[5]
2059 force = args[5]
2027 else:
2060 else:
2028 force = opts.get('force')
2061 force = opts.get('force')
2029 self.abort_if_wdir_patched(
2062 self.abort_if_wdir_patched(
2030 _('cannot commit over an applied mq patch'),
2063 _('cannot commit over an applied mq patch'),
2031 force)
2064 force)
2032
2065
2033 return super(mqrepo, self).commit(*args, **opts)
2066 return super(mqrepo, self).commit(*args, **opts)
2034
2067
2035 def push(self, remote, force=False, revs=None):
2068 def push(self, remote, force=False, revs=None):
2036 if self.mq.applied and not force:
2069 if self.mq.applied and not force:
2037 raise util.Abort(_('source has mq patches applied'))
2070 raise util.Abort(_('source has mq patches applied'))
2038 return super(mqrepo, self).push(remote, force, revs)
2071 return super(mqrepo, self).push(remote, force, revs)
2039
2072
2040 def tags(self):
2073 def tags(self):
2041 if self.tagscache:
2074 if self.tagscache:
2042 return self.tagscache
2075 return self.tagscache
2043
2076
2044 tagscache = super(mqrepo, self).tags()
2077 tagscache = super(mqrepo, self).tags()
2045
2078
2046 q = self.mq
2079 q = self.mq
2047 if not q.applied:
2080 if not q.applied:
2048 return tagscache
2081 return tagscache
2049
2082
2050 mqtags = [(patch.rev, patch.name) for patch in q.applied]
2083 mqtags = [(patch.rev, patch.name) for patch in q.applied]
2051 mqtags.append((mqtags[-1][0], 'qtip'))
2084 mqtags.append((mqtags[-1][0], 'qtip'))
2052 mqtags.append((mqtags[0][0], 'qbase'))
2085 mqtags.append((mqtags[0][0], 'qbase'))
2053 for patch in mqtags:
2086 for patch in mqtags:
2054 if patch[1] in tagscache:
2087 if patch[1] in tagscache:
2055 self.ui.warn('Tag %s overrides mq patch of the same name\n' % patch[1])
2088 self.ui.warn('Tag %s overrides mq patch of the same name\n' % patch[1])
2056 else:
2089 else:
2057 tagscache[patch[1]] = revlog.bin(patch[0])
2090 tagscache[patch[1]] = revlog.bin(patch[0])
2058
2091
2059 return tagscache
2092 return tagscache
2060
2093
2061 def _branchtags(self):
2094 def _branchtags(self):
2062 q = self.mq
2095 q = self.mq
2063 if not q.applied:
2096 if not q.applied:
2064 return super(mqrepo, self)._branchtags()
2097 return super(mqrepo, self)._branchtags()
2065
2098
2066 self.branchcache = {} # avoid recursion in changectx
2099 self.branchcache = {} # avoid recursion in changectx
2067 cl = self.changelog
2100 cl = self.changelog
2068 partial, last, lrev = self._readbranchcache()
2101 partial, last, lrev = self._readbranchcache()
2069
2102
2070 qbase = cl.rev(revlog.bin(q.applied[0].rev))
2103 qbase = cl.rev(revlog.bin(q.applied[0].rev))
2071 start = lrev + 1
2104 start = lrev + 1
2072 if start < qbase:
2105 if start < qbase:
2073 # update the cache (excluding the patches) and save it
2106 # update the cache (excluding the patches) and save it
2074 self._updatebranchcache(partial, lrev+1, qbase)
2107 self._updatebranchcache(partial, lrev+1, qbase)
2075 self._writebranchcache(partial, cl.node(qbase-1), qbase-1)
2108 self._writebranchcache(partial, cl.node(qbase-1), qbase-1)
2076 start = qbase
2109 start = qbase
2077 # if start = qbase, the cache is as updated as it should be.
2110 # if start = qbase, the cache is as updated as it should be.
2078 # if start > qbase, the cache includes (part of) the patches.
2111 # if start > qbase, the cache includes (part of) the patches.
2079 # we might as well use it, but we won't save it.
2112 # we might as well use it, but we won't save it.
2080
2113
2081 # update the cache up to the tip
2114 # update the cache up to the tip
2082 self._updatebranchcache(partial, start, cl.count())
2115 self._updatebranchcache(partial, start, cl.count())
2083
2116
2084 return partial
2117 return partial
2085
2118
2086 if repo.local():
2119 if repo.local():
2087 repo.__class__ = mqrepo
2120 repo.__class__ = mqrepo
2088 repo.mq = queue(ui, repo.join(""))
2121 repo.mq = queue(ui, repo.join(""))
2089
2122
2090 seriesopts = [('s', 'summary', None, _('print first line of patch header'))]
2123 seriesopts = [('s', 'summary', None, _('print first line of patch header'))]
2091
2124
2092 cmdtable = {
2125 cmdtable = {
2093 "qapplied": (applied, [] + seriesopts, 'hg qapplied [-s] [PATCH]'),
2126 "qapplied": (applied, [] + seriesopts, 'hg qapplied [-s] [PATCH]'),
2094 "qclone": (clone,
2127 "qclone": (clone,
2095 [('', 'pull', None, _('use pull protocol to copy metadata')),
2128 [('', 'pull', None, _('use pull protocol to copy metadata')),
2096 ('U', 'noupdate', None, _('do not update the new working directories')),
2129 ('U', 'noupdate', None, _('do not update the new working directories')),
2097 ('', 'uncompressed', None,
2130 ('', 'uncompressed', None,
2098 _('use uncompressed transfer (fast over LAN)')),
2131 _('use uncompressed transfer (fast over LAN)')),
2099 ('e', 'ssh', '', _('specify ssh command to use')),
2132 ('e', 'ssh', '', _('specify ssh command to use')),
2100 ('p', 'patches', '', _('location of source patch repo')),
2133 ('p', 'patches', '', _('location of source patch repo')),
2101 ('', 'remotecmd', '',
2134 ('', 'remotecmd', '',
2102 _('specify hg command to run on the remote side'))],
2135 _('specify hg command to run on the remote side'))],
2103 'hg qclone [OPTION]... SOURCE [DEST]'),
2136 'hg qclone [OPTION]... SOURCE [DEST]'),
2104 "qcommit|qci":
2137 "qcommit|qci":
2105 (commit,
2138 (commit,
2106 commands.table["^commit|ci"][1],
2139 commands.table["^commit|ci"][1],
2107 'hg qcommit [OPTION]... [FILE]...'),
2140 'hg qcommit [OPTION]... [FILE]...'),
2108 "^qdiff": (diff,
2141 "^qdiff": (diff,
2109 [('g', 'git', None, _('use git extended diff format')),
2142 [('g', 'git', None, _('use git extended diff format')),
2110 ('I', 'include', [], _('include names matching the given patterns')),
2143 ('I', 'include', [], _('include names matching the given patterns')),
2111 ('X', 'exclude', [], _('exclude names matching the given patterns'))],
2144 ('X', 'exclude', [], _('exclude names matching the given patterns'))],
2112 'hg qdiff [-I] [-X] [FILE]...'),
2145 'hg qdiff [-I] [-X] [FILE]...'),
2113 "qdelete|qremove|qrm":
2146 "qdelete|qremove|qrm":
2114 (delete,
2147 (delete,
2115 [('k', 'keep', None, _('keep patch file')),
2148 [('k', 'keep', None, _('keep patch file')),
2116 ('r', 'rev', [], _('stop managing a revision'))],
2149 ('r', 'rev', [], _('stop managing a revision'))],
2117 'hg qdelete [-k] [-r REV]... PATCH...'),
2150 'hg qdelete [-k] [-r REV]... PATCH...'),
2118 'qfold':
2151 'qfold':
2119 (fold,
2152 (fold,
2120 [('e', 'edit', None, _('edit patch header')),
2153 [('e', 'edit', None, _('edit patch header')),
2121 ('k', 'keep', None, _('keep folded patch files'))
2154 ('k', 'keep', None, _('keep folded patch files'))
2122 ] + commands.commitopts,
2155 ] + commands.commitopts,
2123 'hg qfold [-e] [-m <text>] [-l <file] PATCH...'),
2156 'hg qfold [-e] [-m <text>] [-l <file] PATCH...'),
2124 'qguard': (guard, [('l', 'list', None, _('list all patches and guards')),
2157 'qguard': (guard, [('l', 'list', None, _('list all patches and guards')),
2125 ('n', 'none', None, _('drop all guards'))],
2158 ('n', 'none', None, _('drop all guards'))],
2126 'hg qguard [PATCH] [+GUARD]... [-GUARD]...'),
2159 'hg qguard [PATCH] [+GUARD]... [-GUARD]...'),
2127 'qheader': (header, [],
2160 'qheader': (header, [],
2128 _('hg qheader [PATCH]')),
2161 _('hg qheader [PATCH]')),
2129 "^qimport":
2162 "^qimport":
2130 (qimport,
2163 (qimport,
2131 [('e', 'existing', None, 'import file in patch dir'),
2164 [('e', 'existing', None, 'import file in patch dir'),
2132 ('n', 'name', '', 'patch file name'),
2165 ('n', 'name', '', 'patch file name'),
2133 ('f', 'force', None, 'overwrite existing files'),
2166 ('f', 'force', None, 'overwrite existing files'),
2134 ('r', 'rev', [], 'place existing revisions under mq control'),
2167 ('r', 'rev', [], 'place existing revisions under mq control'),
2135 ('g', 'git', None, _('use git extended diff format'))],
2168 ('g', 'git', None, _('use git extended diff format'))],
2136 'hg qimport [-e] [-n NAME] [-f] [-g] [-r REV]... FILE...'),
2169 'hg qimport [-e] [-n NAME] [-f] [-g] [-r REV]... FILE...'),
2137 "^qinit":
2170 "^qinit":
2138 (init,
2171 (init,
2139 [('c', 'create-repo', None, 'create queue repository')],
2172 [('c', 'create-repo', None, 'create queue repository')],
2140 'hg qinit [-c]'),
2173 'hg qinit [-c]'),
2141 "qnew":
2174 "qnew":
2142 (new,
2175 (new,
2143 [('e', 'edit', None, _('edit commit message')),
2176 [('e', 'edit', None, _('edit commit message')),
2144 ('f', 'force', None, _('import uncommitted changes into patch'))
2177 ('f', 'force', None, _('import uncommitted changes into patch'))
2145 ] + commands.commitopts,
2178 ] + commands.commitopts,
2146 'hg qnew [-e] [-m TEXT] [-l FILE] [-f] PATCH'),
2179 'hg qnew [-e] [-m TEXT] [-l FILE] [-f] PATCH'),
2147 "qnext": (next, [] + seriesopts, 'hg qnext [-s]'),
2180 "qnext": (next, [] + seriesopts, 'hg qnext [-s]'),
2148 "qprev": (prev, [] + seriesopts, 'hg qprev [-s]'),
2181 "qprev": (prev, [] + seriesopts, 'hg qprev [-s]'),
2149 "^qpop":
2182 "^qpop":
2150 (pop,
2183 (pop,
2151 [('a', 'all', None, 'pop all patches'),
2184 [('a', 'all', None, 'pop all patches'),
2152 ('n', 'name', '', 'queue name to pop'),
2185 ('n', 'name', '', 'queue name to pop'),
2153 ('f', 'force', None, 'forget any local changes')],
2186 ('f', 'force', None, 'forget any local changes')],
2154 'hg qpop [-a] [-n NAME] [-f] [PATCH | INDEX]'),
2187 'hg qpop [-a] [-n NAME] [-f] [PATCH | INDEX]'),
2155 "^qpush":
2188 "^qpush":
2156 (push,
2189 (push,
2157 [('f', 'force', None, 'apply if the patch has rejects'),
2190 [('f', 'force', None, 'apply if the patch has rejects'),
2158 ('l', 'list', None, 'list patch name in commit text'),
2191 ('l', 'list', None, 'list patch name in commit text'),
2159 ('a', 'all', None, 'apply all patches'),
2192 ('a', 'all', None, 'apply all patches'),
2160 ('m', 'merge', None, 'merge from another queue'),
2193 ('m', 'merge', None, 'merge from another queue'),
2161 ('n', 'name', '', 'merge queue name')],
2194 ('n', 'name', '', 'merge queue name')],
2162 'hg qpush [-f] [-l] [-a] [-m] [-n NAME] [PATCH | INDEX]'),
2195 'hg qpush [-f] [-l] [-a] [-m] [-n NAME] [PATCH | INDEX]'),
2163 "^qrefresh":
2196 "^qrefresh":
2164 (refresh,
2197 (refresh,
2165 [('e', 'edit', None, _('edit commit message')),
2198 [('e', 'edit', None, _('edit commit message')),
2166 ('g', 'git', None, _('use git extended diff format')),
2199 ('g', 'git', None, _('use git extended diff format')),
2167 ('s', 'short', None, 'refresh only files already in the patch'),
2200 ('s', 'short', None, 'refresh only files already in the patch'),
2168 ('I', 'include', [], _('include names matching the given patterns')),
2201 ('I', 'include', [], _('include names matching the given patterns')),
2169 ('X', 'exclude', [], _('exclude names matching the given patterns'))
2202 ('X', 'exclude', [], _('exclude names matching the given patterns'))
2170 ] + commands.commitopts,
2203 ] + commands.commitopts,
2171 'hg qrefresh [-I] [-X] [-e] [-m TEXT] [-l FILE] [-s] [FILE]...'),
2204 'hg qrefresh [-I] [-X] [-e] [-m TEXT] [-l FILE] [-s] [FILE]...'),
2172 'qrename|qmv':
2205 'qrename|qmv':
2173 (rename, [], 'hg qrename PATCH1 [PATCH2]'),
2206 (rename, [], 'hg qrename PATCH1 [PATCH2]'),
2174 "qrestore":
2207 "qrestore":
2175 (restore,
2208 (restore,
2176 [('d', 'delete', None, 'delete save entry'),
2209 [('d', 'delete', None, 'delete save entry'),
2177 ('u', 'update', None, 'update queue working dir')],
2210 ('u', 'update', None, 'update queue working dir')],
2178 'hg qrestore [-d] [-u] REV'),
2211 'hg qrestore [-d] [-u] REV'),
2179 "qsave":
2212 "qsave":
2180 (save,
2213 (save,
2181 [('c', 'copy', None, 'copy patch directory'),
2214 [('c', 'copy', None, 'copy patch directory'),
2182 ('n', 'name', '', 'copy directory name'),
2215 ('n', 'name', '', 'copy directory name'),
2183 ('e', 'empty', None, 'clear queue status file'),
2216 ('e', 'empty', None, 'clear queue status file'),
2184 ('f', 'force', None, 'force copy')] + commands.commitopts,
2217 ('f', 'force', None, 'force copy')] + commands.commitopts,
2185 'hg qsave [-m TEXT] [-l FILE] [-c] [-n NAME] [-e] [-f]'),
2218 'hg qsave [-m TEXT] [-l FILE] [-c] [-n NAME] [-e] [-f]'),
2186 "qselect": (select,
2219 "qselect": (select,
2187 [('n', 'none', None, _('disable all guards')),
2220 [('n', 'none', None, _('disable all guards')),
2188 ('s', 'series', None, _('list all guards in series file')),
2221 ('s', 'series', None, _('list all guards in series file')),
2189 ('', 'pop', None,
2222 ('', 'pop', None,
2190 _('pop to before first guarded applied patch')),
2223 _('pop to before first guarded applied patch')),
2191 ('', 'reapply', None, _('pop, then reapply patches'))],
2224 ('', 'reapply', None, _('pop, then reapply patches'))],
2192 'hg qselect [OPTION]... [GUARD]...'),
2225 'hg qselect [OPTION]... [GUARD]...'),
2193 "qseries":
2226 "qseries":
2194 (series,
2227 (series,
2195 [('m', 'missing', None, 'print patches not in series')] + seriesopts,
2228 [('m', 'missing', None, 'print patches not in series')] + seriesopts,
2196 'hg qseries [-ms]'),
2229 'hg qseries [-ms]'),
2197 "^strip":
2230 "^strip":
2198 (strip,
2231 (strip,
2199 [('f', 'force', None, 'force multi-head removal'),
2232 [('f', 'force', None, 'force multi-head removal'),
2200 ('b', 'backup', None, 'bundle unrelated changesets'),
2233 ('b', 'backup', None, 'bundle unrelated changesets'),
2201 ('n', 'nobackup', None, 'no backups')],
2234 ('n', 'nobackup', None, 'no backups')],
2202 'hg strip [-f] [-b] [-n] REV'),
2235 'hg strip [-f] [-b] [-n] REV'),
2203 "qtop": (top, [] + seriesopts, 'hg qtop [-s]'),
2236 "qtop": (top, [] + seriesopts, 'hg qtop [-s]'),
2204 "qunapplied": (unapplied, [] + seriesopts, 'hg qunapplied [-s] [PATCH]'),
2237 "qunapplied": (unapplied, [] + seriesopts, 'hg qunapplied [-s] [PATCH]'),
2205 }
2238 }
General Comments 0
You need to be logged in to leave comments. Login now