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