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