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