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