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