##// END OF EJS Templates
mq: smarter handling of plain headers...
Mads Kiilerich -
r23442:a5c94ea3 default
parent child Browse files
Show More
@@ -1,3531 +1,3568 b''
1 # mq.py - patch queues for mercurial
1 # mq.py - patch queues for mercurial
2 #
2 #
3 # Copyright 2005, 2006 Chris Mason <mason@suse.com>
3 # Copyright 2005, 2006 Chris Mason <mason@suse.com>
4 #
4 #
5 # This software may be used and distributed according to the terms of the
5 # This software may be used and distributed according to the terms of the
6 # GNU General Public License version 2 or any later version.
6 # GNU General Public License version 2 or any later version.
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 create new patch qnew
19 create new patch qnew
20 import existing patch qimport
20 import existing patch qimport
21
21
22 print patch series qseries
22 print patch series qseries
23 print applied patches qapplied
23 print applied patches qapplied
24
24
25 add known patch to applied stack qpush
25 add known patch to applied stack qpush
26 remove patch from applied stack qpop
26 remove patch from applied stack qpop
27 refresh contents of top applied patch qrefresh
27 refresh contents of top applied patch qrefresh
28
28
29 By default, mq will automatically use git patches when required to
29 By default, mq will automatically use git patches when required to
30 avoid losing file mode changes, copy records, binary files or empty
30 avoid losing file mode changes, copy records, binary files or empty
31 files creations or deletions. This behaviour can be configured with::
31 files creations or deletions. This behaviour can be configured with::
32
32
33 [mq]
33 [mq]
34 git = auto/keep/yes/no
34 git = auto/keep/yes/no
35
35
36 If set to 'keep', mq will obey the [diff] section configuration while
36 If set to 'keep', mq will obey the [diff] section configuration while
37 preserving existing git patches upon qrefresh. If set to 'yes' or
37 preserving existing git patches upon qrefresh. If set to 'yes' or
38 'no', mq will override the [diff] section and always generate git or
38 'no', mq will override the [diff] section and always generate git or
39 regular patches, possibly losing data in the second case.
39 regular patches, possibly losing data in the second case.
40
40
41 It may be desirable for mq changesets to be kept in the secret phase (see
41 It may be desirable for mq changesets to be kept in the secret phase (see
42 :hg:`help phases`), which can be enabled with the following setting::
42 :hg:`help phases`), which can be enabled with the following setting::
43
43
44 [mq]
44 [mq]
45 secret = True
45 secret = True
46
46
47 You will by default be managing a patch queue named "patches". You can
47 You will by default be managing a patch queue named "patches". You can
48 create other, independent patch queues with the :hg:`qqueue` command.
48 create other, independent patch queues with the :hg:`qqueue` command.
49
49
50 If the working directory contains uncommitted files, qpush, qpop and
50 If the working directory contains uncommitted files, qpush, qpop and
51 qgoto abort immediately. If -f/--force is used, the changes are
51 qgoto abort immediately. If -f/--force is used, the changes are
52 discarded. Setting::
52 discarded. Setting::
53
53
54 [mq]
54 [mq]
55 keepchanges = True
55 keepchanges = True
56
56
57 make them behave as if --keep-changes were passed, and non-conflicting
57 make them behave as if --keep-changes were passed, and non-conflicting
58 local changes will be tolerated and preserved. If incompatible options
58 local changes will be tolerated and preserved. If incompatible options
59 such as -f/--force or --exact are passed, this setting is ignored.
59 such as -f/--force or --exact are passed, this setting is ignored.
60
60
61 This extension used to provide a strip command. This command now lives
61 This extension used to provide a strip command. This command now lives
62 in the strip extension.
62 in the strip extension.
63 '''
63 '''
64
64
65 from mercurial.i18n import _
65 from mercurial.i18n import _
66 from mercurial.node import bin, hex, short, nullid, nullrev
66 from mercurial.node import bin, hex, short, nullid, nullrev
67 from mercurial.lock import release
67 from mercurial.lock import release
68 from mercurial import commands, cmdutil, hg, scmutil, util, revset
68 from mercurial import commands, cmdutil, hg, scmutil, util, revset
69 from mercurial import extensions, error, phases
69 from mercurial import extensions, error, phases
70 from mercurial import patch as patchmod
70 from mercurial import patch as patchmod
71 from mercurial import localrepo
71 from mercurial import localrepo
72 from mercurial import subrepo
72 from mercurial import subrepo
73 import os, re, errno, shutil
73 import os, re, errno, shutil
74
74
75 seriesopts = [('s', 'summary', None, _('print first line of patch header'))]
75 seriesopts = [('s', 'summary', None, _('print first line of patch header'))]
76
76
77 cmdtable = {}
77 cmdtable = {}
78 command = cmdutil.command(cmdtable)
78 command = cmdutil.command(cmdtable)
79 testedwith = 'internal'
79 testedwith = 'internal'
80
80
81 # force load strip extension formerly included in mq and import some utility
81 # force load strip extension formerly included in mq and import some utility
82 try:
82 try:
83 stripext = extensions.find('strip')
83 stripext = extensions.find('strip')
84 except KeyError:
84 except KeyError:
85 # note: load is lazy so we could avoid the try-except,
85 # note: load is lazy so we could avoid the try-except,
86 # but I (marmoute) prefer this explicit code.
86 # but I (marmoute) prefer this explicit code.
87 class dummyui(object):
87 class dummyui(object):
88 def debug(self, msg):
88 def debug(self, msg):
89 pass
89 pass
90 stripext = extensions.load(dummyui(), 'strip', '')
90 stripext = extensions.load(dummyui(), 'strip', '')
91
91
92 strip = stripext.strip
92 strip = stripext.strip
93 checksubstate = stripext.checksubstate
93 checksubstate = stripext.checksubstate
94 checklocalchanges = stripext.checklocalchanges
94 checklocalchanges = stripext.checklocalchanges
95
95
96
96
97 # Patch names looks like unix-file names.
97 # Patch names looks like unix-file names.
98 # They must be joinable with queue directory and result in the patch path.
98 # They must be joinable with queue directory and result in the patch path.
99 normname = util.normpath
99 normname = util.normpath
100
100
101 class statusentry(object):
101 class statusentry(object):
102 def __init__(self, node, name):
102 def __init__(self, node, name):
103 self.node, self.name = node, name
103 self.node, self.name = node, name
104 def __repr__(self):
104 def __repr__(self):
105 return hex(self.node) + ':' + self.name
105 return hex(self.node) + ':' + self.name
106
106
107 # The order of the headers in 'hg export' HG patches:
107 # The order of the headers in 'hg export' HG patches:
108 HGHEADERS = [
108 HGHEADERS = [
109 # '# HG changeset patch',
109 # '# HG changeset patch',
110 '# User ',
110 '# User ',
111 '# Date ',
111 '# Date ',
112 '# ',
112 '# ',
113 '# Branch ',
113 '# Branch ',
114 '# Node ID ',
114 '# Node ID ',
115 '# Parent ', # can occur twice for merges - but that is not relevant for mq
115 '# Parent ', # can occur twice for merges - but that is not relevant for mq
116 ]
116 ]
117 # The order of headers in plain 'mail style' patches:
118 PLAINHEADERS = {
119 'from': 0,
120 'date': 1,
121 'subject': 2,
122 }
117
123
118 def inserthgheader(lines, header, value):
124 def inserthgheader(lines, header, value):
119 """Assuming lines contains a HG patch header, add a header line with value.
125 """Assuming lines contains a HG patch header, add a header line with value.
120 >>> try: inserthgheader([], '# Date ', 'z')
126 >>> try: inserthgheader([], '# Date ', 'z')
121 ... except ValueError, inst: print "oops"
127 ... except ValueError, inst: print "oops"
122 oops
128 oops
123 >>> inserthgheader(['# HG changeset patch'], '# Date ', 'z')
129 >>> inserthgheader(['# HG changeset patch'], '# Date ', 'z')
124 ['# HG changeset patch', '# Date z']
130 ['# HG changeset patch', '# Date z']
125 >>> inserthgheader(['# HG changeset patch', ''], '# Date ', 'z')
131 >>> inserthgheader(['# HG changeset patch', ''], '# Date ', 'z')
126 ['# HG changeset patch', '# Date z', '']
132 ['# HG changeset patch', '# Date z', '']
127 >>> inserthgheader(['# HG changeset patch', '# User y'], '# Date ', 'z')
133 >>> inserthgheader(['# HG changeset patch', '# User y'], '# Date ', 'z')
128 ['# HG changeset patch', '# User y', '# Date z']
134 ['# HG changeset patch', '# User y', '# Date z']
129 >>> inserthgheader(['# HG changeset patch', '# Date x', '# User y'],
135 >>> inserthgheader(['# HG changeset patch', '# Date x', '# User y'],
130 ... '# User ', 'z')
136 ... '# User ', 'z')
131 ['# HG changeset patch', '# Date x', '# User z']
137 ['# HG changeset patch', '# Date x', '# User z']
132 >>> inserthgheader(['# HG changeset patch', '# Date y'], '# Date ', 'z')
138 >>> inserthgheader(['# HG changeset patch', '# Date y'], '# Date ', 'z')
133 ['# HG changeset patch', '# Date z']
139 ['# HG changeset patch', '# Date z']
134 >>> inserthgheader(['# HG changeset patch', '', '# Date y'], '# Date ', 'z')
140 >>> inserthgheader(['# HG changeset patch', '', '# Date y'], '# Date ', 'z')
135 ['# HG changeset patch', '# Date z', '', '# Date y']
141 ['# HG changeset patch', '# Date z', '', '# Date y']
136 >>> inserthgheader(['# HG changeset patch', '# Parent y'], '# Date ', 'z')
142 >>> inserthgheader(['# HG changeset patch', '# Parent y'], '# Date ', 'z')
137 ['# HG changeset patch', '# Date z', '# Parent y']
143 ['# HG changeset patch', '# Date z', '# Parent y']
138 """
144 """
139 start = lines.index('# HG changeset patch') + 1
145 start = lines.index('# HG changeset patch') + 1
140 newindex = HGHEADERS.index(header)
146 newindex = HGHEADERS.index(header)
141 bestpos = len(lines)
147 bestpos = len(lines)
142 for i in range(start, len(lines)):
148 for i in range(start, len(lines)):
143 line = lines[i]
149 line = lines[i]
144 if not line.startswith('# '):
150 if not line.startswith('# '):
145 bestpos = min(bestpos, i)
151 bestpos = min(bestpos, i)
146 break
152 break
147 for lineindex, h in enumerate(HGHEADERS):
153 for lineindex, h in enumerate(HGHEADERS):
148 if line.startswith(h):
154 if line.startswith(h):
149 if lineindex == newindex:
155 if lineindex == newindex:
150 lines[i] = header + value
156 lines[i] = header + value
151 return lines
157 return lines
152 if lineindex > newindex:
158 if lineindex > newindex:
153 bestpos = min(bestpos, i)
159 bestpos = min(bestpos, i)
154 break # next line
160 break # next line
155 lines.insert(bestpos, header + value)
161 lines.insert(bestpos, header + value)
156 return lines
162 return lines
157
163
158 def insertplainheader(lines, header, value):
164 def insertplainheader(lines, header, value):
159 if lines and lines[0] and ':' not in lines[0]:
165 """For lines containing a plain patch header, add a header line with value.
160 lines.insert(0, '')
166 >>> insertplainheader([], 'Date', 'z')
161 lines.insert(0, '%s: %s' % (header, value))
167 ['Date: z']
168 >>> insertplainheader([''], 'Date', 'z')
169 ['Date: z', '']
170 >>> insertplainheader(['x'], 'Date', 'z')
171 ['Date: z', '', 'x']
172 >>> insertplainheader(['From: y', 'x'], 'Date', 'z')
173 ['From: y', 'Date: z', '', 'x']
174 >>> insertplainheader([' date : x', ' from : y', ''], 'From', 'z')
175 [' date : x', 'From: z', '']
176 >>> insertplainheader(['', 'Date: y'], 'Date', 'z')
177 ['Date: z', '', 'Date: y']
178 >>> insertplainheader(['foo: bar', 'DATE: z', 'x'], 'From', 'y')
179 ['From: y', 'foo: bar', 'DATE: z', '', 'x']
180 """
181 newprio = PLAINHEADERS[header.lower()]
182 bestpos = len(lines)
183 for i, line in enumerate(lines):
184 if ':' in line:
185 lheader = line.split(':', 1)[0].strip().lower()
186 lprio = PLAINHEADERS.get(lheader, newprio + 1)
187 if lprio == newprio:
188 lines[i] = '%s: %s' % (header, value)
189 return lines
190 if lprio > newprio and i < bestpos:
191 bestpos = i
192 else:
193 if line:
194 lines.insert(i, '')
195 if i < bestpos:
196 bestpos = i
197 break
198 lines.insert(bestpos, '%s: %s' % (header, value))
162 return lines
199 return lines
163
200
164 class patchheader(object):
201 class patchheader(object):
165 def __init__(self, pf, plainmode=False):
202 def __init__(self, pf, plainmode=False):
166 def eatdiff(lines):
203 def eatdiff(lines):
167 while lines:
204 while lines:
168 l = lines[-1]
205 l = lines[-1]
169 if (l.startswith("diff -") or
206 if (l.startswith("diff -") or
170 l.startswith("Index:") or
207 l.startswith("Index:") or
171 l.startswith("===========")):
208 l.startswith("===========")):
172 del lines[-1]
209 del lines[-1]
173 else:
210 else:
174 break
211 break
175 def eatempty(lines):
212 def eatempty(lines):
176 while lines:
213 while lines:
177 if not lines[-1].strip():
214 if not lines[-1].strip():
178 del lines[-1]
215 del lines[-1]
179 else:
216 else:
180 break
217 break
181
218
182 message = []
219 message = []
183 comments = []
220 comments = []
184 user = None
221 user = None
185 date = None
222 date = None
186 parent = None
223 parent = None
187 format = None
224 format = None
188 subject = None
225 subject = None
189 branch = None
226 branch = None
190 nodeid = None
227 nodeid = None
191 diffstart = 0
228 diffstart = 0
192
229
193 for line in file(pf):
230 for line in file(pf):
194 line = line.rstrip()
231 line = line.rstrip()
195 if (line.startswith('diff --git')
232 if (line.startswith('diff --git')
196 or (diffstart and line.startswith('+++ '))):
233 or (diffstart and line.startswith('+++ '))):
197 diffstart = 2
234 diffstart = 2
198 break
235 break
199 diffstart = 0 # reset
236 diffstart = 0 # reset
200 if line.startswith("--- "):
237 if line.startswith("--- "):
201 diffstart = 1
238 diffstart = 1
202 continue
239 continue
203 elif format == "hgpatch":
240 elif format == "hgpatch":
204 # parse values when importing the result of an hg export
241 # parse values when importing the result of an hg export
205 if line.startswith("# User "):
242 if line.startswith("# User "):
206 user = line[7:]
243 user = line[7:]
207 elif line.startswith("# Date "):
244 elif line.startswith("# Date "):
208 date = line[7:]
245 date = line[7:]
209 elif line.startswith("# Parent "):
246 elif line.startswith("# Parent "):
210 parent = line[9:].lstrip() # handle double trailing space
247 parent = line[9:].lstrip() # handle double trailing space
211 elif line.startswith("# Branch "):
248 elif line.startswith("# Branch "):
212 branch = line[9:]
249 branch = line[9:]
213 elif line.startswith("# Node ID "):
250 elif line.startswith("# Node ID "):
214 nodeid = line[10:]
251 nodeid = line[10:]
215 elif not line.startswith("# ") and line:
252 elif not line.startswith("# ") and line:
216 message.append(line)
253 message.append(line)
217 format = None
254 format = None
218 elif line == '# HG changeset patch':
255 elif line == '# HG changeset patch':
219 message = []
256 message = []
220 format = "hgpatch"
257 format = "hgpatch"
221 elif (format != "tagdone" and (line.startswith("Subject: ") or
258 elif (format != "tagdone" and (line.startswith("Subject: ") or
222 line.startswith("subject: "))):
259 line.startswith("subject: "))):
223 subject = line[9:]
260 subject = line[9:]
224 format = "tag"
261 format = "tag"
225 elif (format != "tagdone" and (line.startswith("From: ") or
262 elif (format != "tagdone" and (line.startswith("From: ") or
226 line.startswith("from: "))):
263 line.startswith("from: "))):
227 user = line[6:]
264 user = line[6:]
228 format = "tag"
265 format = "tag"
229 elif (format != "tagdone" and (line.startswith("Date: ") or
266 elif (format != "tagdone" and (line.startswith("Date: ") or
230 line.startswith("date: "))):
267 line.startswith("date: "))):
231 date = line[6:]
268 date = line[6:]
232 format = "tag"
269 format = "tag"
233 elif format == "tag" and line == "":
270 elif format == "tag" and line == "":
234 # when looking for tags (subject: from: etc) they
271 # when looking for tags (subject: from: etc) they
235 # end once you find a blank line in the source
272 # end once you find a blank line in the source
236 format = "tagdone"
273 format = "tagdone"
237 elif message or line:
274 elif message or line:
238 message.append(line)
275 message.append(line)
239 comments.append(line)
276 comments.append(line)
240
277
241 eatdiff(message)
278 eatdiff(message)
242 eatdiff(comments)
279 eatdiff(comments)
243 # Remember the exact starting line of the patch diffs before consuming
280 # Remember the exact starting line of the patch diffs before consuming
244 # empty lines, for external use by TortoiseHg and others
281 # empty lines, for external use by TortoiseHg and others
245 self.diffstartline = len(comments)
282 self.diffstartline = len(comments)
246 eatempty(message)
283 eatempty(message)
247 eatempty(comments)
284 eatempty(comments)
248
285
249 # make sure message isn't empty
286 # make sure message isn't empty
250 if format and format.startswith("tag") and subject:
287 if format and format.startswith("tag") and subject:
251 message.insert(0, subject)
288 message.insert(0, subject)
252
289
253 self.message = message
290 self.message = message
254 self.comments = comments
291 self.comments = comments
255 self.user = user
292 self.user = user
256 self.date = date
293 self.date = date
257 self.parent = parent
294 self.parent = parent
258 # nodeid and branch are for external use by TortoiseHg and others
295 # nodeid and branch are for external use by TortoiseHg and others
259 self.nodeid = nodeid
296 self.nodeid = nodeid
260 self.branch = branch
297 self.branch = branch
261 self.haspatch = diffstart > 1
298 self.haspatch = diffstart > 1
262 self.plainmode = (plainmode or
299 self.plainmode = (plainmode or
263 '# HG changeset patch' not in self.comments and
300 '# HG changeset patch' not in self.comments and
264 util.any(c.startswith('Date: ') or
301 util.any(c.startswith('Date: ') or
265 c.startswith('From: ')
302 c.startswith('From: ')
266 for c in self.comments))
303 for c in self.comments))
267
304
268 def setuser(self, user):
305 def setuser(self, user):
269 if not self.updateheader(['From: ', '# User '], user):
306 if not self.updateheader(['From: ', '# User '], user):
270 try:
307 try:
271 inserthgheader(self.comments, '# User ', user)
308 inserthgheader(self.comments, '# User ', user)
272 except ValueError:
309 except ValueError:
273 if self.plainmode:
310 if self.plainmode:
274 insertplainheader(self.comments, 'From', user)
311 insertplainheader(self.comments, 'From', user)
275 else:
312 else:
276 tmp = ['# HG changeset patch', '# User ' + user]
313 tmp = ['# HG changeset patch', '# User ' + user]
277 self.comments = tmp + self.comments
314 self.comments = tmp + self.comments
278 self.user = user
315 self.user = user
279
316
280 def setdate(self, date):
317 def setdate(self, date):
281 if not self.updateheader(['Date: ', '# Date '], date):
318 if not self.updateheader(['Date: ', '# Date '], date):
282 try:
319 try:
283 inserthgheader(self.comments, '# Date ', date)
320 inserthgheader(self.comments, '# Date ', date)
284 except ValueError:
321 except ValueError:
285 if self.plainmode:
322 if self.plainmode:
286 insertplainheader(self.comments, 'Date', date)
323 insertplainheader(self.comments, 'Date', date)
287 else:
324 else:
288 tmp = ['# HG changeset patch', '# Date ' + date]
325 tmp = ['# HG changeset patch', '# Date ' + date]
289 self.comments = tmp + self.comments
326 self.comments = tmp + self.comments
290 self.date = date
327 self.date = date
291
328
292 def setparent(self, parent):
329 def setparent(self, parent):
293 if not (self.updateheader(['# Parent '], parent) or
330 if not (self.updateheader(['# Parent '], parent) or
294 self.updateheader(['# Parent '], parent)):
331 self.updateheader(['# Parent '], parent)):
295 try:
332 try:
296 inserthgheader(self.comments, '# Parent ', parent)
333 inserthgheader(self.comments, '# Parent ', parent)
297 except ValueError:
334 except ValueError:
298 if not self.plainmode:
335 if not self.plainmode:
299 tmp = ['# HG changeset patch', '# Parent ' + parent]
336 tmp = ['# HG changeset patch', '# Parent ' + parent]
300 self.comments = tmp + self.comments
337 self.comments = tmp + self.comments
301 self.parent = parent
338 self.parent = parent
302
339
303 def setmessage(self, message):
340 def setmessage(self, message):
304 if self.comments:
341 if self.comments:
305 self._delmsg()
342 self._delmsg()
306 self.message = [message]
343 self.message = [message]
307 if message:
344 if message:
308 if self.plainmode and self.comments and self.comments[-1]:
345 if self.plainmode and self.comments and self.comments[-1]:
309 self.comments.append('')
346 self.comments.append('')
310 self.comments.append(message)
347 self.comments.append(message)
311
348
312 def updateheader(self, prefixes, new):
349 def updateheader(self, prefixes, new):
313 '''Update all references to a field in the patch header.
350 '''Update all references to a field in the patch header.
314 Return whether the field is present.'''
351 Return whether the field is present.'''
315 res = False
352 res = False
316 for prefix in prefixes:
353 for prefix in prefixes:
317 for i in xrange(len(self.comments)):
354 for i in xrange(len(self.comments)):
318 if self.comments[i].startswith(prefix):
355 if self.comments[i].startswith(prefix):
319 self.comments[i] = prefix + new
356 self.comments[i] = prefix + new
320 res = True
357 res = True
321 break
358 break
322 return res
359 return res
323
360
324 def __str__(self):
361 def __str__(self):
325 s = '\n'.join(self.comments).rstrip()
362 s = '\n'.join(self.comments).rstrip()
326 if not s:
363 if not s:
327 return ''
364 return ''
328 return s + '\n\n'
365 return s + '\n\n'
329
366
330 def _delmsg(self):
367 def _delmsg(self):
331 '''Remove existing message, keeping the rest of the comments fields.
368 '''Remove existing message, keeping the rest of the comments fields.
332 If comments contains 'subject: ', message will prepend
369 If comments contains 'subject: ', message will prepend
333 the field and a blank line.'''
370 the field and a blank line.'''
334 if self.message:
371 if self.message:
335 subj = 'subject: ' + self.message[0].lower()
372 subj = 'subject: ' + self.message[0].lower()
336 for i in xrange(len(self.comments)):
373 for i in xrange(len(self.comments)):
337 if subj == self.comments[i].lower():
374 if subj == self.comments[i].lower():
338 del self.comments[i]
375 del self.comments[i]
339 self.message = self.message[2:]
376 self.message = self.message[2:]
340 break
377 break
341 ci = 0
378 ci = 0
342 for mi in self.message:
379 for mi in self.message:
343 while mi != self.comments[ci]:
380 while mi != self.comments[ci]:
344 ci += 1
381 ci += 1
345 del self.comments[ci]
382 del self.comments[ci]
346
383
347 def newcommit(repo, phase, *args, **kwargs):
384 def newcommit(repo, phase, *args, **kwargs):
348 """helper dedicated to ensure a commit respect mq.secret setting
385 """helper dedicated to ensure a commit respect mq.secret setting
349
386
350 It should be used instead of repo.commit inside the mq source for operation
387 It should be used instead of repo.commit inside the mq source for operation
351 creating new changeset.
388 creating new changeset.
352 """
389 """
353 repo = repo.unfiltered()
390 repo = repo.unfiltered()
354 if phase is None:
391 if phase is None:
355 if repo.ui.configbool('mq', 'secret', False):
392 if repo.ui.configbool('mq', 'secret', False):
356 phase = phases.secret
393 phase = phases.secret
357 if phase is not None:
394 if phase is not None:
358 backup = repo.ui.backupconfig('phases', 'new-commit')
395 backup = repo.ui.backupconfig('phases', 'new-commit')
359 try:
396 try:
360 if phase is not None:
397 if phase is not None:
361 repo.ui.setconfig('phases', 'new-commit', phase, 'mq')
398 repo.ui.setconfig('phases', 'new-commit', phase, 'mq')
362 return repo.commit(*args, **kwargs)
399 return repo.commit(*args, **kwargs)
363 finally:
400 finally:
364 if phase is not None:
401 if phase is not None:
365 repo.ui.restoreconfig(backup)
402 repo.ui.restoreconfig(backup)
366
403
367 class AbortNoCleanup(error.Abort):
404 class AbortNoCleanup(error.Abort):
368 pass
405 pass
369
406
370 class queue(object):
407 class queue(object):
371 def __init__(self, ui, baseui, path, patchdir=None):
408 def __init__(self, ui, baseui, path, patchdir=None):
372 self.basepath = path
409 self.basepath = path
373 try:
410 try:
374 fh = open(os.path.join(path, 'patches.queue'))
411 fh = open(os.path.join(path, 'patches.queue'))
375 cur = fh.read().rstrip()
412 cur = fh.read().rstrip()
376 fh.close()
413 fh.close()
377 if not cur:
414 if not cur:
378 curpath = os.path.join(path, 'patches')
415 curpath = os.path.join(path, 'patches')
379 else:
416 else:
380 curpath = os.path.join(path, 'patches-' + cur)
417 curpath = os.path.join(path, 'patches-' + cur)
381 except IOError:
418 except IOError:
382 curpath = os.path.join(path, 'patches')
419 curpath = os.path.join(path, 'patches')
383 self.path = patchdir or curpath
420 self.path = patchdir or curpath
384 self.opener = scmutil.opener(self.path)
421 self.opener = scmutil.opener(self.path)
385 self.ui = ui
422 self.ui = ui
386 self.baseui = baseui
423 self.baseui = baseui
387 self.applieddirty = False
424 self.applieddirty = False
388 self.seriesdirty = False
425 self.seriesdirty = False
389 self.added = []
426 self.added = []
390 self.seriespath = "series"
427 self.seriespath = "series"
391 self.statuspath = "status"
428 self.statuspath = "status"
392 self.guardspath = "guards"
429 self.guardspath = "guards"
393 self.activeguards = None
430 self.activeguards = None
394 self.guardsdirty = False
431 self.guardsdirty = False
395 # Handle mq.git as a bool with extended values
432 # Handle mq.git as a bool with extended values
396 try:
433 try:
397 gitmode = ui.configbool('mq', 'git', None)
434 gitmode = ui.configbool('mq', 'git', None)
398 if gitmode is None:
435 if gitmode is None:
399 raise error.ConfigError
436 raise error.ConfigError
400 self.gitmode = gitmode and 'yes' or 'no'
437 self.gitmode = gitmode and 'yes' or 'no'
401 except error.ConfigError:
438 except error.ConfigError:
402 self.gitmode = ui.config('mq', 'git', 'auto').lower()
439 self.gitmode = ui.config('mq', 'git', 'auto').lower()
403 self.plainmode = ui.configbool('mq', 'plain', False)
440 self.plainmode = ui.configbool('mq', 'plain', False)
404 self.checkapplied = True
441 self.checkapplied = True
405
442
406 @util.propertycache
443 @util.propertycache
407 def applied(self):
444 def applied(self):
408 def parselines(lines):
445 def parselines(lines):
409 for l in lines:
446 for l in lines:
410 entry = l.split(':', 1)
447 entry = l.split(':', 1)
411 if len(entry) > 1:
448 if len(entry) > 1:
412 n, name = entry
449 n, name = entry
413 yield statusentry(bin(n), name)
450 yield statusentry(bin(n), name)
414 elif l.strip():
451 elif l.strip():
415 self.ui.warn(_('malformated mq status line: %s\n') % entry)
452 self.ui.warn(_('malformated mq status line: %s\n') % entry)
416 # else we ignore empty lines
453 # else we ignore empty lines
417 try:
454 try:
418 lines = self.opener.read(self.statuspath).splitlines()
455 lines = self.opener.read(self.statuspath).splitlines()
419 return list(parselines(lines))
456 return list(parselines(lines))
420 except IOError, e:
457 except IOError, e:
421 if e.errno == errno.ENOENT:
458 if e.errno == errno.ENOENT:
422 return []
459 return []
423 raise
460 raise
424
461
425 @util.propertycache
462 @util.propertycache
426 def fullseries(self):
463 def fullseries(self):
427 try:
464 try:
428 return self.opener.read(self.seriespath).splitlines()
465 return self.opener.read(self.seriespath).splitlines()
429 except IOError, e:
466 except IOError, e:
430 if e.errno == errno.ENOENT:
467 if e.errno == errno.ENOENT:
431 return []
468 return []
432 raise
469 raise
433
470
434 @util.propertycache
471 @util.propertycache
435 def series(self):
472 def series(self):
436 self.parseseries()
473 self.parseseries()
437 return self.series
474 return self.series
438
475
439 @util.propertycache
476 @util.propertycache
440 def seriesguards(self):
477 def seriesguards(self):
441 self.parseseries()
478 self.parseseries()
442 return self.seriesguards
479 return self.seriesguards
443
480
444 def invalidate(self):
481 def invalidate(self):
445 for a in 'applied fullseries series seriesguards'.split():
482 for a in 'applied fullseries series seriesguards'.split():
446 if a in self.__dict__:
483 if a in self.__dict__:
447 delattr(self, a)
484 delattr(self, a)
448 self.applieddirty = False
485 self.applieddirty = False
449 self.seriesdirty = False
486 self.seriesdirty = False
450 self.guardsdirty = False
487 self.guardsdirty = False
451 self.activeguards = None
488 self.activeguards = None
452
489
453 def diffopts(self, opts={}, patchfn=None):
490 def diffopts(self, opts={}, patchfn=None):
454 diffopts = patchmod.diffopts(self.ui, opts)
491 diffopts = patchmod.diffopts(self.ui, opts)
455 if self.gitmode == 'auto':
492 if self.gitmode == 'auto':
456 diffopts.upgrade = True
493 diffopts.upgrade = True
457 elif self.gitmode == 'keep':
494 elif self.gitmode == 'keep':
458 pass
495 pass
459 elif self.gitmode in ('yes', 'no'):
496 elif self.gitmode in ('yes', 'no'):
460 diffopts.git = self.gitmode == 'yes'
497 diffopts.git = self.gitmode == 'yes'
461 else:
498 else:
462 raise util.Abort(_('mq.git option can be auto/keep/yes/no'
499 raise util.Abort(_('mq.git option can be auto/keep/yes/no'
463 ' got %s') % self.gitmode)
500 ' got %s') % self.gitmode)
464 if patchfn:
501 if patchfn:
465 diffopts = self.patchopts(diffopts, patchfn)
502 diffopts = self.patchopts(diffopts, patchfn)
466 return diffopts
503 return diffopts
467
504
468 def patchopts(self, diffopts, *patches):
505 def patchopts(self, diffopts, *patches):
469 """Return a copy of input diff options with git set to true if
506 """Return a copy of input diff options with git set to true if
470 referenced patch is a git patch and should be preserved as such.
507 referenced patch is a git patch and should be preserved as such.
471 """
508 """
472 diffopts = diffopts.copy()
509 diffopts = diffopts.copy()
473 if not diffopts.git and self.gitmode == 'keep':
510 if not diffopts.git and self.gitmode == 'keep':
474 for patchfn in patches:
511 for patchfn in patches:
475 patchf = self.opener(patchfn, 'r')
512 patchf = self.opener(patchfn, 'r')
476 # if the patch was a git patch, refresh it as a git patch
513 # if the patch was a git patch, refresh it as a git patch
477 for line in patchf:
514 for line in patchf:
478 if line.startswith('diff --git'):
515 if line.startswith('diff --git'):
479 diffopts.git = True
516 diffopts.git = True
480 break
517 break
481 patchf.close()
518 patchf.close()
482 return diffopts
519 return diffopts
483
520
484 def join(self, *p):
521 def join(self, *p):
485 return os.path.join(self.path, *p)
522 return os.path.join(self.path, *p)
486
523
487 def findseries(self, patch):
524 def findseries(self, patch):
488 def matchpatch(l):
525 def matchpatch(l):
489 l = l.split('#', 1)[0]
526 l = l.split('#', 1)[0]
490 return l.strip() == patch
527 return l.strip() == patch
491 for index, l in enumerate(self.fullseries):
528 for index, l in enumerate(self.fullseries):
492 if matchpatch(l):
529 if matchpatch(l):
493 return index
530 return index
494 return None
531 return None
495
532
496 guard_re = re.compile(r'\s?#([-+][^-+# \t\r\n\f][^# \t\r\n\f]*)')
533 guard_re = re.compile(r'\s?#([-+][^-+# \t\r\n\f][^# \t\r\n\f]*)')
497
534
498 def parseseries(self):
535 def parseseries(self):
499 self.series = []
536 self.series = []
500 self.seriesguards = []
537 self.seriesguards = []
501 for l in self.fullseries:
538 for l in self.fullseries:
502 h = l.find('#')
539 h = l.find('#')
503 if h == -1:
540 if h == -1:
504 patch = l
541 patch = l
505 comment = ''
542 comment = ''
506 elif h == 0:
543 elif h == 0:
507 continue
544 continue
508 else:
545 else:
509 patch = l[:h]
546 patch = l[:h]
510 comment = l[h:]
547 comment = l[h:]
511 patch = patch.strip()
548 patch = patch.strip()
512 if patch:
549 if patch:
513 if patch in self.series:
550 if patch in self.series:
514 raise util.Abort(_('%s appears more than once in %s') %
551 raise util.Abort(_('%s appears more than once in %s') %
515 (patch, self.join(self.seriespath)))
552 (patch, self.join(self.seriespath)))
516 self.series.append(patch)
553 self.series.append(patch)
517 self.seriesguards.append(self.guard_re.findall(comment))
554 self.seriesguards.append(self.guard_re.findall(comment))
518
555
519 def checkguard(self, guard):
556 def checkguard(self, guard):
520 if not guard:
557 if not guard:
521 return _('guard cannot be an empty string')
558 return _('guard cannot be an empty string')
522 bad_chars = '# \t\r\n\f'
559 bad_chars = '# \t\r\n\f'
523 first = guard[0]
560 first = guard[0]
524 if first in '-+':
561 if first in '-+':
525 return (_('guard %r starts with invalid character: %r') %
562 return (_('guard %r starts with invalid character: %r') %
526 (guard, first))
563 (guard, first))
527 for c in bad_chars:
564 for c in bad_chars:
528 if c in guard:
565 if c in guard:
529 return _('invalid character in guard %r: %r') % (guard, c)
566 return _('invalid character in guard %r: %r') % (guard, c)
530
567
531 def setactive(self, guards):
568 def setactive(self, guards):
532 for guard in guards:
569 for guard in guards:
533 bad = self.checkguard(guard)
570 bad = self.checkguard(guard)
534 if bad:
571 if bad:
535 raise util.Abort(bad)
572 raise util.Abort(bad)
536 guards = sorted(set(guards))
573 guards = sorted(set(guards))
537 self.ui.debug('active guards: %s\n' % ' '.join(guards))
574 self.ui.debug('active guards: %s\n' % ' '.join(guards))
538 self.activeguards = guards
575 self.activeguards = guards
539 self.guardsdirty = True
576 self.guardsdirty = True
540
577
541 def active(self):
578 def active(self):
542 if self.activeguards is None:
579 if self.activeguards is None:
543 self.activeguards = []
580 self.activeguards = []
544 try:
581 try:
545 guards = self.opener.read(self.guardspath).split()
582 guards = self.opener.read(self.guardspath).split()
546 except IOError, err:
583 except IOError, err:
547 if err.errno != errno.ENOENT:
584 if err.errno != errno.ENOENT:
548 raise
585 raise
549 guards = []
586 guards = []
550 for i, guard in enumerate(guards):
587 for i, guard in enumerate(guards):
551 bad = self.checkguard(guard)
588 bad = self.checkguard(guard)
552 if bad:
589 if bad:
553 self.ui.warn('%s:%d: %s\n' %
590 self.ui.warn('%s:%d: %s\n' %
554 (self.join(self.guardspath), i + 1, bad))
591 (self.join(self.guardspath), i + 1, bad))
555 else:
592 else:
556 self.activeguards.append(guard)
593 self.activeguards.append(guard)
557 return self.activeguards
594 return self.activeguards
558
595
559 def setguards(self, idx, guards):
596 def setguards(self, idx, guards):
560 for g in guards:
597 for g in guards:
561 if len(g) < 2:
598 if len(g) < 2:
562 raise util.Abort(_('guard %r too short') % g)
599 raise util.Abort(_('guard %r too short') % g)
563 if g[0] not in '-+':
600 if g[0] not in '-+':
564 raise util.Abort(_('guard %r starts with invalid char') % g)
601 raise util.Abort(_('guard %r starts with invalid char') % g)
565 bad = self.checkguard(g[1:])
602 bad = self.checkguard(g[1:])
566 if bad:
603 if bad:
567 raise util.Abort(bad)
604 raise util.Abort(bad)
568 drop = self.guard_re.sub('', self.fullseries[idx])
605 drop = self.guard_re.sub('', self.fullseries[idx])
569 self.fullseries[idx] = drop + ''.join([' #' + g for g in guards])
606 self.fullseries[idx] = drop + ''.join([' #' + g for g in guards])
570 self.parseseries()
607 self.parseseries()
571 self.seriesdirty = True
608 self.seriesdirty = True
572
609
573 def pushable(self, idx):
610 def pushable(self, idx):
574 if isinstance(idx, str):
611 if isinstance(idx, str):
575 idx = self.series.index(idx)
612 idx = self.series.index(idx)
576 patchguards = self.seriesguards[idx]
613 patchguards = self.seriesguards[idx]
577 if not patchguards:
614 if not patchguards:
578 return True, None
615 return True, None
579 guards = self.active()
616 guards = self.active()
580 exactneg = [g for g in patchguards if g[0] == '-' and g[1:] in guards]
617 exactneg = [g for g in patchguards if g[0] == '-' and g[1:] in guards]
581 if exactneg:
618 if exactneg:
582 return False, repr(exactneg[0])
619 return False, repr(exactneg[0])
583 pos = [g for g in patchguards if g[0] == '+']
620 pos = [g for g in patchguards if g[0] == '+']
584 exactpos = [g for g in pos if g[1:] in guards]
621 exactpos = [g for g in pos if g[1:] in guards]
585 if pos:
622 if pos:
586 if exactpos:
623 if exactpos:
587 return True, repr(exactpos[0])
624 return True, repr(exactpos[0])
588 return False, ' '.join(map(repr, pos))
625 return False, ' '.join(map(repr, pos))
589 return True, ''
626 return True, ''
590
627
591 def explainpushable(self, idx, all_patches=False):
628 def explainpushable(self, idx, all_patches=False):
592 write = all_patches and self.ui.write or self.ui.warn
629 write = all_patches and self.ui.write or self.ui.warn
593 if all_patches or self.ui.verbose:
630 if all_patches or self.ui.verbose:
594 if isinstance(idx, str):
631 if isinstance(idx, str):
595 idx = self.series.index(idx)
632 idx = self.series.index(idx)
596 pushable, why = self.pushable(idx)
633 pushable, why = self.pushable(idx)
597 if all_patches and pushable:
634 if all_patches and pushable:
598 if why is None:
635 if why is None:
599 write(_('allowing %s - no guards in effect\n') %
636 write(_('allowing %s - no guards in effect\n') %
600 self.series[idx])
637 self.series[idx])
601 else:
638 else:
602 if not why:
639 if not why:
603 write(_('allowing %s - no matching negative guards\n') %
640 write(_('allowing %s - no matching negative guards\n') %
604 self.series[idx])
641 self.series[idx])
605 else:
642 else:
606 write(_('allowing %s - guarded by %s\n') %
643 write(_('allowing %s - guarded by %s\n') %
607 (self.series[idx], why))
644 (self.series[idx], why))
608 if not pushable:
645 if not pushable:
609 if why:
646 if why:
610 write(_('skipping %s - guarded by %s\n') %
647 write(_('skipping %s - guarded by %s\n') %
611 (self.series[idx], why))
648 (self.series[idx], why))
612 else:
649 else:
613 write(_('skipping %s - no matching guards\n') %
650 write(_('skipping %s - no matching guards\n') %
614 self.series[idx])
651 self.series[idx])
615
652
616 def savedirty(self):
653 def savedirty(self):
617 def writelist(items, path):
654 def writelist(items, path):
618 fp = self.opener(path, 'w')
655 fp = self.opener(path, 'w')
619 for i in items:
656 for i in items:
620 fp.write("%s\n" % i)
657 fp.write("%s\n" % i)
621 fp.close()
658 fp.close()
622 if self.applieddirty:
659 if self.applieddirty:
623 writelist(map(str, self.applied), self.statuspath)
660 writelist(map(str, self.applied), self.statuspath)
624 self.applieddirty = False
661 self.applieddirty = False
625 if self.seriesdirty:
662 if self.seriesdirty:
626 writelist(self.fullseries, self.seriespath)
663 writelist(self.fullseries, self.seriespath)
627 self.seriesdirty = False
664 self.seriesdirty = False
628 if self.guardsdirty:
665 if self.guardsdirty:
629 writelist(self.activeguards, self.guardspath)
666 writelist(self.activeguards, self.guardspath)
630 self.guardsdirty = False
667 self.guardsdirty = False
631 if self.added:
668 if self.added:
632 qrepo = self.qrepo()
669 qrepo = self.qrepo()
633 if qrepo:
670 if qrepo:
634 qrepo[None].add(f for f in self.added if f not in qrepo[None])
671 qrepo[None].add(f for f in self.added if f not in qrepo[None])
635 self.added = []
672 self.added = []
636
673
637 def removeundo(self, repo):
674 def removeundo(self, repo):
638 undo = repo.sjoin('undo')
675 undo = repo.sjoin('undo')
639 if not os.path.exists(undo):
676 if not os.path.exists(undo):
640 return
677 return
641 try:
678 try:
642 os.unlink(undo)
679 os.unlink(undo)
643 except OSError, inst:
680 except OSError, inst:
644 self.ui.warn(_('error removing undo: %s\n') % str(inst))
681 self.ui.warn(_('error removing undo: %s\n') % str(inst))
645
682
646 def backup(self, repo, files, copy=False):
683 def backup(self, repo, files, copy=False):
647 # backup local changes in --force case
684 # backup local changes in --force case
648 for f in sorted(files):
685 for f in sorted(files):
649 absf = repo.wjoin(f)
686 absf = repo.wjoin(f)
650 if os.path.lexists(absf):
687 if os.path.lexists(absf):
651 self.ui.note(_('saving current version of %s as %s\n') %
688 self.ui.note(_('saving current version of %s as %s\n') %
652 (f, f + '.orig'))
689 (f, f + '.orig'))
653 if copy:
690 if copy:
654 util.copyfile(absf, absf + '.orig')
691 util.copyfile(absf, absf + '.orig')
655 else:
692 else:
656 util.rename(absf, absf + '.orig')
693 util.rename(absf, absf + '.orig')
657
694
658 def printdiff(self, repo, diffopts, node1, node2=None, files=None,
695 def printdiff(self, repo, diffopts, node1, node2=None, files=None,
659 fp=None, changes=None, opts={}):
696 fp=None, changes=None, opts={}):
660 stat = opts.get('stat')
697 stat = opts.get('stat')
661 m = scmutil.match(repo[node1], files, opts)
698 m = scmutil.match(repo[node1], files, opts)
662 cmdutil.diffordiffstat(self.ui, repo, diffopts, node1, node2, m,
699 cmdutil.diffordiffstat(self.ui, repo, diffopts, node1, node2, m,
663 changes, stat, fp)
700 changes, stat, fp)
664
701
665 def mergeone(self, repo, mergeq, head, patch, rev, diffopts):
702 def mergeone(self, repo, mergeq, head, patch, rev, diffopts):
666 # first try just applying the patch
703 # first try just applying the patch
667 (err, n) = self.apply(repo, [patch], update_status=False,
704 (err, n) = self.apply(repo, [patch], update_status=False,
668 strict=True, merge=rev)
705 strict=True, merge=rev)
669
706
670 if err == 0:
707 if err == 0:
671 return (err, n)
708 return (err, n)
672
709
673 if n is None:
710 if n is None:
674 raise util.Abort(_("apply failed for patch %s") % patch)
711 raise util.Abort(_("apply failed for patch %s") % patch)
675
712
676 self.ui.warn(_("patch didn't work out, merging %s\n") % patch)
713 self.ui.warn(_("patch didn't work out, merging %s\n") % patch)
677
714
678 # apply failed, strip away that rev and merge.
715 # apply failed, strip away that rev and merge.
679 hg.clean(repo, head)
716 hg.clean(repo, head)
680 strip(self.ui, repo, [n], update=False, backup=False)
717 strip(self.ui, repo, [n], update=False, backup=False)
681
718
682 ctx = repo[rev]
719 ctx = repo[rev]
683 ret = hg.merge(repo, rev)
720 ret = hg.merge(repo, rev)
684 if ret:
721 if ret:
685 raise util.Abort(_("update returned %d") % ret)
722 raise util.Abort(_("update returned %d") % ret)
686 n = newcommit(repo, None, ctx.description(), ctx.user(), force=True)
723 n = newcommit(repo, None, ctx.description(), ctx.user(), force=True)
687 if n is None:
724 if n is None:
688 raise util.Abort(_("repo commit failed"))
725 raise util.Abort(_("repo commit failed"))
689 try:
726 try:
690 ph = patchheader(mergeq.join(patch), self.plainmode)
727 ph = patchheader(mergeq.join(patch), self.plainmode)
691 except Exception:
728 except Exception:
692 raise util.Abort(_("unable to read %s") % patch)
729 raise util.Abort(_("unable to read %s") % patch)
693
730
694 diffopts = self.patchopts(diffopts, patch)
731 diffopts = self.patchopts(diffopts, patch)
695 patchf = self.opener(patch, "w")
732 patchf = self.opener(patch, "w")
696 comments = str(ph)
733 comments = str(ph)
697 if comments:
734 if comments:
698 patchf.write(comments)
735 patchf.write(comments)
699 self.printdiff(repo, diffopts, head, n, fp=patchf)
736 self.printdiff(repo, diffopts, head, n, fp=patchf)
700 patchf.close()
737 patchf.close()
701 self.removeundo(repo)
738 self.removeundo(repo)
702 return (0, n)
739 return (0, n)
703
740
704 def qparents(self, repo, rev=None):
741 def qparents(self, repo, rev=None):
705 """return the mq handled parent or p1
742 """return the mq handled parent or p1
706
743
707 In some case where mq get himself in being the parent of a merge the
744 In some case where mq get himself in being the parent of a merge the
708 appropriate parent may be p2.
745 appropriate parent may be p2.
709 (eg: an in progress merge started with mq disabled)
746 (eg: an in progress merge started with mq disabled)
710
747
711 If no parent are managed by mq, p1 is returned.
748 If no parent are managed by mq, p1 is returned.
712 """
749 """
713 if rev is None:
750 if rev is None:
714 (p1, p2) = repo.dirstate.parents()
751 (p1, p2) = repo.dirstate.parents()
715 if p2 == nullid:
752 if p2 == nullid:
716 return p1
753 return p1
717 if not self.applied:
754 if not self.applied:
718 return None
755 return None
719 return self.applied[-1].node
756 return self.applied[-1].node
720 p1, p2 = repo.changelog.parents(rev)
757 p1, p2 = repo.changelog.parents(rev)
721 if p2 != nullid and p2 in [x.node for x in self.applied]:
758 if p2 != nullid and p2 in [x.node for x in self.applied]:
722 return p2
759 return p2
723 return p1
760 return p1
724
761
725 def mergepatch(self, repo, mergeq, series, diffopts):
762 def mergepatch(self, repo, mergeq, series, diffopts):
726 if not self.applied:
763 if not self.applied:
727 # each of the patches merged in will have two parents. This
764 # each of the patches merged in will have two parents. This
728 # can confuse the qrefresh, qdiff, and strip code because it
765 # can confuse the qrefresh, qdiff, and strip code because it
729 # needs to know which parent is actually in the patch queue.
766 # needs to know which parent is actually in the patch queue.
730 # so, we insert a merge marker with only one parent. This way
767 # so, we insert a merge marker with only one parent. This way
731 # the first patch in the queue is never a merge patch
768 # the first patch in the queue is never a merge patch
732 #
769 #
733 pname = ".hg.patches.merge.marker"
770 pname = ".hg.patches.merge.marker"
734 n = newcommit(repo, None, '[mq]: merge marker', force=True)
771 n = newcommit(repo, None, '[mq]: merge marker', force=True)
735 self.removeundo(repo)
772 self.removeundo(repo)
736 self.applied.append(statusentry(n, pname))
773 self.applied.append(statusentry(n, pname))
737 self.applieddirty = True
774 self.applieddirty = True
738
775
739 head = self.qparents(repo)
776 head = self.qparents(repo)
740
777
741 for patch in series:
778 for patch in series:
742 patch = mergeq.lookup(patch, strict=True)
779 patch = mergeq.lookup(patch, strict=True)
743 if not patch:
780 if not patch:
744 self.ui.warn(_("patch %s does not exist\n") % patch)
781 self.ui.warn(_("patch %s does not exist\n") % patch)
745 return (1, None)
782 return (1, None)
746 pushable, reason = self.pushable(patch)
783 pushable, reason = self.pushable(patch)
747 if not pushable:
784 if not pushable:
748 self.explainpushable(patch, all_patches=True)
785 self.explainpushable(patch, all_patches=True)
749 continue
786 continue
750 info = mergeq.isapplied(patch)
787 info = mergeq.isapplied(patch)
751 if not info:
788 if not info:
752 self.ui.warn(_("patch %s is not applied\n") % patch)
789 self.ui.warn(_("patch %s is not applied\n") % patch)
753 return (1, None)
790 return (1, None)
754 rev = info[1]
791 rev = info[1]
755 err, head = self.mergeone(repo, mergeq, head, patch, rev, diffopts)
792 err, head = self.mergeone(repo, mergeq, head, patch, rev, diffopts)
756 if head:
793 if head:
757 self.applied.append(statusentry(head, patch))
794 self.applied.append(statusentry(head, patch))
758 self.applieddirty = True
795 self.applieddirty = True
759 if err:
796 if err:
760 return (err, head)
797 return (err, head)
761 self.savedirty()
798 self.savedirty()
762 return (0, head)
799 return (0, head)
763
800
764 def patch(self, repo, patchfile):
801 def patch(self, repo, patchfile):
765 '''Apply patchfile to the working directory.
802 '''Apply patchfile to the working directory.
766 patchfile: name of patch file'''
803 patchfile: name of patch file'''
767 files = set()
804 files = set()
768 try:
805 try:
769 fuzz = patchmod.patch(self.ui, repo, patchfile, strip=1,
806 fuzz = patchmod.patch(self.ui, repo, patchfile, strip=1,
770 files=files, eolmode=None)
807 files=files, eolmode=None)
771 return (True, list(files), fuzz)
808 return (True, list(files), fuzz)
772 except Exception, inst:
809 except Exception, inst:
773 self.ui.note(str(inst) + '\n')
810 self.ui.note(str(inst) + '\n')
774 if not self.ui.verbose:
811 if not self.ui.verbose:
775 self.ui.warn(_("patch failed, unable to continue (try -v)\n"))
812 self.ui.warn(_("patch failed, unable to continue (try -v)\n"))
776 self.ui.traceback()
813 self.ui.traceback()
777 return (False, list(files), False)
814 return (False, list(files), False)
778
815
779 def apply(self, repo, series, list=False, update_status=True,
816 def apply(self, repo, series, list=False, update_status=True,
780 strict=False, patchdir=None, merge=None, all_files=None,
817 strict=False, patchdir=None, merge=None, all_files=None,
781 tobackup=None, keepchanges=False):
818 tobackup=None, keepchanges=False):
782 wlock = lock = tr = None
819 wlock = lock = tr = None
783 try:
820 try:
784 wlock = repo.wlock()
821 wlock = repo.wlock()
785 lock = repo.lock()
822 lock = repo.lock()
786 tr = repo.transaction("qpush")
823 tr = repo.transaction("qpush")
787 try:
824 try:
788 ret = self._apply(repo, series, list, update_status,
825 ret = self._apply(repo, series, list, update_status,
789 strict, patchdir, merge, all_files=all_files,
826 strict, patchdir, merge, all_files=all_files,
790 tobackup=tobackup, keepchanges=keepchanges)
827 tobackup=tobackup, keepchanges=keepchanges)
791 tr.close()
828 tr.close()
792 self.savedirty()
829 self.savedirty()
793 return ret
830 return ret
794 except AbortNoCleanup:
831 except AbortNoCleanup:
795 tr.close()
832 tr.close()
796 self.savedirty()
833 self.savedirty()
797 return 2, repo.dirstate.p1()
834 return 2, repo.dirstate.p1()
798 except: # re-raises
835 except: # re-raises
799 try:
836 try:
800 tr.abort()
837 tr.abort()
801 finally:
838 finally:
802 repo.invalidate()
839 repo.invalidate()
803 repo.dirstate.invalidate()
840 repo.dirstate.invalidate()
804 self.invalidate()
841 self.invalidate()
805 raise
842 raise
806 finally:
843 finally:
807 release(tr, lock, wlock)
844 release(tr, lock, wlock)
808 self.removeundo(repo)
845 self.removeundo(repo)
809
846
810 def _apply(self, repo, series, list=False, update_status=True,
847 def _apply(self, repo, series, list=False, update_status=True,
811 strict=False, patchdir=None, merge=None, all_files=None,
848 strict=False, patchdir=None, merge=None, all_files=None,
812 tobackup=None, keepchanges=False):
849 tobackup=None, keepchanges=False):
813 """returns (error, hash)
850 """returns (error, hash)
814
851
815 error = 1 for unable to read, 2 for patch failed, 3 for patch
852 error = 1 for unable to read, 2 for patch failed, 3 for patch
816 fuzz. tobackup is None or a set of files to backup before they
853 fuzz. tobackup is None or a set of files to backup before they
817 are modified by a patch.
854 are modified by a patch.
818 """
855 """
819 # TODO unify with commands.py
856 # TODO unify with commands.py
820 if not patchdir:
857 if not patchdir:
821 patchdir = self.path
858 patchdir = self.path
822 err = 0
859 err = 0
823 n = None
860 n = None
824 for patchname in series:
861 for patchname in series:
825 pushable, reason = self.pushable(patchname)
862 pushable, reason = self.pushable(patchname)
826 if not pushable:
863 if not pushable:
827 self.explainpushable(patchname, all_patches=True)
864 self.explainpushable(patchname, all_patches=True)
828 continue
865 continue
829 self.ui.status(_("applying %s\n") % patchname)
866 self.ui.status(_("applying %s\n") % patchname)
830 pf = os.path.join(patchdir, patchname)
867 pf = os.path.join(patchdir, patchname)
831
868
832 try:
869 try:
833 ph = patchheader(self.join(patchname), self.plainmode)
870 ph = patchheader(self.join(patchname), self.plainmode)
834 except IOError:
871 except IOError:
835 self.ui.warn(_("unable to read %s\n") % patchname)
872 self.ui.warn(_("unable to read %s\n") % patchname)
836 err = 1
873 err = 1
837 break
874 break
838
875
839 message = ph.message
876 message = ph.message
840 if not message:
877 if not message:
841 # The commit message should not be translated
878 # The commit message should not be translated
842 message = "imported patch %s\n" % patchname
879 message = "imported patch %s\n" % patchname
843 else:
880 else:
844 if list:
881 if list:
845 # The commit message should not be translated
882 # The commit message should not be translated
846 message.append("\nimported patch %s" % patchname)
883 message.append("\nimported patch %s" % patchname)
847 message = '\n'.join(message)
884 message = '\n'.join(message)
848
885
849 if ph.haspatch:
886 if ph.haspatch:
850 if tobackup:
887 if tobackup:
851 touched = patchmod.changedfiles(self.ui, repo, pf)
888 touched = patchmod.changedfiles(self.ui, repo, pf)
852 touched = set(touched) & tobackup
889 touched = set(touched) & tobackup
853 if touched and keepchanges:
890 if touched and keepchanges:
854 raise AbortNoCleanup(
891 raise AbortNoCleanup(
855 _("local changes found, refresh first"))
892 _("local changes found, refresh first"))
856 self.backup(repo, touched, copy=True)
893 self.backup(repo, touched, copy=True)
857 tobackup = tobackup - touched
894 tobackup = tobackup - touched
858 (patcherr, files, fuzz) = self.patch(repo, pf)
895 (patcherr, files, fuzz) = self.patch(repo, pf)
859 if all_files is not None:
896 if all_files is not None:
860 all_files.update(files)
897 all_files.update(files)
861 patcherr = not patcherr
898 patcherr = not patcherr
862 else:
899 else:
863 self.ui.warn(_("patch %s is empty\n") % patchname)
900 self.ui.warn(_("patch %s is empty\n") % patchname)
864 patcherr, files, fuzz = 0, [], 0
901 patcherr, files, fuzz = 0, [], 0
865
902
866 if merge and files:
903 if merge and files:
867 # Mark as removed/merged and update dirstate parent info
904 # Mark as removed/merged and update dirstate parent info
868 removed = []
905 removed = []
869 merged = []
906 merged = []
870 for f in files:
907 for f in files:
871 if os.path.lexists(repo.wjoin(f)):
908 if os.path.lexists(repo.wjoin(f)):
872 merged.append(f)
909 merged.append(f)
873 else:
910 else:
874 removed.append(f)
911 removed.append(f)
875 repo.dirstate.beginparentchange()
912 repo.dirstate.beginparentchange()
876 for f in removed:
913 for f in removed:
877 repo.dirstate.remove(f)
914 repo.dirstate.remove(f)
878 for f in merged:
915 for f in merged:
879 repo.dirstate.merge(f)
916 repo.dirstate.merge(f)
880 p1, p2 = repo.dirstate.parents()
917 p1, p2 = repo.dirstate.parents()
881 repo.setparents(p1, merge)
918 repo.setparents(p1, merge)
882 repo.dirstate.endparentchange()
919 repo.dirstate.endparentchange()
883
920
884 if all_files and '.hgsubstate' in all_files:
921 if all_files and '.hgsubstate' in all_files:
885 wctx = repo[None]
922 wctx = repo[None]
886 pctx = repo['.']
923 pctx = repo['.']
887 overwrite = False
924 overwrite = False
888 mergedsubstate = subrepo.submerge(repo, pctx, wctx, wctx,
925 mergedsubstate = subrepo.submerge(repo, pctx, wctx, wctx,
889 overwrite)
926 overwrite)
890 files += mergedsubstate.keys()
927 files += mergedsubstate.keys()
891
928
892 match = scmutil.matchfiles(repo, files or [])
929 match = scmutil.matchfiles(repo, files or [])
893 oldtip = repo['tip']
930 oldtip = repo['tip']
894 n = newcommit(repo, None, message, ph.user, ph.date, match=match,
931 n = newcommit(repo, None, message, ph.user, ph.date, match=match,
895 force=True)
932 force=True)
896 if repo['tip'] == oldtip:
933 if repo['tip'] == oldtip:
897 raise util.Abort(_("qpush exactly duplicates child changeset"))
934 raise util.Abort(_("qpush exactly duplicates child changeset"))
898 if n is None:
935 if n is None:
899 raise util.Abort(_("repository commit failed"))
936 raise util.Abort(_("repository commit failed"))
900
937
901 if update_status:
938 if update_status:
902 self.applied.append(statusentry(n, patchname))
939 self.applied.append(statusentry(n, patchname))
903
940
904 if patcherr:
941 if patcherr:
905 self.ui.warn(_("patch failed, rejects left in working dir\n"))
942 self.ui.warn(_("patch failed, rejects left in working dir\n"))
906 err = 2
943 err = 2
907 break
944 break
908
945
909 if fuzz and strict:
946 if fuzz and strict:
910 self.ui.warn(_("fuzz found when applying patch, stopping\n"))
947 self.ui.warn(_("fuzz found when applying patch, stopping\n"))
911 err = 3
948 err = 3
912 break
949 break
913 return (err, n)
950 return (err, n)
914
951
915 def _cleanup(self, patches, numrevs, keep=False):
952 def _cleanup(self, patches, numrevs, keep=False):
916 if not keep:
953 if not keep:
917 r = self.qrepo()
954 r = self.qrepo()
918 if r:
955 if r:
919 r[None].forget(patches)
956 r[None].forget(patches)
920 for p in patches:
957 for p in patches:
921 try:
958 try:
922 os.unlink(self.join(p))
959 os.unlink(self.join(p))
923 except OSError, inst:
960 except OSError, inst:
924 if inst.errno != errno.ENOENT:
961 if inst.errno != errno.ENOENT:
925 raise
962 raise
926
963
927 qfinished = []
964 qfinished = []
928 if numrevs:
965 if numrevs:
929 qfinished = self.applied[:numrevs]
966 qfinished = self.applied[:numrevs]
930 del self.applied[:numrevs]
967 del self.applied[:numrevs]
931 self.applieddirty = True
968 self.applieddirty = True
932
969
933 unknown = []
970 unknown = []
934
971
935 for (i, p) in sorted([(self.findseries(p), p) for p in patches],
972 for (i, p) in sorted([(self.findseries(p), p) for p in patches],
936 reverse=True):
973 reverse=True):
937 if i is not None:
974 if i is not None:
938 del self.fullseries[i]
975 del self.fullseries[i]
939 else:
976 else:
940 unknown.append(p)
977 unknown.append(p)
941
978
942 if unknown:
979 if unknown:
943 if numrevs:
980 if numrevs:
944 rev = dict((entry.name, entry.node) for entry in qfinished)
981 rev = dict((entry.name, entry.node) for entry in qfinished)
945 for p in unknown:
982 for p in unknown:
946 msg = _('revision %s refers to unknown patches: %s\n')
983 msg = _('revision %s refers to unknown patches: %s\n')
947 self.ui.warn(msg % (short(rev[p]), p))
984 self.ui.warn(msg % (short(rev[p]), p))
948 else:
985 else:
949 msg = _('unknown patches: %s\n')
986 msg = _('unknown patches: %s\n')
950 raise util.Abort(''.join(msg % p for p in unknown))
987 raise util.Abort(''.join(msg % p for p in unknown))
951
988
952 self.parseseries()
989 self.parseseries()
953 self.seriesdirty = True
990 self.seriesdirty = True
954 return [entry.node for entry in qfinished]
991 return [entry.node for entry in qfinished]
955
992
956 def _revpatches(self, repo, revs):
993 def _revpatches(self, repo, revs):
957 firstrev = repo[self.applied[0].node].rev()
994 firstrev = repo[self.applied[0].node].rev()
958 patches = []
995 patches = []
959 for i, rev in enumerate(revs):
996 for i, rev in enumerate(revs):
960
997
961 if rev < firstrev:
998 if rev < firstrev:
962 raise util.Abort(_('revision %d is not managed') % rev)
999 raise util.Abort(_('revision %d is not managed') % rev)
963
1000
964 ctx = repo[rev]
1001 ctx = repo[rev]
965 base = self.applied[i].node
1002 base = self.applied[i].node
966 if ctx.node() != base:
1003 if ctx.node() != base:
967 msg = _('cannot delete revision %d above applied patches')
1004 msg = _('cannot delete revision %d above applied patches')
968 raise util.Abort(msg % rev)
1005 raise util.Abort(msg % rev)
969
1006
970 patch = self.applied[i].name
1007 patch = self.applied[i].name
971 for fmt in ('[mq]: %s', 'imported patch %s'):
1008 for fmt in ('[mq]: %s', 'imported patch %s'):
972 if ctx.description() == fmt % patch:
1009 if ctx.description() == fmt % patch:
973 msg = _('patch %s finalized without changeset message\n')
1010 msg = _('patch %s finalized without changeset message\n')
974 repo.ui.status(msg % patch)
1011 repo.ui.status(msg % patch)
975 break
1012 break
976
1013
977 patches.append(patch)
1014 patches.append(patch)
978 return patches
1015 return patches
979
1016
980 def finish(self, repo, revs):
1017 def finish(self, repo, revs):
981 # Manually trigger phase computation to ensure phasedefaults is
1018 # Manually trigger phase computation to ensure phasedefaults is
982 # executed before we remove the patches.
1019 # executed before we remove the patches.
983 repo._phasecache
1020 repo._phasecache
984 patches = self._revpatches(repo, sorted(revs))
1021 patches = self._revpatches(repo, sorted(revs))
985 qfinished = self._cleanup(patches, len(patches))
1022 qfinished = self._cleanup(patches, len(patches))
986 if qfinished and repo.ui.configbool('mq', 'secret', False):
1023 if qfinished and repo.ui.configbool('mq', 'secret', False):
987 # only use this logic when the secret option is added
1024 # only use this logic when the secret option is added
988 oldqbase = repo[qfinished[0]]
1025 oldqbase = repo[qfinished[0]]
989 tphase = repo.ui.config('phases', 'new-commit', phases.draft)
1026 tphase = repo.ui.config('phases', 'new-commit', phases.draft)
990 if oldqbase.phase() > tphase and oldqbase.p1().phase() <= tphase:
1027 if oldqbase.phase() > tphase and oldqbase.p1().phase() <= tphase:
991 tr = repo.transaction('qfinish')
1028 tr = repo.transaction('qfinish')
992 try:
1029 try:
993 phases.advanceboundary(repo, tr, tphase, qfinished)
1030 phases.advanceboundary(repo, tr, tphase, qfinished)
994 tr.close()
1031 tr.close()
995 finally:
1032 finally:
996 tr.release()
1033 tr.release()
997
1034
998 def delete(self, repo, patches, opts):
1035 def delete(self, repo, patches, opts):
999 if not patches and not opts.get('rev'):
1036 if not patches and not opts.get('rev'):
1000 raise util.Abort(_('qdelete requires at least one revision or '
1037 raise util.Abort(_('qdelete requires at least one revision or '
1001 'patch name'))
1038 'patch name'))
1002
1039
1003 realpatches = []
1040 realpatches = []
1004 for patch in patches:
1041 for patch in patches:
1005 patch = self.lookup(patch, strict=True)
1042 patch = self.lookup(patch, strict=True)
1006 info = self.isapplied(patch)
1043 info = self.isapplied(patch)
1007 if info:
1044 if info:
1008 raise util.Abort(_("cannot delete applied patch %s") % patch)
1045 raise util.Abort(_("cannot delete applied patch %s") % patch)
1009 if patch not in self.series:
1046 if patch not in self.series:
1010 raise util.Abort(_("patch %s not in series file") % patch)
1047 raise util.Abort(_("patch %s not in series file") % patch)
1011 if patch not in realpatches:
1048 if patch not in realpatches:
1012 realpatches.append(patch)
1049 realpatches.append(patch)
1013
1050
1014 numrevs = 0
1051 numrevs = 0
1015 if opts.get('rev'):
1052 if opts.get('rev'):
1016 if not self.applied:
1053 if not self.applied:
1017 raise util.Abort(_('no patches applied'))
1054 raise util.Abort(_('no patches applied'))
1018 revs = scmutil.revrange(repo, opts.get('rev'))
1055 revs = scmutil.revrange(repo, opts.get('rev'))
1019 revs.sort()
1056 revs.sort()
1020 revpatches = self._revpatches(repo, revs)
1057 revpatches = self._revpatches(repo, revs)
1021 realpatches += revpatches
1058 realpatches += revpatches
1022 numrevs = len(revpatches)
1059 numrevs = len(revpatches)
1023
1060
1024 self._cleanup(realpatches, numrevs, opts.get('keep'))
1061 self._cleanup(realpatches, numrevs, opts.get('keep'))
1025
1062
1026 def checktoppatch(self, repo):
1063 def checktoppatch(self, repo):
1027 '''check that working directory is at qtip'''
1064 '''check that working directory is at qtip'''
1028 if self.applied:
1065 if self.applied:
1029 top = self.applied[-1].node
1066 top = self.applied[-1].node
1030 patch = self.applied[-1].name
1067 patch = self.applied[-1].name
1031 if repo.dirstate.p1() != top:
1068 if repo.dirstate.p1() != top:
1032 raise util.Abort(_("working directory revision is not qtip"))
1069 raise util.Abort(_("working directory revision is not qtip"))
1033 return top, patch
1070 return top, patch
1034 return None, None
1071 return None, None
1035
1072
1036 def putsubstate2changes(self, substatestate, changes):
1073 def putsubstate2changes(self, substatestate, changes):
1037 for files in changes[:3]:
1074 for files in changes[:3]:
1038 if '.hgsubstate' in files:
1075 if '.hgsubstate' in files:
1039 return # already listed up
1076 return # already listed up
1040 # not yet listed up
1077 # not yet listed up
1041 if substatestate in 'a?':
1078 if substatestate in 'a?':
1042 changes[1].append('.hgsubstate')
1079 changes[1].append('.hgsubstate')
1043 elif substatestate in 'r':
1080 elif substatestate in 'r':
1044 changes[2].append('.hgsubstate')
1081 changes[2].append('.hgsubstate')
1045 else: # modified
1082 else: # modified
1046 changes[0].append('.hgsubstate')
1083 changes[0].append('.hgsubstate')
1047
1084
1048 def checklocalchanges(self, repo, force=False, refresh=True):
1085 def checklocalchanges(self, repo, force=False, refresh=True):
1049 excsuffix = ''
1086 excsuffix = ''
1050 if refresh:
1087 if refresh:
1051 excsuffix = ', refresh first'
1088 excsuffix = ', refresh first'
1052 # plain versions for i18n tool to detect them
1089 # plain versions for i18n tool to detect them
1053 _("local changes found, refresh first")
1090 _("local changes found, refresh first")
1054 _("local changed subrepos found, refresh first")
1091 _("local changed subrepos found, refresh first")
1055 return checklocalchanges(repo, force, excsuffix)
1092 return checklocalchanges(repo, force, excsuffix)
1056
1093
1057 _reserved = ('series', 'status', 'guards', '.', '..')
1094 _reserved = ('series', 'status', 'guards', '.', '..')
1058 def checkreservedname(self, name):
1095 def checkreservedname(self, name):
1059 if name in self._reserved:
1096 if name in self._reserved:
1060 raise util.Abort(_('"%s" cannot be used as the name of a patch')
1097 raise util.Abort(_('"%s" cannot be used as the name of a patch')
1061 % name)
1098 % name)
1062 for prefix in ('.hg', '.mq'):
1099 for prefix in ('.hg', '.mq'):
1063 if name.startswith(prefix):
1100 if name.startswith(prefix):
1064 raise util.Abort(_('patch name cannot begin with "%s"')
1101 raise util.Abort(_('patch name cannot begin with "%s"')
1065 % prefix)
1102 % prefix)
1066 for c in ('#', ':'):
1103 for c in ('#', ':'):
1067 if c in name:
1104 if c in name:
1068 raise util.Abort(_('"%s" cannot be used in the name of a patch')
1105 raise util.Abort(_('"%s" cannot be used in the name of a patch')
1069 % c)
1106 % c)
1070
1107
1071 def checkpatchname(self, name, force=False):
1108 def checkpatchname(self, name, force=False):
1072 self.checkreservedname(name)
1109 self.checkreservedname(name)
1073 if not force and os.path.exists(self.join(name)):
1110 if not force and os.path.exists(self.join(name)):
1074 if os.path.isdir(self.join(name)):
1111 if os.path.isdir(self.join(name)):
1075 raise util.Abort(_('"%s" already exists as a directory')
1112 raise util.Abort(_('"%s" already exists as a directory')
1076 % name)
1113 % name)
1077 else:
1114 else:
1078 raise util.Abort(_('patch "%s" already exists') % name)
1115 raise util.Abort(_('patch "%s" already exists') % name)
1079
1116
1080 def checkkeepchanges(self, keepchanges, force):
1117 def checkkeepchanges(self, keepchanges, force):
1081 if force and keepchanges:
1118 if force and keepchanges:
1082 raise util.Abort(_('cannot use both --force and --keep-changes'))
1119 raise util.Abort(_('cannot use both --force and --keep-changes'))
1083
1120
1084 def new(self, repo, patchfn, *pats, **opts):
1121 def new(self, repo, patchfn, *pats, **opts):
1085 """options:
1122 """options:
1086 msg: a string or a no-argument function returning a string
1123 msg: a string or a no-argument function returning a string
1087 """
1124 """
1088 msg = opts.get('msg')
1125 msg = opts.get('msg')
1089 edit = opts.get('edit')
1126 edit = opts.get('edit')
1090 editform = opts.get('editform', 'mq.qnew')
1127 editform = opts.get('editform', 'mq.qnew')
1091 user = opts.get('user')
1128 user = opts.get('user')
1092 date = opts.get('date')
1129 date = opts.get('date')
1093 if date:
1130 if date:
1094 date = util.parsedate(date)
1131 date = util.parsedate(date)
1095 diffopts = self.diffopts({'git': opts.get('git')})
1132 diffopts = self.diffopts({'git': opts.get('git')})
1096 if opts.get('checkname', True):
1133 if opts.get('checkname', True):
1097 self.checkpatchname(patchfn)
1134 self.checkpatchname(patchfn)
1098 inclsubs = checksubstate(repo)
1135 inclsubs = checksubstate(repo)
1099 if inclsubs:
1136 if inclsubs:
1100 substatestate = repo.dirstate['.hgsubstate']
1137 substatestate = repo.dirstate['.hgsubstate']
1101 if opts.get('include') or opts.get('exclude') or pats:
1138 if opts.get('include') or opts.get('exclude') or pats:
1102 match = scmutil.match(repo[None], pats, opts)
1139 match = scmutil.match(repo[None], pats, opts)
1103 # detect missing files in pats
1140 # detect missing files in pats
1104 def badfn(f, msg):
1141 def badfn(f, msg):
1105 if f != '.hgsubstate': # .hgsubstate is auto-created
1142 if f != '.hgsubstate': # .hgsubstate is auto-created
1106 raise util.Abort('%s: %s' % (f, msg))
1143 raise util.Abort('%s: %s' % (f, msg))
1107 match.bad = badfn
1144 match.bad = badfn
1108 changes = repo.status(match=match)
1145 changes = repo.status(match=match)
1109 else:
1146 else:
1110 changes = self.checklocalchanges(repo, force=True)
1147 changes = self.checklocalchanges(repo, force=True)
1111 commitfiles = list(inclsubs)
1148 commitfiles = list(inclsubs)
1112 for files in changes[:3]:
1149 for files in changes[:3]:
1113 commitfiles.extend(files)
1150 commitfiles.extend(files)
1114 match = scmutil.matchfiles(repo, commitfiles)
1151 match = scmutil.matchfiles(repo, commitfiles)
1115 if len(repo[None].parents()) > 1:
1152 if len(repo[None].parents()) > 1:
1116 raise util.Abort(_('cannot manage merge changesets'))
1153 raise util.Abort(_('cannot manage merge changesets'))
1117 self.checktoppatch(repo)
1154 self.checktoppatch(repo)
1118 insert = self.fullseriesend()
1155 insert = self.fullseriesend()
1119 wlock = repo.wlock()
1156 wlock = repo.wlock()
1120 try:
1157 try:
1121 try:
1158 try:
1122 # if patch file write fails, abort early
1159 # if patch file write fails, abort early
1123 p = self.opener(patchfn, "w")
1160 p = self.opener(patchfn, "w")
1124 except IOError, e:
1161 except IOError, e:
1125 raise util.Abort(_('cannot write patch "%s": %s')
1162 raise util.Abort(_('cannot write patch "%s": %s')
1126 % (patchfn, e.strerror))
1163 % (patchfn, e.strerror))
1127 try:
1164 try:
1128 defaultmsg = "[mq]: %s" % patchfn
1165 defaultmsg = "[mq]: %s" % patchfn
1129 editor = cmdutil.getcommiteditor(editform=editform)
1166 editor = cmdutil.getcommiteditor(editform=editform)
1130 if edit:
1167 if edit:
1131 def finishdesc(desc):
1168 def finishdesc(desc):
1132 if desc.rstrip():
1169 if desc.rstrip():
1133 return desc
1170 return desc
1134 else:
1171 else:
1135 return defaultmsg
1172 return defaultmsg
1136 # i18n: this message is shown in editor with "HG: " prefix
1173 # i18n: this message is shown in editor with "HG: " prefix
1137 extramsg = _('Leave message empty to use default message.')
1174 extramsg = _('Leave message empty to use default message.')
1138 editor = cmdutil.getcommiteditor(finishdesc=finishdesc,
1175 editor = cmdutil.getcommiteditor(finishdesc=finishdesc,
1139 extramsg=extramsg,
1176 extramsg=extramsg,
1140 editform=editform)
1177 editform=editform)
1141 commitmsg = msg
1178 commitmsg = msg
1142 else:
1179 else:
1143 commitmsg = msg or defaultmsg
1180 commitmsg = msg or defaultmsg
1144
1181
1145 n = newcommit(repo, None, commitmsg, user, date, match=match,
1182 n = newcommit(repo, None, commitmsg, user, date, match=match,
1146 force=True, editor=editor)
1183 force=True, editor=editor)
1147 if n is None:
1184 if n is None:
1148 raise util.Abort(_("repo commit failed"))
1185 raise util.Abort(_("repo commit failed"))
1149 try:
1186 try:
1150 self.fullseries[insert:insert] = [patchfn]
1187 self.fullseries[insert:insert] = [patchfn]
1151 self.applied.append(statusentry(n, patchfn))
1188 self.applied.append(statusentry(n, patchfn))
1152 self.parseseries()
1189 self.parseseries()
1153 self.seriesdirty = True
1190 self.seriesdirty = True
1154 self.applieddirty = True
1191 self.applieddirty = True
1155 nctx = repo[n]
1192 nctx = repo[n]
1156 ph = patchheader(self.join(patchfn), self.plainmode)
1193 ph = patchheader(self.join(patchfn), self.plainmode)
1157 if user:
1194 if user:
1158 ph.setuser(user)
1195 ph.setuser(user)
1159 if date:
1196 if date:
1160 ph.setdate('%s %s' % date)
1197 ph.setdate('%s %s' % date)
1161 ph.setparent(hex(nctx.p1().node()))
1198 ph.setparent(hex(nctx.p1().node()))
1162 msg = nctx.description().strip()
1199 msg = nctx.description().strip()
1163 if msg == defaultmsg.strip():
1200 if msg == defaultmsg.strip():
1164 msg = ''
1201 msg = ''
1165 ph.setmessage(msg)
1202 ph.setmessage(msg)
1166 p.write(str(ph))
1203 p.write(str(ph))
1167 if commitfiles:
1204 if commitfiles:
1168 parent = self.qparents(repo, n)
1205 parent = self.qparents(repo, n)
1169 if inclsubs:
1206 if inclsubs:
1170 self.putsubstate2changes(substatestate, changes)
1207 self.putsubstate2changes(substatestate, changes)
1171 chunks = patchmod.diff(repo, node1=parent, node2=n,
1208 chunks = patchmod.diff(repo, node1=parent, node2=n,
1172 changes=changes, opts=diffopts)
1209 changes=changes, opts=diffopts)
1173 for chunk in chunks:
1210 for chunk in chunks:
1174 p.write(chunk)
1211 p.write(chunk)
1175 p.close()
1212 p.close()
1176 r = self.qrepo()
1213 r = self.qrepo()
1177 if r:
1214 if r:
1178 r[None].add([patchfn])
1215 r[None].add([patchfn])
1179 except: # re-raises
1216 except: # re-raises
1180 repo.rollback()
1217 repo.rollback()
1181 raise
1218 raise
1182 except Exception:
1219 except Exception:
1183 patchpath = self.join(patchfn)
1220 patchpath = self.join(patchfn)
1184 try:
1221 try:
1185 os.unlink(patchpath)
1222 os.unlink(patchpath)
1186 except OSError:
1223 except OSError:
1187 self.ui.warn(_('error unlinking %s\n') % patchpath)
1224 self.ui.warn(_('error unlinking %s\n') % patchpath)
1188 raise
1225 raise
1189 self.removeundo(repo)
1226 self.removeundo(repo)
1190 finally:
1227 finally:
1191 release(wlock)
1228 release(wlock)
1192
1229
1193 def isapplied(self, patch):
1230 def isapplied(self, patch):
1194 """returns (index, rev, patch)"""
1231 """returns (index, rev, patch)"""
1195 for i, a in enumerate(self.applied):
1232 for i, a in enumerate(self.applied):
1196 if a.name == patch:
1233 if a.name == patch:
1197 return (i, a.node, a.name)
1234 return (i, a.node, a.name)
1198 return None
1235 return None
1199
1236
1200 # if the exact patch name does not exist, we try a few
1237 # if the exact patch name does not exist, we try a few
1201 # variations. If strict is passed, we try only #1
1238 # variations. If strict is passed, we try only #1
1202 #
1239 #
1203 # 1) a number (as string) to indicate an offset in the series file
1240 # 1) a number (as string) to indicate an offset in the series file
1204 # 2) a unique substring of the patch name was given
1241 # 2) a unique substring of the patch name was given
1205 # 3) patchname[-+]num to indicate an offset in the series file
1242 # 3) patchname[-+]num to indicate an offset in the series file
1206 def lookup(self, patch, strict=False):
1243 def lookup(self, patch, strict=False):
1207 def partialname(s):
1244 def partialname(s):
1208 if s in self.series:
1245 if s in self.series:
1209 return s
1246 return s
1210 matches = [x for x in self.series if s in x]
1247 matches = [x for x in self.series if s in x]
1211 if len(matches) > 1:
1248 if len(matches) > 1:
1212 self.ui.warn(_('patch name "%s" is ambiguous:\n') % s)
1249 self.ui.warn(_('patch name "%s" is ambiguous:\n') % s)
1213 for m in matches:
1250 for m in matches:
1214 self.ui.warn(' %s\n' % m)
1251 self.ui.warn(' %s\n' % m)
1215 return None
1252 return None
1216 if matches:
1253 if matches:
1217 return matches[0]
1254 return matches[0]
1218 if self.series and self.applied:
1255 if self.series and self.applied:
1219 if s == 'qtip':
1256 if s == 'qtip':
1220 return self.series[self.seriesend(True) - 1]
1257 return self.series[self.seriesend(True) - 1]
1221 if s == 'qbase':
1258 if s == 'qbase':
1222 return self.series[0]
1259 return self.series[0]
1223 return None
1260 return None
1224
1261
1225 if patch in self.series:
1262 if patch in self.series:
1226 return patch
1263 return patch
1227
1264
1228 if not os.path.isfile(self.join(patch)):
1265 if not os.path.isfile(self.join(patch)):
1229 try:
1266 try:
1230 sno = int(patch)
1267 sno = int(patch)
1231 except (ValueError, OverflowError):
1268 except (ValueError, OverflowError):
1232 pass
1269 pass
1233 else:
1270 else:
1234 if -len(self.series) <= sno < len(self.series):
1271 if -len(self.series) <= sno < len(self.series):
1235 return self.series[sno]
1272 return self.series[sno]
1236
1273
1237 if not strict:
1274 if not strict:
1238 res = partialname(patch)
1275 res = partialname(patch)
1239 if res:
1276 if res:
1240 return res
1277 return res
1241 minus = patch.rfind('-')
1278 minus = patch.rfind('-')
1242 if minus >= 0:
1279 if minus >= 0:
1243 res = partialname(patch[:minus])
1280 res = partialname(patch[:minus])
1244 if res:
1281 if res:
1245 i = self.series.index(res)
1282 i = self.series.index(res)
1246 try:
1283 try:
1247 off = int(patch[minus + 1:] or 1)
1284 off = int(patch[minus + 1:] or 1)
1248 except (ValueError, OverflowError):
1285 except (ValueError, OverflowError):
1249 pass
1286 pass
1250 else:
1287 else:
1251 if i - off >= 0:
1288 if i - off >= 0:
1252 return self.series[i - off]
1289 return self.series[i - off]
1253 plus = patch.rfind('+')
1290 plus = patch.rfind('+')
1254 if plus >= 0:
1291 if plus >= 0:
1255 res = partialname(patch[:plus])
1292 res = partialname(patch[:plus])
1256 if res:
1293 if res:
1257 i = self.series.index(res)
1294 i = self.series.index(res)
1258 try:
1295 try:
1259 off = int(patch[plus + 1:] or 1)
1296 off = int(patch[plus + 1:] or 1)
1260 except (ValueError, OverflowError):
1297 except (ValueError, OverflowError):
1261 pass
1298 pass
1262 else:
1299 else:
1263 if i + off < len(self.series):
1300 if i + off < len(self.series):
1264 return self.series[i + off]
1301 return self.series[i + off]
1265 raise util.Abort(_("patch %s not in series") % patch)
1302 raise util.Abort(_("patch %s not in series") % patch)
1266
1303
1267 def push(self, repo, patch=None, force=False, list=False, mergeq=None,
1304 def push(self, repo, patch=None, force=False, list=False, mergeq=None,
1268 all=False, move=False, exact=False, nobackup=False,
1305 all=False, move=False, exact=False, nobackup=False,
1269 keepchanges=False):
1306 keepchanges=False):
1270 self.checkkeepchanges(keepchanges, force)
1307 self.checkkeepchanges(keepchanges, force)
1271 diffopts = self.diffopts()
1308 diffopts = self.diffopts()
1272 wlock = repo.wlock()
1309 wlock = repo.wlock()
1273 try:
1310 try:
1274 heads = []
1311 heads = []
1275 for hs in repo.branchmap().itervalues():
1312 for hs in repo.branchmap().itervalues():
1276 heads.extend(hs)
1313 heads.extend(hs)
1277 if not heads:
1314 if not heads:
1278 heads = [nullid]
1315 heads = [nullid]
1279 if repo.dirstate.p1() not in heads and not exact:
1316 if repo.dirstate.p1() not in heads and not exact:
1280 self.ui.status(_("(working directory not at a head)\n"))
1317 self.ui.status(_("(working directory not at a head)\n"))
1281
1318
1282 if not self.series:
1319 if not self.series:
1283 self.ui.warn(_('no patches in series\n'))
1320 self.ui.warn(_('no patches in series\n'))
1284 return 0
1321 return 0
1285
1322
1286 # Suppose our series file is: A B C and the current 'top'
1323 # Suppose our series file is: A B C and the current 'top'
1287 # patch is B. qpush C should be performed (moving forward)
1324 # patch is B. qpush C should be performed (moving forward)
1288 # qpush B is a NOP (no change) qpush A is an error (can't
1325 # qpush B is a NOP (no change) qpush A is an error (can't
1289 # go backwards with qpush)
1326 # go backwards with qpush)
1290 if patch:
1327 if patch:
1291 patch = self.lookup(patch)
1328 patch = self.lookup(patch)
1292 info = self.isapplied(patch)
1329 info = self.isapplied(patch)
1293 if info and info[0] >= len(self.applied) - 1:
1330 if info and info[0] >= len(self.applied) - 1:
1294 self.ui.warn(
1331 self.ui.warn(
1295 _('qpush: %s is already at the top\n') % patch)
1332 _('qpush: %s is already at the top\n') % patch)
1296 return 0
1333 return 0
1297
1334
1298 pushable, reason = self.pushable(patch)
1335 pushable, reason = self.pushable(patch)
1299 if pushable:
1336 if pushable:
1300 if self.series.index(patch) < self.seriesend():
1337 if self.series.index(patch) < self.seriesend():
1301 raise util.Abort(
1338 raise util.Abort(
1302 _("cannot push to a previous patch: %s") % patch)
1339 _("cannot push to a previous patch: %s") % patch)
1303 else:
1340 else:
1304 if reason:
1341 if reason:
1305 reason = _('guarded by %s') % reason
1342 reason = _('guarded by %s') % reason
1306 else:
1343 else:
1307 reason = _('no matching guards')
1344 reason = _('no matching guards')
1308 self.ui.warn(_("cannot push '%s' - %s\n") % (patch, reason))
1345 self.ui.warn(_("cannot push '%s' - %s\n") % (patch, reason))
1309 return 1
1346 return 1
1310 elif all:
1347 elif all:
1311 patch = self.series[-1]
1348 patch = self.series[-1]
1312 if self.isapplied(patch):
1349 if self.isapplied(patch):
1313 self.ui.warn(_('all patches are currently applied\n'))
1350 self.ui.warn(_('all patches are currently applied\n'))
1314 return 0
1351 return 0
1315
1352
1316 # Following the above example, starting at 'top' of B:
1353 # Following the above example, starting at 'top' of B:
1317 # qpush should be performed (pushes C), but a subsequent
1354 # qpush should be performed (pushes C), but a subsequent
1318 # qpush without an argument is an error (nothing to
1355 # qpush without an argument is an error (nothing to
1319 # apply). This allows a loop of "...while hg qpush..." to
1356 # apply). This allows a loop of "...while hg qpush..." to
1320 # work as it detects an error when done
1357 # work as it detects an error when done
1321 start = self.seriesend()
1358 start = self.seriesend()
1322 if start == len(self.series):
1359 if start == len(self.series):
1323 self.ui.warn(_('patch series already fully applied\n'))
1360 self.ui.warn(_('patch series already fully applied\n'))
1324 return 1
1361 return 1
1325 if not force and not keepchanges:
1362 if not force and not keepchanges:
1326 self.checklocalchanges(repo, refresh=self.applied)
1363 self.checklocalchanges(repo, refresh=self.applied)
1327
1364
1328 if exact:
1365 if exact:
1329 if keepchanges:
1366 if keepchanges:
1330 raise util.Abort(
1367 raise util.Abort(
1331 _("cannot use --exact and --keep-changes together"))
1368 _("cannot use --exact and --keep-changes together"))
1332 if move:
1369 if move:
1333 raise util.Abort(_('cannot use --exact and --move '
1370 raise util.Abort(_('cannot use --exact and --move '
1334 'together'))
1371 'together'))
1335 if self.applied:
1372 if self.applied:
1336 raise util.Abort(_('cannot push --exact with applied '
1373 raise util.Abort(_('cannot push --exact with applied '
1337 'patches'))
1374 'patches'))
1338 root = self.series[start]
1375 root = self.series[start]
1339 target = patchheader(self.join(root), self.plainmode).parent
1376 target = patchheader(self.join(root), self.plainmode).parent
1340 if not target:
1377 if not target:
1341 raise util.Abort(
1378 raise util.Abort(
1342 _("%s does not have a parent recorded") % root)
1379 _("%s does not have a parent recorded") % root)
1343 if not repo[target] == repo['.']:
1380 if not repo[target] == repo['.']:
1344 hg.update(repo, target)
1381 hg.update(repo, target)
1345
1382
1346 if move:
1383 if move:
1347 if not patch:
1384 if not patch:
1348 raise util.Abort(_("please specify the patch to move"))
1385 raise util.Abort(_("please specify the patch to move"))
1349 for fullstart, rpn in enumerate(self.fullseries):
1386 for fullstart, rpn in enumerate(self.fullseries):
1350 # strip markers for patch guards
1387 # strip markers for patch guards
1351 if self.guard_re.split(rpn, 1)[0] == self.series[start]:
1388 if self.guard_re.split(rpn, 1)[0] == self.series[start]:
1352 break
1389 break
1353 for i, rpn in enumerate(self.fullseries[fullstart:]):
1390 for i, rpn in enumerate(self.fullseries[fullstart:]):
1354 # strip markers for patch guards
1391 # strip markers for patch guards
1355 if self.guard_re.split(rpn, 1)[0] == patch:
1392 if self.guard_re.split(rpn, 1)[0] == patch:
1356 break
1393 break
1357 index = fullstart + i
1394 index = fullstart + i
1358 assert index < len(self.fullseries)
1395 assert index < len(self.fullseries)
1359 fullpatch = self.fullseries[index]
1396 fullpatch = self.fullseries[index]
1360 del self.fullseries[index]
1397 del self.fullseries[index]
1361 self.fullseries.insert(fullstart, fullpatch)
1398 self.fullseries.insert(fullstart, fullpatch)
1362 self.parseseries()
1399 self.parseseries()
1363 self.seriesdirty = True
1400 self.seriesdirty = True
1364
1401
1365 self.applieddirty = True
1402 self.applieddirty = True
1366 if start > 0:
1403 if start > 0:
1367 self.checktoppatch(repo)
1404 self.checktoppatch(repo)
1368 if not patch:
1405 if not patch:
1369 patch = self.series[start]
1406 patch = self.series[start]
1370 end = start + 1
1407 end = start + 1
1371 else:
1408 else:
1372 end = self.series.index(patch, start) + 1
1409 end = self.series.index(patch, start) + 1
1373
1410
1374 tobackup = set()
1411 tobackup = set()
1375 if (not nobackup and force) or keepchanges:
1412 if (not nobackup and force) or keepchanges:
1376 status = self.checklocalchanges(repo, force=True)
1413 status = self.checklocalchanges(repo, force=True)
1377 if keepchanges:
1414 if keepchanges:
1378 tobackup.update(status.modified + status.added +
1415 tobackup.update(status.modified + status.added +
1379 status.removed + status.deleted)
1416 status.removed + status.deleted)
1380 else:
1417 else:
1381 tobackup.update(status.modified + status.added)
1418 tobackup.update(status.modified + status.added)
1382
1419
1383 s = self.series[start:end]
1420 s = self.series[start:end]
1384 all_files = set()
1421 all_files = set()
1385 try:
1422 try:
1386 if mergeq:
1423 if mergeq:
1387 ret = self.mergepatch(repo, mergeq, s, diffopts)
1424 ret = self.mergepatch(repo, mergeq, s, diffopts)
1388 else:
1425 else:
1389 ret = self.apply(repo, s, list, all_files=all_files,
1426 ret = self.apply(repo, s, list, all_files=all_files,
1390 tobackup=tobackup, keepchanges=keepchanges)
1427 tobackup=tobackup, keepchanges=keepchanges)
1391 except: # re-raises
1428 except: # re-raises
1392 self.ui.warn(_('cleaning up working directory...'))
1429 self.ui.warn(_('cleaning up working directory...'))
1393 node = repo.dirstate.p1()
1430 node = repo.dirstate.p1()
1394 hg.revert(repo, node, None)
1431 hg.revert(repo, node, None)
1395 # only remove unknown files that we know we touched or
1432 # only remove unknown files that we know we touched or
1396 # created while patching
1433 # created while patching
1397 for f in all_files:
1434 for f in all_files:
1398 if f not in repo.dirstate:
1435 if f not in repo.dirstate:
1399 util.unlinkpath(repo.wjoin(f), ignoremissing=True)
1436 util.unlinkpath(repo.wjoin(f), ignoremissing=True)
1400 self.ui.warn(_('done\n'))
1437 self.ui.warn(_('done\n'))
1401 raise
1438 raise
1402
1439
1403 if not self.applied:
1440 if not self.applied:
1404 return ret[0]
1441 return ret[0]
1405 top = self.applied[-1].name
1442 top = self.applied[-1].name
1406 if ret[0] and ret[0] > 1:
1443 if ret[0] and ret[0] > 1:
1407 msg = _("errors during apply, please fix and refresh %s\n")
1444 msg = _("errors during apply, please fix and refresh %s\n")
1408 self.ui.write(msg % top)
1445 self.ui.write(msg % top)
1409 else:
1446 else:
1410 self.ui.write(_("now at: %s\n") % top)
1447 self.ui.write(_("now at: %s\n") % top)
1411 return ret[0]
1448 return ret[0]
1412
1449
1413 finally:
1450 finally:
1414 wlock.release()
1451 wlock.release()
1415
1452
1416 def pop(self, repo, patch=None, force=False, update=True, all=False,
1453 def pop(self, repo, patch=None, force=False, update=True, all=False,
1417 nobackup=False, keepchanges=False):
1454 nobackup=False, keepchanges=False):
1418 self.checkkeepchanges(keepchanges, force)
1455 self.checkkeepchanges(keepchanges, force)
1419 wlock = repo.wlock()
1456 wlock = repo.wlock()
1420 try:
1457 try:
1421 if patch:
1458 if patch:
1422 # index, rev, patch
1459 # index, rev, patch
1423 info = self.isapplied(patch)
1460 info = self.isapplied(patch)
1424 if not info:
1461 if not info:
1425 patch = self.lookup(patch)
1462 patch = self.lookup(patch)
1426 info = self.isapplied(patch)
1463 info = self.isapplied(patch)
1427 if not info:
1464 if not info:
1428 raise util.Abort(_("patch %s is not applied") % patch)
1465 raise util.Abort(_("patch %s is not applied") % patch)
1429
1466
1430 if not self.applied:
1467 if not self.applied:
1431 # Allow qpop -a to work repeatedly,
1468 # Allow qpop -a to work repeatedly,
1432 # but not qpop without an argument
1469 # but not qpop without an argument
1433 self.ui.warn(_("no patches applied\n"))
1470 self.ui.warn(_("no patches applied\n"))
1434 return not all
1471 return not all
1435
1472
1436 if all:
1473 if all:
1437 start = 0
1474 start = 0
1438 elif patch:
1475 elif patch:
1439 start = info[0] + 1
1476 start = info[0] + 1
1440 else:
1477 else:
1441 start = len(self.applied) - 1
1478 start = len(self.applied) - 1
1442
1479
1443 if start >= len(self.applied):
1480 if start >= len(self.applied):
1444 self.ui.warn(_("qpop: %s is already at the top\n") % patch)
1481 self.ui.warn(_("qpop: %s is already at the top\n") % patch)
1445 return
1482 return
1446
1483
1447 if not update:
1484 if not update:
1448 parents = repo.dirstate.parents()
1485 parents = repo.dirstate.parents()
1449 rr = [x.node for x in self.applied]
1486 rr = [x.node for x in self.applied]
1450 for p in parents:
1487 for p in parents:
1451 if p in rr:
1488 if p in rr:
1452 self.ui.warn(_("qpop: forcing dirstate update\n"))
1489 self.ui.warn(_("qpop: forcing dirstate update\n"))
1453 update = True
1490 update = True
1454 else:
1491 else:
1455 parents = [p.node() for p in repo[None].parents()]
1492 parents = [p.node() for p in repo[None].parents()]
1456 needupdate = False
1493 needupdate = False
1457 for entry in self.applied[start:]:
1494 for entry in self.applied[start:]:
1458 if entry.node in parents:
1495 if entry.node in parents:
1459 needupdate = True
1496 needupdate = True
1460 break
1497 break
1461 update = needupdate
1498 update = needupdate
1462
1499
1463 tobackup = set()
1500 tobackup = set()
1464 if update:
1501 if update:
1465 s = self.checklocalchanges(repo, force=force or keepchanges)
1502 s = self.checklocalchanges(repo, force=force or keepchanges)
1466 if force:
1503 if force:
1467 if not nobackup:
1504 if not nobackup:
1468 tobackup.update(s.modified + s.added)
1505 tobackup.update(s.modified + s.added)
1469 elif keepchanges:
1506 elif keepchanges:
1470 tobackup.update(s.modified + s.added +
1507 tobackup.update(s.modified + s.added +
1471 s.removed + s.deleted)
1508 s.removed + s.deleted)
1472
1509
1473 self.applieddirty = True
1510 self.applieddirty = True
1474 end = len(self.applied)
1511 end = len(self.applied)
1475 rev = self.applied[start].node
1512 rev = self.applied[start].node
1476
1513
1477 try:
1514 try:
1478 heads = repo.changelog.heads(rev)
1515 heads = repo.changelog.heads(rev)
1479 except error.LookupError:
1516 except error.LookupError:
1480 node = short(rev)
1517 node = short(rev)
1481 raise util.Abort(_('trying to pop unknown node %s') % node)
1518 raise util.Abort(_('trying to pop unknown node %s') % node)
1482
1519
1483 if heads != [self.applied[-1].node]:
1520 if heads != [self.applied[-1].node]:
1484 raise util.Abort(_("popping would remove a revision not "
1521 raise util.Abort(_("popping would remove a revision not "
1485 "managed by this patch queue"))
1522 "managed by this patch queue"))
1486 if not repo[self.applied[-1].node].mutable():
1523 if not repo[self.applied[-1].node].mutable():
1487 raise util.Abort(
1524 raise util.Abort(
1488 _("popping would remove an immutable revision"),
1525 _("popping would remove an immutable revision"),
1489 hint=_('see "hg help phases" for details'))
1526 hint=_('see "hg help phases" for details'))
1490
1527
1491 # we know there are no local changes, so we can make a simplified
1528 # we know there are no local changes, so we can make a simplified
1492 # form of hg.update.
1529 # form of hg.update.
1493 if update:
1530 if update:
1494 qp = self.qparents(repo, rev)
1531 qp = self.qparents(repo, rev)
1495 ctx = repo[qp]
1532 ctx = repo[qp]
1496 m, a, r, d = repo.status(qp, '.')[:4]
1533 m, a, r, d = repo.status(qp, '.')[:4]
1497 if d:
1534 if d:
1498 raise util.Abort(_("deletions found between repo revs"))
1535 raise util.Abort(_("deletions found between repo revs"))
1499
1536
1500 tobackup = set(a + m + r) & tobackup
1537 tobackup = set(a + m + r) & tobackup
1501 if keepchanges and tobackup:
1538 if keepchanges and tobackup:
1502 raise util.Abort(_("local changes found, refresh first"))
1539 raise util.Abort(_("local changes found, refresh first"))
1503 self.backup(repo, tobackup)
1540 self.backup(repo, tobackup)
1504 repo.dirstate.beginparentchange()
1541 repo.dirstate.beginparentchange()
1505 for f in a:
1542 for f in a:
1506 util.unlinkpath(repo.wjoin(f), ignoremissing=True)
1543 util.unlinkpath(repo.wjoin(f), ignoremissing=True)
1507 repo.dirstate.drop(f)
1544 repo.dirstate.drop(f)
1508 for f in m + r:
1545 for f in m + r:
1509 fctx = ctx[f]
1546 fctx = ctx[f]
1510 repo.wwrite(f, fctx.data(), fctx.flags())
1547 repo.wwrite(f, fctx.data(), fctx.flags())
1511 repo.dirstate.normal(f)
1548 repo.dirstate.normal(f)
1512 repo.setparents(qp, nullid)
1549 repo.setparents(qp, nullid)
1513 repo.dirstate.endparentchange()
1550 repo.dirstate.endparentchange()
1514 for patch in reversed(self.applied[start:end]):
1551 for patch in reversed(self.applied[start:end]):
1515 self.ui.status(_("popping %s\n") % patch.name)
1552 self.ui.status(_("popping %s\n") % patch.name)
1516 del self.applied[start:end]
1553 del self.applied[start:end]
1517 strip(self.ui, repo, [rev], update=False, backup=False)
1554 strip(self.ui, repo, [rev], update=False, backup=False)
1518 for s, state in repo['.'].substate.items():
1555 for s, state in repo['.'].substate.items():
1519 repo['.'].sub(s).get(state)
1556 repo['.'].sub(s).get(state)
1520 if self.applied:
1557 if self.applied:
1521 self.ui.write(_("now at: %s\n") % self.applied[-1].name)
1558 self.ui.write(_("now at: %s\n") % self.applied[-1].name)
1522 else:
1559 else:
1523 self.ui.write(_("patch queue now empty\n"))
1560 self.ui.write(_("patch queue now empty\n"))
1524 finally:
1561 finally:
1525 wlock.release()
1562 wlock.release()
1526
1563
1527 def diff(self, repo, pats, opts):
1564 def diff(self, repo, pats, opts):
1528 top, patch = self.checktoppatch(repo)
1565 top, patch = self.checktoppatch(repo)
1529 if not top:
1566 if not top:
1530 self.ui.write(_("no patches applied\n"))
1567 self.ui.write(_("no patches applied\n"))
1531 return
1568 return
1532 qp = self.qparents(repo, top)
1569 qp = self.qparents(repo, top)
1533 if opts.get('reverse'):
1570 if opts.get('reverse'):
1534 node1, node2 = None, qp
1571 node1, node2 = None, qp
1535 else:
1572 else:
1536 node1, node2 = qp, None
1573 node1, node2 = qp, None
1537 diffopts = self.diffopts(opts, patch)
1574 diffopts = self.diffopts(opts, patch)
1538 self.printdiff(repo, diffopts, node1, node2, files=pats, opts=opts)
1575 self.printdiff(repo, diffopts, node1, node2, files=pats, opts=opts)
1539
1576
1540 def refresh(self, repo, pats=None, **opts):
1577 def refresh(self, repo, pats=None, **opts):
1541 if not self.applied:
1578 if not self.applied:
1542 self.ui.write(_("no patches applied\n"))
1579 self.ui.write(_("no patches applied\n"))
1543 return 1
1580 return 1
1544 msg = opts.get('msg', '').rstrip()
1581 msg = opts.get('msg', '').rstrip()
1545 edit = opts.get('edit')
1582 edit = opts.get('edit')
1546 editform = opts.get('editform', 'mq.qrefresh')
1583 editform = opts.get('editform', 'mq.qrefresh')
1547 newuser = opts.get('user')
1584 newuser = opts.get('user')
1548 newdate = opts.get('date')
1585 newdate = opts.get('date')
1549 if newdate:
1586 if newdate:
1550 newdate = '%d %d' % util.parsedate(newdate)
1587 newdate = '%d %d' % util.parsedate(newdate)
1551 wlock = repo.wlock()
1588 wlock = repo.wlock()
1552
1589
1553 try:
1590 try:
1554 self.checktoppatch(repo)
1591 self.checktoppatch(repo)
1555 (top, patchfn) = (self.applied[-1].node, self.applied[-1].name)
1592 (top, patchfn) = (self.applied[-1].node, self.applied[-1].name)
1556 if repo.changelog.heads(top) != [top]:
1593 if repo.changelog.heads(top) != [top]:
1557 raise util.Abort(_("cannot refresh a revision with children"))
1594 raise util.Abort(_("cannot refresh a revision with children"))
1558 if not repo[top].mutable():
1595 if not repo[top].mutable():
1559 raise util.Abort(_("cannot refresh immutable revision"),
1596 raise util.Abort(_("cannot refresh immutable revision"),
1560 hint=_('see "hg help phases" for details'))
1597 hint=_('see "hg help phases" for details'))
1561
1598
1562 cparents = repo.changelog.parents(top)
1599 cparents = repo.changelog.parents(top)
1563 patchparent = self.qparents(repo, top)
1600 patchparent = self.qparents(repo, top)
1564
1601
1565 inclsubs = checksubstate(repo, hex(patchparent))
1602 inclsubs = checksubstate(repo, hex(patchparent))
1566 if inclsubs:
1603 if inclsubs:
1567 substatestate = repo.dirstate['.hgsubstate']
1604 substatestate = repo.dirstate['.hgsubstate']
1568
1605
1569 ph = patchheader(self.join(patchfn), self.plainmode)
1606 ph = patchheader(self.join(patchfn), self.plainmode)
1570 diffopts = self.diffopts({'git': opts.get('git')}, patchfn)
1607 diffopts = self.diffopts({'git': opts.get('git')}, patchfn)
1571 if newuser:
1608 if newuser:
1572 ph.setuser(newuser)
1609 ph.setuser(newuser)
1573 if newdate:
1610 if newdate:
1574 ph.setdate(newdate)
1611 ph.setdate(newdate)
1575 ph.setparent(hex(patchparent))
1612 ph.setparent(hex(patchparent))
1576
1613
1577 # only commit new patch when write is complete
1614 # only commit new patch when write is complete
1578 patchf = self.opener(patchfn, 'w', atomictemp=True)
1615 patchf = self.opener(patchfn, 'w', atomictemp=True)
1579
1616
1580 # update the dirstate in place, strip off the qtip commit
1617 # update the dirstate in place, strip off the qtip commit
1581 # and then commit.
1618 # and then commit.
1582 #
1619 #
1583 # this should really read:
1620 # this should really read:
1584 # mm, dd, aa = repo.status(top, patchparent)[:3]
1621 # mm, dd, aa = repo.status(top, patchparent)[:3]
1585 # but we do it backwards to take advantage of manifest/changelog
1622 # but we do it backwards to take advantage of manifest/changelog
1586 # caching against the next repo.status call
1623 # caching against the next repo.status call
1587 mm, aa, dd = repo.status(patchparent, top)[:3]
1624 mm, aa, dd = repo.status(patchparent, top)[:3]
1588 changes = repo.changelog.read(top)
1625 changes = repo.changelog.read(top)
1589 man = repo.manifest.read(changes[0])
1626 man = repo.manifest.read(changes[0])
1590 aaa = aa[:]
1627 aaa = aa[:]
1591 matchfn = scmutil.match(repo[None], pats, opts)
1628 matchfn = scmutil.match(repo[None], pats, opts)
1592 # in short mode, we only diff the files included in the
1629 # in short mode, we only diff the files included in the
1593 # patch already plus specified files
1630 # patch already plus specified files
1594 if opts.get('short'):
1631 if opts.get('short'):
1595 # if amending a patch, we start with existing
1632 # if amending a patch, we start with existing
1596 # files plus specified files - unfiltered
1633 # files plus specified files - unfiltered
1597 match = scmutil.matchfiles(repo, mm + aa + dd + matchfn.files())
1634 match = scmutil.matchfiles(repo, mm + aa + dd + matchfn.files())
1598 # filter with include/exclude options
1635 # filter with include/exclude options
1599 matchfn = scmutil.match(repo[None], opts=opts)
1636 matchfn = scmutil.match(repo[None], opts=opts)
1600 else:
1637 else:
1601 match = scmutil.matchall(repo)
1638 match = scmutil.matchall(repo)
1602 m, a, r, d = repo.status(match=match)[:4]
1639 m, a, r, d = repo.status(match=match)[:4]
1603 mm = set(mm)
1640 mm = set(mm)
1604 aa = set(aa)
1641 aa = set(aa)
1605 dd = set(dd)
1642 dd = set(dd)
1606
1643
1607 # we might end up with files that were added between
1644 # we might end up with files that were added between
1608 # qtip and the dirstate parent, but then changed in the
1645 # qtip and the dirstate parent, but then changed in the
1609 # local dirstate. in this case, we want them to only
1646 # local dirstate. in this case, we want them to only
1610 # show up in the added section
1647 # show up in the added section
1611 for x in m:
1648 for x in m:
1612 if x not in aa:
1649 if x not in aa:
1613 mm.add(x)
1650 mm.add(x)
1614 # we might end up with files added by the local dirstate that
1651 # we might end up with files added by the local dirstate that
1615 # were deleted by the patch. In this case, they should only
1652 # were deleted by the patch. In this case, they should only
1616 # show up in the changed section.
1653 # show up in the changed section.
1617 for x in a:
1654 for x in a:
1618 if x in dd:
1655 if x in dd:
1619 dd.remove(x)
1656 dd.remove(x)
1620 mm.add(x)
1657 mm.add(x)
1621 else:
1658 else:
1622 aa.add(x)
1659 aa.add(x)
1623 # make sure any files deleted in the local dirstate
1660 # make sure any files deleted in the local dirstate
1624 # are not in the add or change column of the patch
1661 # are not in the add or change column of the patch
1625 forget = []
1662 forget = []
1626 for x in d + r:
1663 for x in d + r:
1627 if x in aa:
1664 if x in aa:
1628 aa.remove(x)
1665 aa.remove(x)
1629 forget.append(x)
1666 forget.append(x)
1630 continue
1667 continue
1631 else:
1668 else:
1632 mm.discard(x)
1669 mm.discard(x)
1633 dd.add(x)
1670 dd.add(x)
1634
1671
1635 m = list(mm)
1672 m = list(mm)
1636 r = list(dd)
1673 r = list(dd)
1637 a = list(aa)
1674 a = list(aa)
1638
1675
1639 # create 'match' that includes the files to be recommitted.
1676 # create 'match' that includes the files to be recommitted.
1640 # apply matchfn via repo.status to ensure correct case handling.
1677 # apply matchfn via repo.status to ensure correct case handling.
1641 cm, ca, cr, cd = repo.status(patchparent, match=matchfn)[:4]
1678 cm, ca, cr, cd = repo.status(patchparent, match=matchfn)[:4]
1642 allmatches = set(cm + ca + cr + cd)
1679 allmatches = set(cm + ca + cr + cd)
1643 refreshchanges = [x.intersection(allmatches) for x in (mm, aa, dd)]
1680 refreshchanges = [x.intersection(allmatches) for x in (mm, aa, dd)]
1644
1681
1645 files = set(inclsubs)
1682 files = set(inclsubs)
1646 for x in refreshchanges:
1683 for x in refreshchanges:
1647 files.update(x)
1684 files.update(x)
1648 match = scmutil.matchfiles(repo, files)
1685 match = scmutil.matchfiles(repo, files)
1649
1686
1650 bmlist = repo[top].bookmarks()
1687 bmlist = repo[top].bookmarks()
1651
1688
1652 try:
1689 try:
1653 repo.dirstate.beginparentchange()
1690 repo.dirstate.beginparentchange()
1654 if diffopts.git or diffopts.upgrade:
1691 if diffopts.git or diffopts.upgrade:
1655 copies = {}
1692 copies = {}
1656 for dst in a:
1693 for dst in a:
1657 src = repo.dirstate.copied(dst)
1694 src = repo.dirstate.copied(dst)
1658 # during qfold, the source file for copies may
1695 # during qfold, the source file for copies may
1659 # be removed. Treat this as a simple add.
1696 # be removed. Treat this as a simple add.
1660 if src is not None and src in repo.dirstate:
1697 if src is not None and src in repo.dirstate:
1661 copies.setdefault(src, []).append(dst)
1698 copies.setdefault(src, []).append(dst)
1662 repo.dirstate.add(dst)
1699 repo.dirstate.add(dst)
1663 # remember the copies between patchparent and qtip
1700 # remember the copies between patchparent and qtip
1664 for dst in aaa:
1701 for dst in aaa:
1665 f = repo.file(dst)
1702 f = repo.file(dst)
1666 src = f.renamed(man[dst])
1703 src = f.renamed(man[dst])
1667 if src:
1704 if src:
1668 copies.setdefault(src[0], []).extend(
1705 copies.setdefault(src[0], []).extend(
1669 copies.get(dst, []))
1706 copies.get(dst, []))
1670 if dst in a:
1707 if dst in a:
1671 copies[src[0]].append(dst)
1708 copies[src[0]].append(dst)
1672 # we can't copy a file created by the patch itself
1709 # we can't copy a file created by the patch itself
1673 if dst in copies:
1710 if dst in copies:
1674 del copies[dst]
1711 del copies[dst]
1675 for src, dsts in copies.iteritems():
1712 for src, dsts in copies.iteritems():
1676 for dst in dsts:
1713 for dst in dsts:
1677 repo.dirstate.copy(src, dst)
1714 repo.dirstate.copy(src, dst)
1678 else:
1715 else:
1679 for dst in a:
1716 for dst in a:
1680 repo.dirstate.add(dst)
1717 repo.dirstate.add(dst)
1681 # Drop useless copy information
1718 # Drop useless copy information
1682 for f in list(repo.dirstate.copies()):
1719 for f in list(repo.dirstate.copies()):
1683 repo.dirstate.copy(None, f)
1720 repo.dirstate.copy(None, f)
1684 for f in r:
1721 for f in r:
1685 repo.dirstate.remove(f)
1722 repo.dirstate.remove(f)
1686 # if the patch excludes a modified file, mark that
1723 # if the patch excludes a modified file, mark that
1687 # file with mtime=0 so status can see it.
1724 # file with mtime=0 so status can see it.
1688 mm = []
1725 mm = []
1689 for i in xrange(len(m) - 1, -1, -1):
1726 for i in xrange(len(m) - 1, -1, -1):
1690 if not matchfn(m[i]):
1727 if not matchfn(m[i]):
1691 mm.append(m[i])
1728 mm.append(m[i])
1692 del m[i]
1729 del m[i]
1693 for f in m:
1730 for f in m:
1694 repo.dirstate.normal(f)
1731 repo.dirstate.normal(f)
1695 for f in mm:
1732 for f in mm:
1696 repo.dirstate.normallookup(f)
1733 repo.dirstate.normallookup(f)
1697 for f in forget:
1734 for f in forget:
1698 repo.dirstate.drop(f)
1735 repo.dirstate.drop(f)
1699
1736
1700 user = ph.user or changes[1]
1737 user = ph.user or changes[1]
1701
1738
1702 oldphase = repo[top].phase()
1739 oldphase = repo[top].phase()
1703
1740
1704 # assumes strip can roll itself back if interrupted
1741 # assumes strip can roll itself back if interrupted
1705 repo.setparents(*cparents)
1742 repo.setparents(*cparents)
1706 repo.dirstate.endparentchange()
1743 repo.dirstate.endparentchange()
1707 self.applied.pop()
1744 self.applied.pop()
1708 self.applieddirty = True
1745 self.applieddirty = True
1709 strip(self.ui, repo, [top], update=False, backup=False)
1746 strip(self.ui, repo, [top], update=False, backup=False)
1710 except: # re-raises
1747 except: # re-raises
1711 repo.dirstate.invalidate()
1748 repo.dirstate.invalidate()
1712 raise
1749 raise
1713
1750
1714 try:
1751 try:
1715 # might be nice to attempt to roll back strip after this
1752 # might be nice to attempt to roll back strip after this
1716
1753
1717 defaultmsg = "[mq]: %s" % patchfn
1754 defaultmsg = "[mq]: %s" % patchfn
1718 editor = cmdutil.getcommiteditor(editform=editform)
1755 editor = cmdutil.getcommiteditor(editform=editform)
1719 if edit:
1756 if edit:
1720 def finishdesc(desc):
1757 def finishdesc(desc):
1721 if desc.rstrip():
1758 if desc.rstrip():
1722 ph.setmessage(desc)
1759 ph.setmessage(desc)
1723 return desc
1760 return desc
1724 return defaultmsg
1761 return defaultmsg
1725 # i18n: this message is shown in editor with "HG: " prefix
1762 # i18n: this message is shown in editor with "HG: " prefix
1726 extramsg = _('Leave message empty to use default message.')
1763 extramsg = _('Leave message empty to use default message.')
1727 editor = cmdutil.getcommiteditor(finishdesc=finishdesc,
1764 editor = cmdutil.getcommiteditor(finishdesc=finishdesc,
1728 extramsg=extramsg,
1765 extramsg=extramsg,
1729 editform=editform)
1766 editform=editform)
1730 message = msg or "\n".join(ph.message)
1767 message = msg or "\n".join(ph.message)
1731 elif not msg:
1768 elif not msg:
1732 if not ph.message:
1769 if not ph.message:
1733 message = defaultmsg
1770 message = defaultmsg
1734 else:
1771 else:
1735 message = "\n".join(ph.message)
1772 message = "\n".join(ph.message)
1736 else:
1773 else:
1737 message = msg
1774 message = msg
1738 ph.setmessage(msg)
1775 ph.setmessage(msg)
1739
1776
1740 # Ensure we create a new changeset in the same phase than
1777 # Ensure we create a new changeset in the same phase than
1741 # the old one.
1778 # the old one.
1742 n = newcommit(repo, oldphase, message, user, ph.date,
1779 n = newcommit(repo, oldphase, message, user, ph.date,
1743 match=match, force=True, editor=editor)
1780 match=match, force=True, editor=editor)
1744 # only write patch after a successful commit
1781 # only write patch after a successful commit
1745 c = [list(x) for x in refreshchanges]
1782 c = [list(x) for x in refreshchanges]
1746 if inclsubs:
1783 if inclsubs:
1747 self.putsubstate2changes(substatestate, c)
1784 self.putsubstate2changes(substatestate, c)
1748 chunks = patchmod.diff(repo, patchparent,
1785 chunks = patchmod.diff(repo, patchparent,
1749 changes=c, opts=diffopts)
1786 changes=c, opts=diffopts)
1750 comments = str(ph)
1787 comments = str(ph)
1751 if comments:
1788 if comments:
1752 patchf.write(comments)
1789 patchf.write(comments)
1753 for chunk in chunks:
1790 for chunk in chunks:
1754 patchf.write(chunk)
1791 patchf.write(chunk)
1755 patchf.close()
1792 patchf.close()
1756
1793
1757 marks = repo._bookmarks
1794 marks = repo._bookmarks
1758 for bm in bmlist:
1795 for bm in bmlist:
1759 marks[bm] = n
1796 marks[bm] = n
1760 marks.write()
1797 marks.write()
1761
1798
1762 self.applied.append(statusentry(n, patchfn))
1799 self.applied.append(statusentry(n, patchfn))
1763 except: # re-raises
1800 except: # re-raises
1764 ctx = repo[cparents[0]]
1801 ctx = repo[cparents[0]]
1765 repo.dirstate.rebuild(ctx.node(), ctx.manifest())
1802 repo.dirstate.rebuild(ctx.node(), ctx.manifest())
1766 self.savedirty()
1803 self.savedirty()
1767 self.ui.warn(_('refresh interrupted while patch was popped! '
1804 self.ui.warn(_('refresh interrupted while patch was popped! '
1768 '(revert --all, qpush to recover)\n'))
1805 '(revert --all, qpush to recover)\n'))
1769 raise
1806 raise
1770 finally:
1807 finally:
1771 wlock.release()
1808 wlock.release()
1772 self.removeundo(repo)
1809 self.removeundo(repo)
1773
1810
1774 def init(self, repo, create=False):
1811 def init(self, repo, create=False):
1775 if not create and os.path.isdir(self.path):
1812 if not create and os.path.isdir(self.path):
1776 raise util.Abort(_("patch queue directory already exists"))
1813 raise util.Abort(_("patch queue directory already exists"))
1777 try:
1814 try:
1778 os.mkdir(self.path)
1815 os.mkdir(self.path)
1779 except OSError, inst:
1816 except OSError, inst:
1780 if inst.errno != errno.EEXIST or not create:
1817 if inst.errno != errno.EEXIST or not create:
1781 raise
1818 raise
1782 if create:
1819 if create:
1783 return self.qrepo(create=True)
1820 return self.qrepo(create=True)
1784
1821
1785 def unapplied(self, repo, patch=None):
1822 def unapplied(self, repo, patch=None):
1786 if patch and patch not in self.series:
1823 if patch and patch not in self.series:
1787 raise util.Abort(_("patch %s is not in series file") % patch)
1824 raise util.Abort(_("patch %s is not in series file") % patch)
1788 if not patch:
1825 if not patch:
1789 start = self.seriesend()
1826 start = self.seriesend()
1790 else:
1827 else:
1791 start = self.series.index(patch) + 1
1828 start = self.series.index(patch) + 1
1792 unapplied = []
1829 unapplied = []
1793 for i in xrange(start, len(self.series)):
1830 for i in xrange(start, len(self.series)):
1794 pushable, reason = self.pushable(i)
1831 pushable, reason = self.pushable(i)
1795 if pushable:
1832 if pushable:
1796 unapplied.append((i, self.series[i]))
1833 unapplied.append((i, self.series[i]))
1797 self.explainpushable(i)
1834 self.explainpushable(i)
1798 return unapplied
1835 return unapplied
1799
1836
1800 def qseries(self, repo, missing=None, start=0, length=None, status=None,
1837 def qseries(self, repo, missing=None, start=0, length=None, status=None,
1801 summary=False):
1838 summary=False):
1802 def displayname(pfx, patchname, state):
1839 def displayname(pfx, patchname, state):
1803 if pfx:
1840 if pfx:
1804 self.ui.write(pfx)
1841 self.ui.write(pfx)
1805 if summary:
1842 if summary:
1806 ph = patchheader(self.join(patchname), self.plainmode)
1843 ph = patchheader(self.join(patchname), self.plainmode)
1807 msg = ph.message and ph.message[0] or ''
1844 msg = ph.message and ph.message[0] or ''
1808 if self.ui.formatted():
1845 if self.ui.formatted():
1809 width = self.ui.termwidth() - len(pfx) - len(patchname) - 2
1846 width = self.ui.termwidth() - len(pfx) - len(patchname) - 2
1810 if width > 0:
1847 if width > 0:
1811 msg = util.ellipsis(msg, width)
1848 msg = util.ellipsis(msg, width)
1812 else:
1849 else:
1813 msg = ''
1850 msg = ''
1814 self.ui.write(patchname, label='qseries.' + state)
1851 self.ui.write(patchname, label='qseries.' + state)
1815 self.ui.write(': ')
1852 self.ui.write(': ')
1816 self.ui.write(msg, label='qseries.message.' + state)
1853 self.ui.write(msg, label='qseries.message.' + state)
1817 else:
1854 else:
1818 self.ui.write(patchname, label='qseries.' + state)
1855 self.ui.write(patchname, label='qseries.' + state)
1819 self.ui.write('\n')
1856 self.ui.write('\n')
1820
1857
1821 applied = set([p.name for p in self.applied])
1858 applied = set([p.name for p in self.applied])
1822 if length is None:
1859 if length is None:
1823 length = len(self.series) - start
1860 length = len(self.series) - start
1824 if not missing:
1861 if not missing:
1825 if self.ui.verbose:
1862 if self.ui.verbose:
1826 idxwidth = len(str(start + length - 1))
1863 idxwidth = len(str(start + length - 1))
1827 for i in xrange(start, start + length):
1864 for i in xrange(start, start + length):
1828 patch = self.series[i]
1865 patch = self.series[i]
1829 if patch in applied:
1866 if patch in applied:
1830 char, state = 'A', 'applied'
1867 char, state = 'A', 'applied'
1831 elif self.pushable(i)[0]:
1868 elif self.pushable(i)[0]:
1832 char, state = 'U', 'unapplied'
1869 char, state = 'U', 'unapplied'
1833 else:
1870 else:
1834 char, state = 'G', 'guarded'
1871 char, state = 'G', 'guarded'
1835 pfx = ''
1872 pfx = ''
1836 if self.ui.verbose:
1873 if self.ui.verbose:
1837 pfx = '%*d %s ' % (idxwidth, i, char)
1874 pfx = '%*d %s ' % (idxwidth, i, char)
1838 elif status and status != char:
1875 elif status and status != char:
1839 continue
1876 continue
1840 displayname(pfx, patch, state)
1877 displayname(pfx, patch, state)
1841 else:
1878 else:
1842 msng_list = []
1879 msng_list = []
1843 for root, dirs, files in os.walk(self.path):
1880 for root, dirs, files in os.walk(self.path):
1844 d = root[len(self.path) + 1:]
1881 d = root[len(self.path) + 1:]
1845 for f in files:
1882 for f in files:
1846 fl = os.path.join(d, f)
1883 fl = os.path.join(d, f)
1847 if (fl not in self.series and
1884 if (fl not in self.series and
1848 fl not in (self.statuspath, self.seriespath,
1885 fl not in (self.statuspath, self.seriespath,
1849 self.guardspath)
1886 self.guardspath)
1850 and not fl.startswith('.')):
1887 and not fl.startswith('.')):
1851 msng_list.append(fl)
1888 msng_list.append(fl)
1852 for x in sorted(msng_list):
1889 for x in sorted(msng_list):
1853 pfx = self.ui.verbose and ('D ') or ''
1890 pfx = self.ui.verbose and ('D ') or ''
1854 displayname(pfx, x, 'missing')
1891 displayname(pfx, x, 'missing')
1855
1892
1856 def issaveline(self, l):
1893 def issaveline(self, l):
1857 if l.name == '.hg.patches.save.line':
1894 if l.name == '.hg.patches.save.line':
1858 return True
1895 return True
1859
1896
1860 def qrepo(self, create=False):
1897 def qrepo(self, create=False):
1861 ui = self.baseui.copy()
1898 ui = self.baseui.copy()
1862 if create or os.path.isdir(self.join(".hg")):
1899 if create or os.path.isdir(self.join(".hg")):
1863 return hg.repository(ui, path=self.path, create=create)
1900 return hg.repository(ui, path=self.path, create=create)
1864
1901
1865 def restore(self, repo, rev, delete=None, qupdate=None):
1902 def restore(self, repo, rev, delete=None, qupdate=None):
1866 desc = repo[rev].description().strip()
1903 desc = repo[rev].description().strip()
1867 lines = desc.splitlines()
1904 lines = desc.splitlines()
1868 i = 0
1905 i = 0
1869 datastart = None
1906 datastart = None
1870 series = []
1907 series = []
1871 applied = []
1908 applied = []
1872 qpp = None
1909 qpp = None
1873 for i, line in enumerate(lines):
1910 for i, line in enumerate(lines):
1874 if line == 'Patch Data:':
1911 if line == 'Patch Data:':
1875 datastart = i + 1
1912 datastart = i + 1
1876 elif line.startswith('Dirstate:'):
1913 elif line.startswith('Dirstate:'):
1877 l = line.rstrip()
1914 l = line.rstrip()
1878 l = l[10:].split(' ')
1915 l = l[10:].split(' ')
1879 qpp = [bin(x) for x in l]
1916 qpp = [bin(x) for x in l]
1880 elif datastart is not None:
1917 elif datastart is not None:
1881 l = line.rstrip()
1918 l = line.rstrip()
1882 n, name = l.split(':', 1)
1919 n, name = l.split(':', 1)
1883 if n:
1920 if n:
1884 applied.append(statusentry(bin(n), name))
1921 applied.append(statusentry(bin(n), name))
1885 else:
1922 else:
1886 series.append(l)
1923 series.append(l)
1887 if datastart is None:
1924 if datastart is None:
1888 self.ui.warn(_("no saved patch data found\n"))
1925 self.ui.warn(_("no saved patch data found\n"))
1889 return 1
1926 return 1
1890 self.ui.warn(_("restoring status: %s\n") % lines[0])
1927 self.ui.warn(_("restoring status: %s\n") % lines[0])
1891 self.fullseries = series
1928 self.fullseries = series
1892 self.applied = applied
1929 self.applied = applied
1893 self.parseseries()
1930 self.parseseries()
1894 self.seriesdirty = True
1931 self.seriesdirty = True
1895 self.applieddirty = True
1932 self.applieddirty = True
1896 heads = repo.changelog.heads()
1933 heads = repo.changelog.heads()
1897 if delete:
1934 if delete:
1898 if rev not in heads:
1935 if rev not in heads:
1899 self.ui.warn(_("save entry has children, leaving it alone\n"))
1936 self.ui.warn(_("save entry has children, leaving it alone\n"))
1900 else:
1937 else:
1901 self.ui.warn(_("removing save entry %s\n") % short(rev))
1938 self.ui.warn(_("removing save entry %s\n") % short(rev))
1902 pp = repo.dirstate.parents()
1939 pp = repo.dirstate.parents()
1903 if rev in pp:
1940 if rev in pp:
1904 update = True
1941 update = True
1905 else:
1942 else:
1906 update = False
1943 update = False
1907 strip(self.ui, repo, [rev], update=update, backup=False)
1944 strip(self.ui, repo, [rev], update=update, backup=False)
1908 if qpp:
1945 if qpp:
1909 self.ui.warn(_("saved queue repository parents: %s %s\n") %
1946 self.ui.warn(_("saved queue repository parents: %s %s\n") %
1910 (short(qpp[0]), short(qpp[1])))
1947 (short(qpp[0]), short(qpp[1])))
1911 if qupdate:
1948 if qupdate:
1912 self.ui.status(_("updating queue directory\n"))
1949 self.ui.status(_("updating queue directory\n"))
1913 r = self.qrepo()
1950 r = self.qrepo()
1914 if not r:
1951 if not r:
1915 self.ui.warn(_("unable to load queue repository\n"))
1952 self.ui.warn(_("unable to load queue repository\n"))
1916 return 1
1953 return 1
1917 hg.clean(r, qpp[0])
1954 hg.clean(r, qpp[0])
1918
1955
1919 def save(self, repo, msg=None):
1956 def save(self, repo, msg=None):
1920 if not self.applied:
1957 if not self.applied:
1921 self.ui.warn(_("save: no patches applied, exiting\n"))
1958 self.ui.warn(_("save: no patches applied, exiting\n"))
1922 return 1
1959 return 1
1923 if self.issaveline(self.applied[-1]):
1960 if self.issaveline(self.applied[-1]):
1924 self.ui.warn(_("status is already saved\n"))
1961 self.ui.warn(_("status is already saved\n"))
1925 return 1
1962 return 1
1926
1963
1927 if not msg:
1964 if not msg:
1928 msg = _("hg patches saved state")
1965 msg = _("hg patches saved state")
1929 else:
1966 else:
1930 msg = "hg patches: " + msg.rstrip('\r\n')
1967 msg = "hg patches: " + msg.rstrip('\r\n')
1931 r = self.qrepo()
1968 r = self.qrepo()
1932 if r:
1969 if r:
1933 pp = r.dirstate.parents()
1970 pp = r.dirstate.parents()
1934 msg += "\nDirstate: %s %s" % (hex(pp[0]), hex(pp[1]))
1971 msg += "\nDirstate: %s %s" % (hex(pp[0]), hex(pp[1]))
1935 msg += "\n\nPatch Data:\n"
1972 msg += "\n\nPatch Data:\n"
1936 msg += ''.join('%s\n' % x for x in self.applied)
1973 msg += ''.join('%s\n' % x for x in self.applied)
1937 msg += ''.join(':%s\n' % x for x in self.fullseries)
1974 msg += ''.join(':%s\n' % x for x in self.fullseries)
1938 n = repo.commit(msg, force=True)
1975 n = repo.commit(msg, force=True)
1939 if not n:
1976 if not n:
1940 self.ui.warn(_("repo commit failed\n"))
1977 self.ui.warn(_("repo commit failed\n"))
1941 return 1
1978 return 1
1942 self.applied.append(statusentry(n, '.hg.patches.save.line'))
1979 self.applied.append(statusentry(n, '.hg.patches.save.line'))
1943 self.applieddirty = True
1980 self.applieddirty = True
1944 self.removeundo(repo)
1981 self.removeundo(repo)
1945
1982
1946 def fullseriesend(self):
1983 def fullseriesend(self):
1947 if self.applied:
1984 if self.applied:
1948 p = self.applied[-1].name
1985 p = self.applied[-1].name
1949 end = self.findseries(p)
1986 end = self.findseries(p)
1950 if end is None:
1987 if end is None:
1951 return len(self.fullseries)
1988 return len(self.fullseries)
1952 return end + 1
1989 return end + 1
1953 return 0
1990 return 0
1954
1991
1955 def seriesend(self, all_patches=False):
1992 def seriesend(self, all_patches=False):
1956 """If all_patches is False, return the index of the next pushable patch
1993 """If all_patches is False, return the index of the next pushable patch
1957 in the series, or the series length. If all_patches is True, return the
1994 in the series, or the series length. If all_patches is True, return the
1958 index of the first patch past the last applied one.
1995 index of the first patch past the last applied one.
1959 """
1996 """
1960 end = 0
1997 end = 0
1961 def nextpatch(start):
1998 def nextpatch(start):
1962 if all_patches or start >= len(self.series):
1999 if all_patches or start >= len(self.series):
1963 return start
2000 return start
1964 for i in xrange(start, len(self.series)):
2001 for i in xrange(start, len(self.series)):
1965 p, reason = self.pushable(i)
2002 p, reason = self.pushable(i)
1966 if p:
2003 if p:
1967 return i
2004 return i
1968 self.explainpushable(i)
2005 self.explainpushable(i)
1969 return len(self.series)
2006 return len(self.series)
1970 if self.applied:
2007 if self.applied:
1971 p = self.applied[-1].name
2008 p = self.applied[-1].name
1972 try:
2009 try:
1973 end = self.series.index(p)
2010 end = self.series.index(p)
1974 except ValueError:
2011 except ValueError:
1975 return 0
2012 return 0
1976 return nextpatch(end + 1)
2013 return nextpatch(end + 1)
1977 return nextpatch(end)
2014 return nextpatch(end)
1978
2015
1979 def appliedname(self, index):
2016 def appliedname(self, index):
1980 pname = self.applied[index].name
2017 pname = self.applied[index].name
1981 if not self.ui.verbose:
2018 if not self.ui.verbose:
1982 p = pname
2019 p = pname
1983 else:
2020 else:
1984 p = str(self.series.index(pname)) + " " + pname
2021 p = str(self.series.index(pname)) + " " + pname
1985 return p
2022 return p
1986
2023
1987 def qimport(self, repo, files, patchname=None, rev=None, existing=None,
2024 def qimport(self, repo, files, patchname=None, rev=None, existing=None,
1988 force=None, git=False):
2025 force=None, git=False):
1989 def checkseries(patchname):
2026 def checkseries(patchname):
1990 if patchname in self.series:
2027 if patchname in self.series:
1991 raise util.Abort(_('patch %s is already in the series file')
2028 raise util.Abort(_('patch %s is already in the series file')
1992 % patchname)
2029 % patchname)
1993
2030
1994 if rev:
2031 if rev:
1995 if files:
2032 if files:
1996 raise util.Abort(_('option "-r" not valid when importing '
2033 raise util.Abort(_('option "-r" not valid when importing '
1997 'files'))
2034 'files'))
1998 rev = scmutil.revrange(repo, rev)
2035 rev = scmutil.revrange(repo, rev)
1999 rev.sort(reverse=True)
2036 rev.sort(reverse=True)
2000 elif not files:
2037 elif not files:
2001 raise util.Abort(_('no files or revisions specified'))
2038 raise util.Abort(_('no files or revisions specified'))
2002 if (len(files) > 1 or len(rev) > 1) and patchname:
2039 if (len(files) > 1 or len(rev) > 1) and patchname:
2003 raise util.Abort(_('option "-n" not valid when importing multiple '
2040 raise util.Abort(_('option "-n" not valid when importing multiple '
2004 'patches'))
2041 'patches'))
2005 imported = []
2042 imported = []
2006 if rev:
2043 if rev:
2007 # If mq patches are applied, we can only import revisions
2044 # If mq patches are applied, we can only import revisions
2008 # that form a linear path to qbase.
2045 # that form a linear path to qbase.
2009 # Otherwise, they should form a linear path to a head.
2046 # Otherwise, they should form a linear path to a head.
2010 heads = repo.changelog.heads(repo.changelog.node(rev.first()))
2047 heads = repo.changelog.heads(repo.changelog.node(rev.first()))
2011 if len(heads) > 1:
2048 if len(heads) > 1:
2012 raise util.Abort(_('revision %d is the root of more than one '
2049 raise util.Abort(_('revision %d is the root of more than one '
2013 'branch') % rev.last())
2050 'branch') % rev.last())
2014 if self.applied:
2051 if self.applied:
2015 base = repo.changelog.node(rev.first())
2052 base = repo.changelog.node(rev.first())
2016 if base in [n.node for n in self.applied]:
2053 if base in [n.node for n in self.applied]:
2017 raise util.Abort(_('revision %d is already managed')
2054 raise util.Abort(_('revision %d is already managed')
2018 % rev.first())
2055 % rev.first())
2019 if heads != [self.applied[-1].node]:
2056 if heads != [self.applied[-1].node]:
2020 raise util.Abort(_('revision %d is not the parent of '
2057 raise util.Abort(_('revision %d is not the parent of '
2021 'the queue') % rev.first())
2058 'the queue') % rev.first())
2022 base = repo.changelog.rev(self.applied[0].node)
2059 base = repo.changelog.rev(self.applied[0].node)
2023 lastparent = repo.changelog.parentrevs(base)[0]
2060 lastparent = repo.changelog.parentrevs(base)[0]
2024 else:
2061 else:
2025 if heads != [repo.changelog.node(rev.first())]:
2062 if heads != [repo.changelog.node(rev.first())]:
2026 raise util.Abort(_('revision %d has unmanaged children')
2063 raise util.Abort(_('revision %d has unmanaged children')
2027 % rev.first())
2064 % rev.first())
2028 lastparent = None
2065 lastparent = None
2029
2066
2030 diffopts = self.diffopts({'git': git})
2067 diffopts = self.diffopts({'git': git})
2031 tr = repo.transaction('qimport')
2068 tr = repo.transaction('qimport')
2032 try:
2069 try:
2033 for r in rev:
2070 for r in rev:
2034 if not repo[r].mutable():
2071 if not repo[r].mutable():
2035 raise util.Abort(_('revision %d is not mutable') % r,
2072 raise util.Abort(_('revision %d is not mutable') % r,
2036 hint=_('see "hg help phases" '
2073 hint=_('see "hg help phases" '
2037 'for details'))
2074 'for details'))
2038 p1, p2 = repo.changelog.parentrevs(r)
2075 p1, p2 = repo.changelog.parentrevs(r)
2039 n = repo.changelog.node(r)
2076 n = repo.changelog.node(r)
2040 if p2 != nullrev:
2077 if p2 != nullrev:
2041 raise util.Abort(_('cannot import merge revision %d')
2078 raise util.Abort(_('cannot import merge revision %d')
2042 % r)
2079 % r)
2043 if lastparent and lastparent != r:
2080 if lastparent and lastparent != r:
2044 raise util.Abort(_('revision %d is not the parent of '
2081 raise util.Abort(_('revision %d is not the parent of '
2045 '%d')
2082 '%d')
2046 % (r, lastparent))
2083 % (r, lastparent))
2047 lastparent = p1
2084 lastparent = p1
2048
2085
2049 if not patchname:
2086 if not patchname:
2050 patchname = normname('%d.diff' % r)
2087 patchname = normname('%d.diff' % r)
2051 checkseries(patchname)
2088 checkseries(patchname)
2052 self.checkpatchname(patchname, force)
2089 self.checkpatchname(patchname, force)
2053 self.fullseries.insert(0, patchname)
2090 self.fullseries.insert(0, patchname)
2054
2091
2055 patchf = self.opener(patchname, "w")
2092 patchf = self.opener(patchname, "w")
2056 cmdutil.export(repo, [n], fp=patchf, opts=diffopts)
2093 cmdutil.export(repo, [n], fp=patchf, opts=diffopts)
2057 patchf.close()
2094 patchf.close()
2058
2095
2059 se = statusentry(n, patchname)
2096 se = statusentry(n, patchname)
2060 self.applied.insert(0, se)
2097 self.applied.insert(0, se)
2061
2098
2062 self.added.append(patchname)
2099 self.added.append(patchname)
2063 imported.append(patchname)
2100 imported.append(patchname)
2064 patchname = None
2101 patchname = None
2065 if rev and repo.ui.configbool('mq', 'secret', False):
2102 if rev and repo.ui.configbool('mq', 'secret', False):
2066 # if we added anything with --rev, move the secret root
2103 # if we added anything with --rev, move the secret root
2067 phases.retractboundary(repo, tr, phases.secret, [n])
2104 phases.retractboundary(repo, tr, phases.secret, [n])
2068 self.parseseries()
2105 self.parseseries()
2069 self.applieddirty = True
2106 self.applieddirty = True
2070 self.seriesdirty = True
2107 self.seriesdirty = True
2071 tr.close()
2108 tr.close()
2072 finally:
2109 finally:
2073 tr.release()
2110 tr.release()
2074
2111
2075 for i, filename in enumerate(files):
2112 for i, filename in enumerate(files):
2076 if existing:
2113 if existing:
2077 if filename == '-':
2114 if filename == '-':
2078 raise util.Abort(_('-e is incompatible with import from -'))
2115 raise util.Abort(_('-e is incompatible with import from -'))
2079 filename = normname(filename)
2116 filename = normname(filename)
2080 self.checkreservedname(filename)
2117 self.checkreservedname(filename)
2081 if util.url(filename).islocal():
2118 if util.url(filename).islocal():
2082 originpath = self.join(filename)
2119 originpath = self.join(filename)
2083 if not os.path.isfile(originpath):
2120 if not os.path.isfile(originpath):
2084 raise util.Abort(
2121 raise util.Abort(
2085 _("patch %s does not exist") % filename)
2122 _("patch %s does not exist") % filename)
2086
2123
2087 if patchname:
2124 if patchname:
2088 self.checkpatchname(patchname, force)
2125 self.checkpatchname(patchname, force)
2089
2126
2090 self.ui.write(_('renaming %s to %s\n')
2127 self.ui.write(_('renaming %s to %s\n')
2091 % (filename, patchname))
2128 % (filename, patchname))
2092 util.rename(originpath, self.join(patchname))
2129 util.rename(originpath, self.join(patchname))
2093 else:
2130 else:
2094 patchname = filename
2131 patchname = filename
2095
2132
2096 else:
2133 else:
2097 if filename == '-' and not patchname:
2134 if filename == '-' and not patchname:
2098 raise util.Abort(_('need --name to import a patch from -'))
2135 raise util.Abort(_('need --name to import a patch from -'))
2099 elif not patchname:
2136 elif not patchname:
2100 patchname = normname(os.path.basename(filename.rstrip('/')))
2137 patchname = normname(os.path.basename(filename.rstrip('/')))
2101 self.checkpatchname(patchname, force)
2138 self.checkpatchname(patchname, force)
2102 try:
2139 try:
2103 if filename == '-':
2140 if filename == '-':
2104 text = self.ui.fin.read()
2141 text = self.ui.fin.read()
2105 else:
2142 else:
2106 fp = hg.openpath(self.ui, filename)
2143 fp = hg.openpath(self.ui, filename)
2107 text = fp.read()
2144 text = fp.read()
2108 fp.close()
2145 fp.close()
2109 except (OSError, IOError):
2146 except (OSError, IOError):
2110 raise util.Abort(_("unable to read file %s") % filename)
2147 raise util.Abort(_("unable to read file %s") % filename)
2111 patchf = self.opener(patchname, "w")
2148 patchf = self.opener(patchname, "w")
2112 patchf.write(text)
2149 patchf.write(text)
2113 patchf.close()
2150 patchf.close()
2114 if not force:
2151 if not force:
2115 checkseries(patchname)
2152 checkseries(patchname)
2116 if patchname not in self.series:
2153 if patchname not in self.series:
2117 index = self.fullseriesend() + i
2154 index = self.fullseriesend() + i
2118 self.fullseries[index:index] = [patchname]
2155 self.fullseries[index:index] = [patchname]
2119 self.parseseries()
2156 self.parseseries()
2120 self.seriesdirty = True
2157 self.seriesdirty = True
2121 self.ui.warn(_("adding %s to series file\n") % patchname)
2158 self.ui.warn(_("adding %s to series file\n") % patchname)
2122 self.added.append(patchname)
2159 self.added.append(patchname)
2123 imported.append(patchname)
2160 imported.append(patchname)
2124 patchname = None
2161 patchname = None
2125
2162
2126 self.removeundo(repo)
2163 self.removeundo(repo)
2127 return imported
2164 return imported
2128
2165
2129 def fixkeepchangesopts(ui, opts):
2166 def fixkeepchangesopts(ui, opts):
2130 if (not ui.configbool('mq', 'keepchanges') or opts.get('force')
2167 if (not ui.configbool('mq', 'keepchanges') or opts.get('force')
2131 or opts.get('exact')):
2168 or opts.get('exact')):
2132 return opts
2169 return opts
2133 opts = dict(opts)
2170 opts = dict(opts)
2134 opts['keep_changes'] = True
2171 opts['keep_changes'] = True
2135 return opts
2172 return opts
2136
2173
2137 @command("qdelete|qremove|qrm",
2174 @command("qdelete|qremove|qrm",
2138 [('k', 'keep', None, _('keep patch file')),
2175 [('k', 'keep', None, _('keep patch file')),
2139 ('r', 'rev', [],
2176 ('r', 'rev', [],
2140 _('stop managing a revision (DEPRECATED)'), _('REV'))],
2177 _('stop managing a revision (DEPRECATED)'), _('REV'))],
2141 _('hg qdelete [-k] [PATCH]...'))
2178 _('hg qdelete [-k] [PATCH]...'))
2142 def delete(ui, repo, *patches, **opts):
2179 def delete(ui, repo, *patches, **opts):
2143 """remove patches from queue
2180 """remove patches from queue
2144
2181
2145 The patches must not be applied, and at least one patch is required. Exact
2182 The patches must not be applied, and at least one patch is required. Exact
2146 patch identifiers must be given. With -k/--keep, the patch files are
2183 patch identifiers must be given. With -k/--keep, the patch files are
2147 preserved in the patch directory.
2184 preserved in the patch directory.
2148
2185
2149 To stop managing a patch and move it into permanent history,
2186 To stop managing a patch and move it into permanent history,
2150 use the :hg:`qfinish` command."""
2187 use the :hg:`qfinish` command."""
2151 q = repo.mq
2188 q = repo.mq
2152 q.delete(repo, patches, opts)
2189 q.delete(repo, patches, opts)
2153 q.savedirty()
2190 q.savedirty()
2154 return 0
2191 return 0
2155
2192
2156 @command("qapplied",
2193 @command("qapplied",
2157 [('1', 'last', None, _('show only the preceding applied patch'))
2194 [('1', 'last', None, _('show only the preceding applied patch'))
2158 ] + seriesopts,
2195 ] + seriesopts,
2159 _('hg qapplied [-1] [-s] [PATCH]'))
2196 _('hg qapplied [-1] [-s] [PATCH]'))
2160 def applied(ui, repo, patch=None, **opts):
2197 def applied(ui, repo, patch=None, **opts):
2161 """print the patches already applied
2198 """print the patches already applied
2162
2199
2163 Returns 0 on success."""
2200 Returns 0 on success."""
2164
2201
2165 q = repo.mq
2202 q = repo.mq
2166
2203
2167 if patch:
2204 if patch:
2168 if patch not in q.series:
2205 if patch not in q.series:
2169 raise util.Abort(_("patch %s is not in series file") % patch)
2206 raise util.Abort(_("patch %s is not in series file") % patch)
2170 end = q.series.index(patch) + 1
2207 end = q.series.index(patch) + 1
2171 else:
2208 else:
2172 end = q.seriesend(True)
2209 end = q.seriesend(True)
2173
2210
2174 if opts.get('last') and not end:
2211 if opts.get('last') and not end:
2175 ui.write(_("no patches applied\n"))
2212 ui.write(_("no patches applied\n"))
2176 return 1
2213 return 1
2177 elif opts.get('last') and end == 1:
2214 elif opts.get('last') and end == 1:
2178 ui.write(_("only one patch applied\n"))
2215 ui.write(_("only one patch applied\n"))
2179 return 1
2216 return 1
2180 elif opts.get('last'):
2217 elif opts.get('last'):
2181 start = end - 2
2218 start = end - 2
2182 end = 1
2219 end = 1
2183 else:
2220 else:
2184 start = 0
2221 start = 0
2185
2222
2186 q.qseries(repo, length=end, start=start, status='A',
2223 q.qseries(repo, length=end, start=start, status='A',
2187 summary=opts.get('summary'))
2224 summary=opts.get('summary'))
2188
2225
2189
2226
2190 @command("qunapplied",
2227 @command("qunapplied",
2191 [('1', 'first', None, _('show only the first patch'))] + seriesopts,
2228 [('1', 'first', None, _('show only the first patch'))] + seriesopts,
2192 _('hg qunapplied [-1] [-s] [PATCH]'))
2229 _('hg qunapplied [-1] [-s] [PATCH]'))
2193 def unapplied(ui, repo, patch=None, **opts):
2230 def unapplied(ui, repo, patch=None, **opts):
2194 """print the patches not yet applied
2231 """print the patches not yet applied
2195
2232
2196 Returns 0 on success."""
2233 Returns 0 on success."""
2197
2234
2198 q = repo.mq
2235 q = repo.mq
2199 if patch:
2236 if patch:
2200 if patch not in q.series:
2237 if patch not in q.series:
2201 raise util.Abort(_("patch %s is not in series file") % patch)
2238 raise util.Abort(_("patch %s is not in series file") % patch)
2202 start = q.series.index(patch) + 1
2239 start = q.series.index(patch) + 1
2203 else:
2240 else:
2204 start = q.seriesend(True)
2241 start = q.seriesend(True)
2205
2242
2206 if start == len(q.series) and opts.get('first'):
2243 if start == len(q.series) and opts.get('first'):
2207 ui.write(_("all patches applied\n"))
2244 ui.write(_("all patches applied\n"))
2208 return 1
2245 return 1
2209
2246
2210 length = opts.get('first') and 1 or None
2247 length = opts.get('first') and 1 or None
2211 q.qseries(repo, start=start, length=length, status='U',
2248 q.qseries(repo, start=start, length=length, status='U',
2212 summary=opts.get('summary'))
2249 summary=opts.get('summary'))
2213
2250
2214 @command("qimport",
2251 @command("qimport",
2215 [('e', 'existing', None, _('import file in patch directory')),
2252 [('e', 'existing', None, _('import file in patch directory')),
2216 ('n', 'name', '',
2253 ('n', 'name', '',
2217 _('name of patch file'), _('NAME')),
2254 _('name of patch file'), _('NAME')),
2218 ('f', 'force', None, _('overwrite existing files')),
2255 ('f', 'force', None, _('overwrite existing files')),
2219 ('r', 'rev', [],
2256 ('r', 'rev', [],
2220 _('place existing revisions under mq control'), _('REV')),
2257 _('place existing revisions under mq control'), _('REV')),
2221 ('g', 'git', None, _('use git extended diff format')),
2258 ('g', 'git', None, _('use git extended diff format')),
2222 ('P', 'push', None, _('qpush after importing'))],
2259 ('P', 'push', None, _('qpush after importing'))],
2223 _('hg qimport [-e] [-n NAME] [-f] [-g] [-P] [-r REV]... [FILE]...'))
2260 _('hg qimport [-e] [-n NAME] [-f] [-g] [-P] [-r REV]... [FILE]...'))
2224 def qimport(ui, repo, *filename, **opts):
2261 def qimport(ui, repo, *filename, **opts):
2225 """import a patch or existing changeset
2262 """import a patch or existing changeset
2226
2263
2227 The patch is inserted into the series after the last applied
2264 The patch is inserted into the series after the last applied
2228 patch. If no patches have been applied, qimport prepends the patch
2265 patch. If no patches have been applied, qimport prepends the patch
2229 to the series.
2266 to the series.
2230
2267
2231 The patch will have the same name as its source file unless you
2268 The patch will have the same name as its source file unless you
2232 give it a new one with -n/--name.
2269 give it a new one with -n/--name.
2233
2270
2234 You can register an existing patch inside the patch directory with
2271 You can register an existing patch inside the patch directory with
2235 the -e/--existing flag.
2272 the -e/--existing flag.
2236
2273
2237 With -f/--force, an existing patch of the same name will be
2274 With -f/--force, an existing patch of the same name will be
2238 overwritten.
2275 overwritten.
2239
2276
2240 An existing changeset may be placed under mq control with -r/--rev
2277 An existing changeset may be placed under mq control with -r/--rev
2241 (e.g. qimport --rev . -n patch will place the current revision
2278 (e.g. qimport --rev . -n patch will place the current revision
2242 under mq control). With -g/--git, patches imported with --rev will
2279 under mq control). With -g/--git, patches imported with --rev will
2243 use the git diff format. See the diffs help topic for information
2280 use the git diff format. See the diffs help topic for information
2244 on why this is important for preserving rename/copy information
2281 on why this is important for preserving rename/copy information
2245 and permission changes. Use :hg:`qfinish` to remove changesets
2282 and permission changes. Use :hg:`qfinish` to remove changesets
2246 from mq control.
2283 from mq control.
2247
2284
2248 To import a patch from standard input, pass - as the patch file.
2285 To import a patch from standard input, pass - as the patch file.
2249 When importing from standard input, a patch name must be specified
2286 When importing from standard input, a patch name must be specified
2250 using the --name flag.
2287 using the --name flag.
2251
2288
2252 To import an existing patch while renaming it::
2289 To import an existing patch while renaming it::
2253
2290
2254 hg qimport -e existing-patch -n new-name
2291 hg qimport -e existing-patch -n new-name
2255
2292
2256 Returns 0 if import succeeded.
2293 Returns 0 if import succeeded.
2257 """
2294 """
2258 lock = repo.lock() # cause this may move phase
2295 lock = repo.lock() # cause this may move phase
2259 try:
2296 try:
2260 q = repo.mq
2297 q = repo.mq
2261 try:
2298 try:
2262 imported = q.qimport(
2299 imported = q.qimport(
2263 repo, filename, patchname=opts.get('name'),
2300 repo, filename, patchname=opts.get('name'),
2264 existing=opts.get('existing'), force=opts.get('force'),
2301 existing=opts.get('existing'), force=opts.get('force'),
2265 rev=opts.get('rev'), git=opts.get('git'))
2302 rev=opts.get('rev'), git=opts.get('git'))
2266 finally:
2303 finally:
2267 q.savedirty()
2304 q.savedirty()
2268 finally:
2305 finally:
2269 lock.release()
2306 lock.release()
2270
2307
2271 if imported and opts.get('push') and not opts.get('rev'):
2308 if imported and opts.get('push') and not opts.get('rev'):
2272 return q.push(repo, imported[-1])
2309 return q.push(repo, imported[-1])
2273 return 0
2310 return 0
2274
2311
2275 def qinit(ui, repo, create):
2312 def qinit(ui, repo, create):
2276 """initialize a new queue repository
2313 """initialize a new queue repository
2277
2314
2278 This command also creates a series file for ordering patches, and
2315 This command also creates a series file for ordering patches, and
2279 an mq-specific .hgignore file in the queue repository, to exclude
2316 an mq-specific .hgignore file in the queue repository, to exclude
2280 the status and guards files (these contain mostly transient state).
2317 the status and guards files (these contain mostly transient state).
2281
2318
2282 Returns 0 if initialization succeeded."""
2319 Returns 0 if initialization succeeded."""
2283 q = repo.mq
2320 q = repo.mq
2284 r = q.init(repo, create)
2321 r = q.init(repo, create)
2285 q.savedirty()
2322 q.savedirty()
2286 if r:
2323 if r:
2287 if not os.path.exists(r.wjoin('.hgignore')):
2324 if not os.path.exists(r.wjoin('.hgignore')):
2288 fp = r.wopener('.hgignore', 'w')
2325 fp = r.wopener('.hgignore', 'w')
2289 fp.write('^\\.hg\n')
2326 fp.write('^\\.hg\n')
2290 fp.write('^\\.mq\n')
2327 fp.write('^\\.mq\n')
2291 fp.write('syntax: glob\n')
2328 fp.write('syntax: glob\n')
2292 fp.write('status\n')
2329 fp.write('status\n')
2293 fp.write('guards\n')
2330 fp.write('guards\n')
2294 fp.close()
2331 fp.close()
2295 if not os.path.exists(r.wjoin('series')):
2332 if not os.path.exists(r.wjoin('series')):
2296 r.wopener('series', 'w').close()
2333 r.wopener('series', 'w').close()
2297 r[None].add(['.hgignore', 'series'])
2334 r[None].add(['.hgignore', 'series'])
2298 commands.add(ui, r)
2335 commands.add(ui, r)
2299 return 0
2336 return 0
2300
2337
2301 @command("^qinit",
2338 @command("^qinit",
2302 [('c', 'create-repo', None, _('create queue repository'))],
2339 [('c', 'create-repo', None, _('create queue repository'))],
2303 _('hg qinit [-c]'))
2340 _('hg qinit [-c]'))
2304 def init(ui, repo, **opts):
2341 def init(ui, repo, **opts):
2305 """init a new queue repository (DEPRECATED)
2342 """init a new queue repository (DEPRECATED)
2306
2343
2307 The queue repository is unversioned by default. If
2344 The queue repository is unversioned by default. If
2308 -c/--create-repo is specified, qinit will create a separate nested
2345 -c/--create-repo is specified, qinit will create a separate nested
2309 repository for patches (qinit -c may also be run later to convert
2346 repository for patches (qinit -c may also be run later to convert
2310 an unversioned patch repository into a versioned one). You can use
2347 an unversioned patch repository into a versioned one). You can use
2311 qcommit to commit changes to this queue repository.
2348 qcommit to commit changes to this queue repository.
2312
2349
2313 This command is deprecated. Without -c, it's implied by other relevant
2350 This command is deprecated. Without -c, it's implied by other relevant
2314 commands. With -c, use :hg:`init --mq` instead."""
2351 commands. With -c, use :hg:`init --mq` instead."""
2315 return qinit(ui, repo, create=opts.get('create_repo'))
2352 return qinit(ui, repo, create=opts.get('create_repo'))
2316
2353
2317 @command("qclone",
2354 @command("qclone",
2318 [('', 'pull', None, _('use pull protocol to copy metadata')),
2355 [('', 'pull', None, _('use pull protocol to copy metadata')),
2319 ('U', 'noupdate', None,
2356 ('U', 'noupdate', None,
2320 _('do not update the new working directories')),
2357 _('do not update the new working directories')),
2321 ('', 'uncompressed', None,
2358 ('', 'uncompressed', None,
2322 _('use uncompressed transfer (fast over LAN)')),
2359 _('use uncompressed transfer (fast over LAN)')),
2323 ('p', 'patches', '',
2360 ('p', 'patches', '',
2324 _('location of source patch repository'), _('REPO')),
2361 _('location of source patch repository'), _('REPO')),
2325 ] + commands.remoteopts,
2362 ] + commands.remoteopts,
2326 _('hg qclone [OPTION]... SOURCE [DEST]'),
2363 _('hg qclone [OPTION]... SOURCE [DEST]'),
2327 norepo=True)
2364 norepo=True)
2328 def clone(ui, source, dest=None, **opts):
2365 def clone(ui, source, dest=None, **opts):
2329 '''clone main and patch repository at same time
2366 '''clone main and patch repository at same time
2330
2367
2331 If source is local, destination will have no patches applied. If
2368 If source is local, destination will have no patches applied. If
2332 source is remote, this command can not check if patches are
2369 source is remote, this command can not check if patches are
2333 applied in source, so cannot guarantee that patches are not
2370 applied in source, so cannot guarantee that patches are not
2334 applied in destination. If you clone remote repository, be sure
2371 applied in destination. If you clone remote repository, be sure
2335 before that it has no patches applied.
2372 before that it has no patches applied.
2336
2373
2337 Source patch repository is looked for in <src>/.hg/patches by
2374 Source patch repository is looked for in <src>/.hg/patches by
2338 default. Use -p <url> to change.
2375 default. Use -p <url> to change.
2339
2376
2340 The patch directory must be a nested Mercurial repository, as
2377 The patch directory must be a nested Mercurial repository, as
2341 would be created by :hg:`init --mq`.
2378 would be created by :hg:`init --mq`.
2342
2379
2343 Return 0 on success.
2380 Return 0 on success.
2344 '''
2381 '''
2345 def patchdir(repo):
2382 def patchdir(repo):
2346 """compute a patch repo url from a repo object"""
2383 """compute a patch repo url from a repo object"""
2347 url = repo.url()
2384 url = repo.url()
2348 if url.endswith('/'):
2385 if url.endswith('/'):
2349 url = url[:-1]
2386 url = url[:-1]
2350 return url + '/.hg/patches'
2387 return url + '/.hg/patches'
2351
2388
2352 # main repo (destination and sources)
2389 # main repo (destination and sources)
2353 if dest is None:
2390 if dest is None:
2354 dest = hg.defaultdest(source)
2391 dest = hg.defaultdest(source)
2355 sr = hg.peer(ui, opts, ui.expandpath(source))
2392 sr = hg.peer(ui, opts, ui.expandpath(source))
2356
2393
2357 # patches repo (source only)
2394 # patches repo (source only)
2358 if opts.get('patches'):
2395 if opts.get('patches'):
2359 patchespath = ui.expandpath(opts.get('patches'))
2396 patchespath = ui.expandpath(opts.get('patches'))
2360 else:
2397 else:
2361 patchespath = patchdir(sr)
2398 patchespath = patchdir(sr)
2362 try:
2399 try:
2363 hg.peer(ui, opts, patchespath)
2400 hg.peer(ui, opts, patchespath)
2364 except error.RepoError:
2401 except error.RepoError:
2365 raise util.Abort(_('versioned patch repository not found'
2402 raise util.Abort(_('versioned patch repository not found'
2366 ' (see init --mq)'))
2403 ' (see init --mq)'))
2367 qbase, destrev = None, None
2404 qbase, destrev = None, None
2368 if sr.local():
2405 if sr.local():
2369 repo = sr.local()
2406 repo = sr.local()
2370 if repo.mq.applied and repo[qbase].phase() != phases.secret:
2407 if repo.mq.applied and repo[qbase].phase() != phases.secret:
2371 qbase = repo.mq.applied[0].node
2408 qbase = repo.mq.applied[0].node
2372 if not hg.islocal(dest):
2409 if not hg.islocal(dest):
2373 heads = set(repo.heads())
2410 heads = set(repo.heads())
2374 destrev = list(heads.difference(repo.heads(qbase)))
2411 destrev = list(heads.difference(repo.heads(qbase)))
2375 destrev.append(repo.changelog.parents(qbase)[0])
2412 destrev.append(repo.changelog.parents(qbase)[0])
2376 elif sr.capable('lookup'):
2413 elif sr.capable('lookup'):
2377 try:
2414 try:
2378 qbase = sr.lookup('qbase')
2415 qbase = sr.lookup('qbase')
2379 except error.RepoError:
2416 except error.RepoError:
2380 pass
2417 pass
2381
2418
2382 ui.note(_('cloning main repository\n'))
2419 ui.note(_('cloning main repository\n'))
2383 sr, dr = hg.clone(ui, opts, sr.url(), dest,
2420 sr, dr = hg.clone(ui, opts, sr.url(), dest,
2384 pull=opts.get('pull'),
2421 pull=opts.get('pull'),
2385 rev=destrev,
2422 rev=destrev,
2386 update=False,
2423 update=False,
2387 stream=opts.get('uncompressed'))
2424 stream=opts.get('uncompressed'))
2388
2425
2389 ui.note(_('cloning patch repository\n'))
2426 ui.note(_('cloning patch repository\n'))
2390 hg.clone(ui, opts, opts.get('patches') or patchdir(sr), patchdir(dr),
2427 hg.clone(ui, opts, opts.get('patches') or patchdir(sr), patchdir(dr),
2391 pull=opts.get('pull'), update=not opts.get('noupdate'),
2428 pull=opts.get('pull'), update=not opts.get('noupdate'),
2392 stream=opts.get('uncompressed'))
2429 stream=opts.get('uncompressed'))
2393
2430
2394 if dr.local():
2431 if dr.local():
2395 repo = dr.local()
2432 repo = dr.local()
2396 if qbase:
2433 if qbase:
2397 ui.note(_('stripping applied patches from destination '
2434 ui.note(_('stripping applied patches from destination '
2398 'repository\n'))
2435 'repository\n'))
2399 strip(ui, repo, [qbase], update=False, backup=None)
2436 strip(ui, repo, [qbase], update=False, backup=None)
2400 if not opts.get('noupdate'):
2437 if not opts.get('noupdate'):
2401 ui.note(_('updating destination repository\n'))
2438 ui.note(_('updating destination repository\n'))
2402 hg.update(repo, repo.changelog.tip())
2439 hg.update(repo, repo.changelog.tip())
2403
2440
2404 @command("qcommit|qci",
2441 @command("qcommit|qci",
2405 commands.table["^commit|ci"][1],
2442 commands.table["^commit|ci"][1],
2406 _('hg qcommit [OPTION]... [FILE]...'),
2443 _('hg qcommit [OPTION]... [FILE]...'),
2407 inferrepo=True)
2444 inferrepo=True)
2408 def commit(ui, repo, *pats, **opts):
2445 def commit(ui, repo, *pats, **opts):
2409 """commit changes in the queue repository (DEPRECATED)
2446 """commit changes in the queue repository (DEPRECATED)
2410
2447
2411 This command is deprecated; use :hg:`commit --mq` instead."""
2448 This command is deprecated; use :hg:`commit --mq` instead."""
2412 q = repo.mq
2449 q = repo.mq
2413 r = q.qrepo()
2450 r = q.qrepo()
2414 if not r:
2451 if not r:
2415 raise util.Abort('no queue repository')
2452 raise util.Abort('no queue repository')
2416 commands.commit(r.ui, r, *pats, **opts)
2453 commands.commit(r.ui, r, *pats, **opts)
2417
2454
2418 @command("qseries",
2455 @command("qseries",
2419 [('m', 'missing', None, _('print patches not in series')),
2456 [('m', 'missing', None, _('print patches not in series')),
2420 ] + seriesopts,
2457 ] + seriesopts,
2421 _('hg qseries [-ms]'))
2458 _('hg qseries [-ms]'))
2422 def series(ui, repo, **opts):
2459 def series(ui, repo, **opts):
2423 """print the entire series file
2460 """print the entire series file
2424
2461
2425 Returns 0 on success."""
2462 Returns 0 on success."""
2426 repo.mq.qseries(repo, missing=opts.get('missing'),
2463 repo.mq.qseries(repo, missing=opts.get('missing'),
2427 summary=opts.get('summary'))
2464 summary=opts.get('summary'))
2428 return 0
2465 return 0
2429
2466
2430 @command("qtop", seriesopts, _('hg qtop [-s]'))
2467 @command("qtop", seriesopts, _('hg qtop [-s]'))
2431 def top(ui, repo, **opts):
2468 def top(ui, repo, **opts):
2432 """print the name of the current patch
2469 """print the name of the current patch
2433
2470
2434 Returns 0 on success."""
2471 Returns 0 on success."""
2435 q = repo.mq
2472 q = repo.mq
2436 t = q.applied and q.seriesend(True) or 0
2473 t = q.applied and q.seriesend(True) or 0
2437 if t:
2474 if t:
2438 q.qseries(repo, start=t - 1, length=1, status='A',
2475 q.qseries(repo, start=t - 1, length=1, status='A',
2439 summary=opts.get('summary'))
2476 summary=opts.get('summary'))
2440 else:
2477 else:
2441 ui.write(_("no patches applied\n"))
2478 ui.write(_("no patches applied\n"))
2442 return 1
2479 return 1
2443
2480
2444 @command("qnext", seriesopts, _('hg qnext [-s]'))
2481 @command("qnext", seriesopts, _('hg qnext [-s]'))
2445 def next(ui, repo, **opts):
2482 def next(ui, repo, **opts):
2446 """print the name of the next pushable patch
2483 """print the name of the next pushable patch
2447
2484
2448 Returns 0 on success."""
2485 Returns 0 on success."""
2449 q = repo.mq
2486 q = repo.mq
2450 end = q.seriesend()
2487 end = q.seriesend()
2451 if end == len(q.series):
2488 if end == len(q.series):
2452 ui.write(_("all patches applied\n"))
2489 ui.write(_("all patches applied\n"))
2453 return 1
2490 return 1
2454 q.qseries(repo, start=end, length=1, summary=opts.get('summary'))
2491 q.qseries(repo, start=end, length=1, summary=opts.get('summary'))
2455
2492
2456 @command("qprev", seriesopts, _('hg qprev [-s]'))
2493 @command("qprev", seriesopts, _('hg qprev [-s]'))
2457 def prev(ui, repo, **opts):
2494 def prev(ui, repo, **opts):
2458 """print the name of the preceding applied patch
2495 """print the name of the preceding applied patch
2459
2496
2460 Returns 0 on success."""
2497 Returns 0 on success."""
2461 q = repo.mq
2498 q = repo.mq
2462 l = len(q.applied)
2499 l = len(q.applied)
2463 if l == 1:
2500 if l == 1:
2464 ui.write(_("only one patch applied\n"))
2501 ui.write(_("only one patch applied\n"))
2465 return 1
2502 return 1
2466 if not l:
2503 if not l:
2467 ui.write(_("no patches applied\n"))
2504 ui.write(_("no patches applied\n"))
2468 return 1
2505 return 1
2469 idx = q.series.index(q.applied[-2].name)
2506 idx = q.series.index(q.applied[-2].name)
2470 q.qseries(repo, start=idx, length=1, status='A',
2507 q.qseries(repo, start=idx, length=1, status='A',
2471 summary=opts.get('summary'))
2508 summary=opts.get('summary'))
2472
2509
2473 def setupheaderopts(ui, opts):
2510 def setupheaderopts(ui, opts):
2474 if not opts.get('user') and opts.get('currentuser'):
2511 if not opts.get('user') and opts.get('currentuser'):
2475 opts['user'] = ui.username()
2512 opts['user'] = ui.username()
2476 if not opts.get('date') and opts.get('currentdate'):
2513 if not opts.get('date') and opts.get('currentdate'):
2477 opts['date'] = "%d %d" % util.makedate()
2514 opts['date'] = "%d %d" % util.makedate()
2478
2515
2479 @command("^qnew",
2516 @command("^qnew",
2480 [('e', 'edit', None, _('invoke editor on commit messages')),
2517 [('e', 'edit', None, _('invoke editor on commit messages')),
2481 ('f', 'force', None, _('import uncommitted changes (DEPRECATED)')),
2518 ('f', 'force', None, _('import uncommitted changes (DEPRECATED)')),
2482 ('g', 'git', None, _('use git extended diff format')),
2519 ('g', 'git', None, _('use git extended diff format')),
2483 ('U', 'currentuser', None, _('add "From: <current user>" to patch')),
2520 ('U', 'currentuser', None, _('add "From: <current user>" to patch')),
2484 ('u', 'user', '',
2521 ('u', 'user', '',
2485 _('add "From: <USER>" to patch'), _('USER')),
2522 _('add "From: <USER>" to patch'), _('USER')),
2486 ('D', 'currentdate', None, _('add "Date: <current date>" to patch')),
2523 ('D', 'currentdate', None, _('add "Date: <current date>" to patch')),
2487 ('d', 'date', '',
2524 ('d', 'date', '',
2488 _('add "Date: <DATE>" to patch'), _('DATE'))
2525 _('add "Date: <DATE>" to patch'), _('DATE'))
2489 ] + commands.walkopts + commands.commitopts,
2526 ] + commands.walkopts + commands.commitopts,
2490 _('hg qnew [-e] [-m TEXT] [-l FILE] PATCH [FILE]...'),
2527 _('hg qnew [-e] [-m TEXT] [-l FILE] PATCH [FILE]...'),
2491 inferrepo=True)
2528 inferrepo=True)
2492 def new(ui, repo, patch, *args, **opts):
2529 def new(ui, repo, patch, *args, **opts):
2493 """create a new patch
2530 """create a new patch
2494
2531
2495 qnew creates a new patch on top of the currently-applied patch (if
2532 qnew creates a new patch on top of the currently-applied patch (if
2496 any). The patch will be initialized with any outstanding changes
2533 any). The patch will be initialized with any outstanding changes
2497 in the working directory. You may also use -I/--include,
2534 in the working directory. You may also use -I/--include,
2498 -X/--exclude, and/or a list of files after the patch name to add
2535 -X/--exclude, and/or a list of files after the patch name to add
2499 only changes to matching files to the new patch, leaving the rest
2536 only changes to matching files to the new patch, leaving the rest
2500 as uncommitted modifications.
2537 as uncommitted modifications.
2501
2538
2502 -u/--user and -d/--date can be used to set the (given) user and
2539 -u/--user and -d/--date can be used to set the (given) user and
2503 date, respectively. -U/--currentuser and -D/--currentdate set user
2540 date, respectively. -U/--currentuser and -D/--currentdate set user
2504 to current user and date to current date.
2541 to current user and date to current date.
2505
2542
2506 -e/--edit, -m/--message or -l/--logfile set the patch header as
2543 -e/--edit, -m/--message or -l/--logfile set the patch header as
2507 well as the commit message. If none is specified, the header is
2544 well as the commit message. If none is specified, the header is
2508 empty and the commit message is '[mq]: PATCH'.
2545 empty and the commit message is '[mq]: PATCH'.
2509
2546
2510 Use the -g/--git option to keep the patch in the git extended diff
2547 Use the -g/--git option to keep the patch in the git extended diff
2511 format. Read the diffs help topic for more information on why this
2548 format. Read the diffs help topic for more information on why this
2512 is important for preserving permission changes and copy/rename
2549 is important for preserving permission changes and copy/rename
2513 information.
2550 information.
2514
2551
2515 Returns 0 on successful creation of a new patch.
2552 Returns 0 on successful creation of a new patch.
2516 """
2553 """
2517 msg = cmdutil.logmessage(ui, opts)
2554 msg = cmdutil.logmessage(ui, opts)
2518 q = repo.mq
2555 q = repo.mq
2519 opts['msg'] = msg
2556 opts['msg'] = msg
2520 setupheaderopts(ui, opts)
2557 setupheaderopts(ui, opts)
2521 q.new(repo, patch, *args, **opts)
2558 q.new(repo, patch, *args, **opts)
2522 q.savedirty()
2559 q.savedirty()
2523 return 0
2560 return 0
2524
2561
2525 @command("^qrefresh",
2562 @command("^qrefresh",
2526 [('e', 'edit', None, _('invoke editor on commit messages')),
2563 [('e', 'edit', None, _('invoke editor on commit messages')),
2527 ('g', 'git', None, _('use git extended diff format')),
2564 ('g', 'git', None, _('use git extended diff format')),
2528 ('s', 'short', None,
2565 ('s', 'short', None,
2529 _('refresh only files already in the patch and specified files')),
2566 _('refresh only files already in the patch and specified files')),
2530 ('U', 'currentuser', None,
2567 ('U', 'currentuser', None,
2531 _('add/update author field in patch with current user')),
2568 _('add/update author field in patch with current user')),
2532 ('u', 'user', '',
2569 ('u', 'user', '',
2533 _('add/update author field in patch with given user'), _('USER')),
2570 _('add/update author field in patch with given user'), _('USER')),
2534 ('D', 'currentdate', None,
2571 ('D', 'currentdate', None,
2535 _('add/update date field in patch with current date')),
2572 _('add/update date field in patch with current date')),
2536 ('d', 'date', '',
2573 ('d', 'date', '',
2537 _('add/update date field in patch with given date'), _('DATE'))
2574 _('add/update date field in patch with given date'), _('DATE'))
2538 ] + commands.walkopts + commands.commitopts,
2575 ] + commands.walkopts + commands.commitopts,
2539 _('hg qrefresh [-I] [-X] [-e] [-m TEXT] [-l FILE] [-s] [FILE]...'),
2576 _('hg qrefresh [-I] [-X] [-e] [-m TEXT] [-l FILE] [-s] [FILE]...'),
2540 inferrepo=True)
2577 inferrepo=True)
2541 def refresh(ui, repo, *pats, **opts):
2578 def refresh(ui, repo, *pats, **opts):
2542 """update the current patch
2579 """update the current patch
2543
2580
2544 If any file patterns are provided, the refreshed patch will
2581 If any file patterns are provided, the refreshed patch will
2545 contain only the modifications that match those patterns; the
2582 contain only the modifications that match those patterns; the
2546 remaining modifications will remain in the working directory.
2583 remaining modifications will remain in the working directory.
2547
2584
2548 If -s/--short is specified, files currently included in the patch
2585 If -s/--short is specified, files currently included in the patch
2549 will be refreshed just like matched files and remain in the patch.
2586 will be refreshed just like matched files and remain in the patch.
2550
2587
2551 If -e/--edit is specified, Mercurial will start your configured editor for
2588 If -e/--edit is specified, Mercurial will start your configured editor for
2552 you to enter a message. In case qrefresh fails, you will find a backup of
2589 you to enter a message. In case qrefresh fails, you will find a backup of
2553 your message in ``.hg/last-message.txt``.
2590 your message in ``.hg/last-message.txt``.
2554
2591
2555 hg add/remove/copy/rename work as usual, though you might want to
2592 hg add/remove/copy/rename work as usual, though you might want to
2556 use git-style patches (-g/--git or [diff] git=1) to track copies
2593 use git-style patches (-g/--git or [diff] git=1) to track copies
2557 and renames. See the diffs help topic for more information on the
2594 and renames. See the diffs help topic for more information on the
2558 git diff format.
2595 git diff format.
2559
2596
2560 Returns 0 on success.
2597 Returns 0 on success.
2561 """
2598 """
2562 q = repo.mq
2599 q = repo.mq
2563 message = cmdutil.logmessage(ui, opts)
2600 message = cmdutil.logmessage(ui, opts)
2564 setupheaderopts(ui, opts)
2601 setupheaderopts(ui, opts)
2565 wlock = repo.wlock()
2602 wlock = repo.wlock()
2566 try:
2603 try:
2567 ret = q.refresh(repo, pats, msg=message, **opts)
2604 ret = q.refresh(repo, pats, msg=message, **opts)
2568 q.savedirty()
2605 q.savedirty()
2569 return ret
2606 return ret
2570 finally:
2607 finally:
2571 wlock.release()
2608 wlock.release()
2572
2609
2573 @command("^qdiff",
2610 @command("^qdiff",
2574 commands.diffopts + commands.diffopts2 + commands.walkopts,
2611 commands.diffopts + commands.diffopts2 + commands.walkopts,
2575 _('hg qdiff [OPTION]... [FILE]...'),
2612 _('hg qdiff [OPTION]... [FILE]...'),
2576 inferrepo=True)
2613 inferrepo=True)
2577 def diff(ui, repo, *pats, **opts):
2614 def diff(ui, repo, *pats, **opts):
2578 """diff of the current patch and subsequent modifications
2615 """diff of the current patch and subsequent modifications
2579
2616
2580 Shows a diff which includes the current patch as well as any
2617 Shows a diff which includes the current patch as well as any
2581 changes which have been made in the working directory since the
2618 changes which have been made in the working directory since the
2582 last refresh (thus showing what the current patch would become
2619 last refresh (thus showing what the current patch would become
2583 after a qrefresh).
2620 after a qrefresh).
2584
2621
2585 Use :hg:`diff` if you only want to see the changes made since the
2622 Use :hg:`diff` if you only want to see the changes made since the
2586 last qrefresh, or :hg:`export qtip` if you want to see changes
2623 last qrefresh, or :hg:`export qtip` if you want to see changes
2587 made by the current patch without including changes made since the
2624 made by the current patch without including changes made since the
2588 qrefresh.
2625 qrefresh.
2589
2626
2590 Returns 0 on success.
2627 Returns 0 on success.
2591 """
2628 """
2592 repo.mq.diff(repo, pats, opts)
2629 repo.mq.diff(repo, pats, opts)
2593 return 0
2630 return 0
2594
2631
2595 @command('qfold',
2632 @command('qfold',
2596 [('e', 'edit', None, _('invoke editor on commit messages')),
2633 [('e', 'edit', None, _('invoke editor on commit messages')),
2597 ('k', 'keep', None, _('keep folded patch files')),
2634 ('k', 'keep', None, _('keep folded patch files')),
2598 ] + commands.commitopts,
2635 ] + commands.commitopts,
2599 _('hg qfold [-e] [-k] [-m TEXT] [-l FILE] PATCH...'))
2636 _('hg qfold [-e] [-k] [-m TEXT] [-l FILE] PATCH...'))
2600 def fold(ui, repo, *files, **opts):
2637 def fold(ui, repo, *files, **opts):
2601 """fold the named patches into the current patch
2638 """fold the named patches into the current patch
2602
2639
2603 Patches must not yet be applied. Each patch will be successively
2640 Patches must not yet be applied. Each patch will be successively
2604 applied to the current patch in the order given. If all the
2641 applied to the current patch in the order given. If all the
2605 patches apply successfully, the current patch will be refreshed
2642 patches apply successfully, the current patch will be refreshed
2606 with the new cumulative patch, and the folded patches will be
2643 with the new cumulative patch, and the folded patches will be
2607 deleted. With -k/--keep, the folded patch files will not be
2644 deleted. With -k/--keep, the folded patch files will not be
2608 removed afterwards.
2645 removed afterwards.
2609
2646
2610 The header for each folded patch will be concatenated with the
2647 The header for each folded patch will be concatenated with the
2611 current patch header, separated by a line of ``* * *``.
2648 current patch header, separated by a line of ``* * *``.
2612
2649
2613 Returns 0 on success."""
2650 Returns 0 on success."""
2614 q = repo.mq
2651 q = repo.mq
2615 if not files:
2652 if not files:
2616 raise util.Abort(_('qfold requires at least one patch name'))
2653 raise util.Abort(_('qfold requires at least one patch name'))
2617 if not q.checktoppatch(repo)[0]:
2654 if not q.checktoppatch(repo)[0]:
2618 raise util.Abort(_('no patches applied'))
2655 raise util.Abort(_('no patches applied'))
2619 q.checklocalchanges(repo)
2656 q.checklocalchanges(repo)
2620
2657
2621 message = cmdutil.logmessage(ui, opts)
2658 message = cmdutil.logmessage(ui, opts)
2622
2659
2623 parent = q.lookup('qtip')
2660 parent = q.lookup('qtip')
2624 patches = []
2661 patches = []
2625 messages = []
2662 messages = []
2626 for f in files:
2663 for f in files:
2627 p = q.lookup(f)
2664 p = q.lookup(f)
2628 if p in patches or p == parent:
2665 if p in patches or p == parent:
2629 ui.warn(_('skipping already folded patch %s\n') % p)
2666 ui.warn(_('skipping already folded patch %s\n') % p)
2630 if q.isapplied(p):
2667 if q.isapplied(p):
2631 raise util.Abort(_('qfold cannot fold already applied patch %s')
2668 raise util.Abort(_('qfold cannot fold already applied patch %s')
2632 % p)
2669 % p)
2633 patches.append(p)
2670 patches.append(p)
2634
2671
2635 for p in patches:
2672 for p in patches:
2636 if not message:
2673 if not message:
2637 ph = patchheader(q.join(p), q.plainmode)
2674 ph = patchheader(q.join(p), q.plainmode)
2638 if ph.message:
2675 if ph.message:
2639 messages.append(ph.message)
2676 messages.append(ph.message)
2640 pf = q.join(p)
2677 pf = q.join(p)
2641 (patchsuccess, files, fuzz) = q.patch(repo, pf)
2678 (patchsuccess, files, fuzz) = q.patch(repo, pf)
2642 if not patchsuccess:
2679 if not patchsuccess:
2643 raise util.Abort(_('error folding patch %s') % p)
2680 raise util.Abort(_('error folding patch %s') % p)
2644
2681
2645 if not message:
2682 if not message:
2646 ph = patchheader(q.join(parent), q.plainmode)
2683 ph = patchheader(q.join(parent), q.plainmode)
2647 message = ph.message
2684 message = ph.message
2648 for msg in messages:
2685 for msg in messages:
2649 if msg:
2686 if msg:
2650 if message:
2687 if message:
2651 message.append('* * *')
2688 message.append('* * *')
2652 message.extend(msg)
2689 message.extend(msg)
2653 message = '\n'.join(message)
2690 message = '\n'.join(message)
2654
2691
2655 diffopts = q.patchopts(q.diffopts(), *patches)
2692 diffopts = q.patchopts(q.diffopts(), *patches)
2656 wlock = repo.wlock()
2693 wlock = repo.wlock()
2657 try:
2694 try:
2658 q.refresh(repo, msg=message, git=diffopts.git, edit=opts.get('edit'),
2695 q.refresh(repo, msg=message, git=diffopts.git, edit=opts.get('edit'),
2659 editform='mq.qfold')
2696 editform='mq.qfold')
2660 q.delete(repo, patches, opts)
2697 q.delete(repo, patches, opts)
2661 q.savedirty()
2698 q.savedirty()
2662 finally:
2699 finally:
2663 wlock.release()
2700 wlock.release()
2664
2701
2665 @command("qgoto",
2702 @command("qgoto",
2666 [('', 'keep-changes', None,
2703 [('', 'keep-changes', None,
2667 _('tolerate non-conflicting local changes')),
2704 _('tolerate non-conflicting local changes')),
2668 ('f', 'force', None, _('overwrite any local changes')),
2705 ('f', 'force', None, _('overwrite any local changes')),
2669 ('', 'no-backup', None, _('do not save backup copies of files'))],
2706 ('', 'no-backup', None, _('do not save backup copies of files'))],
2670 _('hg qgoto [OPTION]... PATCH'))
2707 _('hg qgoto [OPTION]... PATCH'))
2671 def goto(ui, repo, patch, **opts):
2708 def goto(ui, repo, patch, **opts):
2672 '''push or pop patches until named patch is at top of stack
2709 '''push or pop patches until named patch is at top of stack
2673
2710
2674 Returns 0 on success.'''
2711 Returns 0 on success.'''
2675 opts = fixkeepchangesopts(ui, opts)
2712 opts = fixkeepchangesopts(ui, opts)
2676 q = repo.mq
2713 q = repo.mq
2677 patch = q.lookup(patch)
2714 patch = q.lookup(patch)
2678 nobackup = opts.get('no_backup')
2715 nobackup = opts.get('no_backup')
2679 keepchanges = opts.get('keep_changes')
2716 keepchanges = opts.get('keep_changes')
2680 if q.isapplied(patch):
2717 if q.isapplied(patch):
2681 ret = q.pop(repo, patch, force=opts.get('force'), nobackup=nobackup,
2718 ret = q.pop(repo, patch, force=opts.get('force'), nobackup=nobackup,
2682 keepchanges=keepchanges)
2719 keepchanges=keepchanges)
2683 else:
2720 else:
2684 ret = q.push(repo, patch, force=opts.get('force'), nobackup=nobackup,
2721 ret = q.push(repo, patch, force=opts.get('force'), nobackup=nobackup,
2685 keepchanges=keepchanges)
2722 keepchanges=keepchanges)
2686 q.savedirty()
2723 q.savedirty()
2687 return ret
2724 return ret
2688
2725
2689 @command("qguard",
2726 @command("qguard",
2690 [('l', 'list', None, _('list all patches and guards')),
2727 [('l', 'list', None, _('list all patches and guards')),
2691 ('n', 'none', None, _('drop all guards'))],
2728 ('n', 'none', None, _('drop all guards'))],
2692 _('hg qguard [-l] [-n] [PATCH] [-- [+GUARD]... [-GUARD]...]'))
2729 _('hg qguard [-l] [-n] [PATCH] [-- [+GUARD]... [-GUARD]...]'))
2693 def guard(ui, repo, *args, **opts):
2730 def guard(ui, repo, *args, **opts):
2694 '''set or print guards for a patch
2731 '''set or print guards for a patch
2695
2732
2696 Guards control whether a patch can be pushed. A patch with no
2733 Guards control whether a patch can be pushed. A patch with no
2697 guards is always pushed. A patch with a positive guard ("+foo") is
2734 guards is always pushed. A patch with a positive guard ("+foo") is
2698 pushed only if the :hg:`qselect` command has activated it. A patch with
2735 pushed only if the :hg:`qselect` command has activated it. A patch with
2699 a negative guard ("-foo") is never pushed if the :hg:`qselect` command
2736 a negative guard ("-foo") is never pushed if the :hg:`qselect` command
2700 has activated it.
2737 has activated it.
2701
2738
2702 With no arguments, print the currently active guards.
2739 With no arguments, print the currently active guards.
2703 With arguments, set guards for the named patch.
2740 With arguments, set guards for the named patch.
2704
2741
2705 .. note::
2742 .. note::
2706
2743
2707 Specifying negative guards now requires '--'.
2744 Specifying negative guards now requires '--'.
2708
2745
2709 To set guards on another patch::
2746 To set guards on another patch::
2710
2747
2711 hg qguard other.patch -- +2.6.17 -stable
2748 hg qguard other.patch -- +2.6.17 -stable
2712
2749
2713 Returns 0 on success.
2750 Returns 0 on success.
2714 '''
2751 '''
2715 def status(idx):
2752 def status(idx):
2716 guards = q.seriesguards[idx] or ['unguarded']
2753 guards = q.seriesguards[idx] or ['unguarded']
2717 if q.series[idx] in applied:
2754 if q.series[idx] in applied:
2718 state = 'applied'
2755 state = 'applied'
2719 elif q.pushable(idx)[0]:
2756 elif q.pushable(idx)[0]:
2720 state = 'unapplied'
2757 state = 'unapplied'
2721 else:
2758 else:
2722 state = 'guarded'
2759 state = 'guarded'
2723 label = 'qguard.patch qguard.%s qseries.%s' % (state, state)
2760 label = 'qguard.patch qguard.%s qseries.%s' % (state, state)
2724 ui.write('%s: ' % ui.label(q.series[idx], label))
2761 ui.write('%s: ' % ui.label(q.series[idx], label))
2725
2762
2726 for i, guard in enumerate(guards):
2763 for i, guard in enumerate(guards):
2727 if guard.startswith('+'):
2764 if guard.startswith('+'):
2728 ui.write(guard, label='qguard.positive')
2765 ui.write(guard, label='qguard.positive')
2729 elif guard.startswith('-'):
2766 elif guard.startswith('-'):
2730 ui.write(guard, label='qguard.negative')
2767 ui.write(guard, label='qguard.negative')
2731 else:
2768 else:
2732 ui.write(guard, label='qguard.unguarded')
2769 ui.write(guard, label='qguard.unguarded')
2733 if i != len(guards) - 1:
2770 if i != len(guards) - 1:
2734 ui.write(' ')
2771 ui.write(' ')
2735 ui.write('\n')
2772 ui.write('\n')
2736 q = repo.mq
2773 q = repo.mq
2737 applied = set(p.name for p in q.applied)
2774 applied = set(p.name for p in q.applied)
2738 patch = None
2775 patch = None
2739 args = list(args)
2776 args = list(args)
2740 if opts.get('list'):
2777 if opts.get('list'):
2741 if args or opts.get('none'):
2778 if args or opts.get('none'):
2742 raise util.Abort(_('cannot mix -l/--list with options or '
2779 raise util.Abort(_('cannot mix -l/--list with options or '
2743 'arguments'))
2780 'arguments'))
2744 for i in xrange(len(q.series)):
2781 for i in xrange(len(q.series)):
2745 status(i)
2782 status(i)
2746 return
2783 return
2747 if not args or args[0][0:1] in '-+':
2784 if not args or args[0][0:1] in '-+':
2748 if not q.applied:
2785 if not q.applied:
2749 raise util.Abort(_('no patches applied'))
2786 raise util.Abort(_('no patches applied'))
2750 patch = q.applied[-1].name
2787 patch = q.applied[-1].name
2751 if patch is None and args[0][0:1] not in '-+':
2788 if patch is None and args[0][0:1] not in '-+':
2752 patch = args.pop(0)
2789 patch = args.pop(0)
2753 if patch is None:
2790 if patch is None:
2754 raise util.Abort(_('no patch to work with'))
2791 raise util.Abort(_('no patch to work with'))
2755 if args or opts.get('none'):
2792 if args or opts.get('none'):
2756 idx = q.findseries(patch)
2793 idx = q.findseries(patch)
2757 if idx is None:
2794 if idx is None:
2758 raise util.Abort(_('no patch named %s') % patch)
2795 raise util.Abort(_('no patch named %s') % patch)
2759 q.setguards(idx, args)
2796 q.setguards(idx, args)
2760 q.savedirty()
2797 q.savedirty()
2761 else:
2798 else:
2762 status(q.series.index(q.lookup(patch)))
2799 status(q.series.index(q.lookup(patch)))
2763
2800
2764 @command("qheader", [], _('hg qheader [PATCH]'))
2801 @command("qheader", [], _('hg qheader [PATCH]'))
2765 def header(ui, repo, patch=None):
2802 def header(ui, repo, patch=None):
2766 """print the header of the topmost or specified patch
2803 """print the header of the topmost or specified patch
2767
2804
2768 Returns 0 on success."""
2805 Returns 0 on success."""
2769 q = repo.mq
2806 q = repo.mq
2770
2807
2771 if patch:
2808 if patch:
2772 patch = q.lookup(patch)
2809 patch = q.lookup(patch)
2773 else:
2810 else:
2774 if not q.applied:
2811 if not q.applied:
2775 ui.write(_('no patches applied\n'))
2812 ui.write(_('no patches applied\n'))
2776 return 1
2813 return 1
2777 patch = q.lookup('qtip')
2814 patch = q.lookup('qtip')
2778 ph = patchheader(q.join(patch), q.plainmode)
2815 ph = patchheader(q.join(patch), q.plainmode)
2779
2816
2780 ui.write('\n'.join(ph.message) + '\n')
2817 ui.write('\n'.join(ph.message) + '\n')
2781
2818
2782 def lastsavename(path):
2819 def lastsavename(path):
2783 (directory, base) = os.path.split(path)
2820 (directory, base) = os.path.split(path)
2784 names = os.listdir(directory)
2821 names = os.listdir(directory)
2785 namere = re.compile("%s.([0-9]+)" % base)
2822 namere = re.compile("%s.([0-9]+)" % base)
2786 maxindex = None
2823 maxindex = None
2787 maxname = None
2824 maxname = None
2788 for f in names:
2825 for f in names:
2789 m = namere.match(f)
2826 m = namere.match(f)
2790 if m:
2827 if m:
2791 index = int(m.group(1))
2828 index = int(m.group(1))
2792 if maxindex is None or index > maxindex:
2829 if maxindex is None or index > maxindex:
2793 maxindex = index
2830 maxindex = index
2794 maxname = f
2831 maxname = f
2795 if maxname:
2832 if maxname:
2796 return (os.path.join(directory, maxname), maxindex)
2833 return (os.path.join(directory, maxname), maxindex)
2797 return (None, None)
2834 return (None, None)
2798
2835
2799 def savename(path):
2836 def savename(path):
2800 (last, index) = lastsavename(path)
2837 (last, index) = lastsavename(path)
2801 if last is None:
2838 if last is None:
2802 index = 0
2839 index = 0
2803 newpath = path + ".%d" % (index + 1)
2840 newpath = path + ".%d" % (index + 1)
2804 return newpath
2841 return newpath
2805
2842
2806 @command("^qpush",
2843 @command("^qpush",
2807 [('', 'keep-changes', None,
2844 [('', 'keep-changes', None,
2808 _('tolerate non-conflicting local changes')),
2845 _('tolerate non-conflicting local changes')),
2809 ('f', 'force', None, _('apply on top of local changes')),
2846 ('f', 'force', None, _('apply on top of local changes')),
2810 ('e', 'exact', None,
2847 ('e', 'exact', None,
2811 _('apply the target patch to its recorded parent')),
2848 _('apply the target patch to its recorded parent')),
2812 ('l', 'list', None, _('list patch name in commit text')),
2849 ('l', 'list', None, _('list patch name in commit text')),
2813 ('a', 'all', None, _('apply all patches')),
2850 ('a', 'all', None, _('apply all patches')),
2814 ('m', 'merge', None, _('merge from another queue (DEPRECATED)')),
2851 ('m', 'merge', None, _('merge from another queue (DEPRECATED)')),
2815 ('n', 'name', '',
2852 ('n', 'name', '',
2816 _('merge queue name (DEPRECATED)'), _('NAME')),
2853 _('merge queue name (DEPRECATED)'), _('NAME')),
2817 ('', 'move', None,
2854 ('', 'move', None,
2818 _('reorder patch series and apply only the patch')),
2855 _('reorder patch series and apply only the patch')),
2819 ('', 'no-backup', None, _('do not save backup copies of files'))],
2856 ('', 'no-backup', None, _('do not save backup copies of files'))],
2820 _('hg qpush [-f] [-l] [-a] [--move] [PATCH | INDEX]'))
2857 _('hg qpush [-f] [-l] [-a] [--move] [PATCH | INDEX]'))
2821 def push(ui, repo, patch=None, **opts):
2858 def push(ui, repo, patch=None, **opts):
2822 """push the next patch onto the stack
2859 """push the next patch onto the stack
2823
2860
2824 By default, abort if the working directory contains uncommitted
2861 By default, abort if the working directory contains uncommitted
2825 changes. With --keep-changes, abort only if the uncommitted files
2862 changes. With --keep-changes, abort only if the uncommitted files
2826 overlap with patched files. With -f/--force, backup and patch over
2863 overlap with patched files. With -f/--force, backup and patch over
2827 uncommitted changes.
2864 uncommitted changes.
2828
2865
2829 Return 0 on success.
2866 Return 0 on success.
2830 """
2867 """
2831 q = repo.mq
2868 q = repo.mq
2832 mergeq = None
2869 mergeq = None
2833
2870
2834 opts = fixkeepchangesopts(ui, opts)
2871 opts = fixkeepchangesopts(ui, opts)
2835 if opts.get('merge'):
2872 if opts.get('merge'):
2836 if opts.get('name'):
2873 if opts.get('name'):
2837 newpath = repo.join(opts.get('name'))
2874 newpath = repo.join(opts.get('name'))
2838 else:
2875 else:
2839 newpath, i = lastsavename(q.path)
2876 newpath, i = lastsavename(q.path)
2840 if not newpath:
2877 if not newpath:
2841 ui.warn(_("no saved queues found, please use -n\n"))
2878 ui.warn(_("no saved queues found, please use -n\n"))
2842 return 1
2879 return 1
2843 mergeq = queue(ui, repo.baseui, repo.path, newpath)
2880 mergeq = queue(ui, repo.baseui, repo.path, newpath)
2844 ui.warn(_("merging with queue at: %s\n") % mergeq.path)
2881 ui.warn(_("merging with queue at: %s\n") % mergeq.path)
2845 ret = q.push(repo, patch, force=opts.get('force'), list=opts.get('list'),
2882 ret = q.push(repo, patch, force=opts.get('force'), list=opts.get('list'),
2846 mergeq=mergeq, all=opts.get('all'), move=opts.get('move'),
2883 mergeq=mergeq, all=opts.get('all'), move=opts.get('move'),
2847 exact=opts.get('exact'), nobackup=opts.get('no_backup'),
2884 exact=opts.get('exact'), nobackup=opts.get('no_backup'),
2848 keepchanges=opts.get('keep_changes'))
2885 keepchanges=opts.get('keep_changes'))
2849 return ret
2886 return ret
2850
2887
2851 @command("^qpop",
2888 @command("^qpop",
2852 [('a', 'all', None, _('pop all patches')),
2889 [('a', 'all', None, _('pop all patches')),
2853 ('n', 'name', '',
2890 ('n', 'name', '',
2854 _('queue name to pop (DEPRECATED)'), _('NAME')),
2891 _('queue name to pop (DEPRECATED)'), _('NAME')),
2855 ('', 'keep-changes', None,
2892 ('', 'keep-changes', None,
2856 _('tolerate non-conflicting local changes')),
2893 _('tolerate non-conflicting local changes')),
2857 ('f', 'force', None, _('forget any local changes to patched files')),
2894 ('f', 'force', None, _('forget any local changes to patched files')),
2858 ('', 'no-backup', None, _('do not save backup copies of files'))],
2895 ('', 'no-backup', None, _('do not save backup copies of files'))],
2859 _('hg qpop [-a] [-f] [PATCH | INDEX]'))
2896 _('hg qpop [-a] [-f] [PATCH | INDEX]'))
2860 def pop(ui, repo, patch=None, **opts):
2897 def pop(ui, repo, patch=None, **opts):
2861 """pop the current patch off the stack
2898 """pop the current patch off the stack
2862
2899
2863 Without argument, pops off the top of the patch stack. If given a
2900 Without argument, pops off the top of the patch stack. If given a
2864 patch name, keeps popping off patches until the named patch is at
2901 patch name, keeps popping off patches until the named patch is at
2865 the top of the stack.
2902 the top of the stack.
2866
2903
2867 By default, abort if the working directory contains uncommitted
2904 By default, abort if the working directory contains uncommitted
2868 changes. With --keep-changes, abort only if the uncommitted files
2905 changes. With --keep-changes, abort only if the uncommitted files
2869 overlap with patched files. With -f/--force, backup and discard
2906 overlap with patched files. With -f/--force, backup and discard
2870 changes made to such files.
2907 changes made to such files.
2871
2908
2872 Return 0 on success.
2909 Return 0 on success.
2873 """
2910 """
2874 opts = fixkeepchangesopts(ui, opts)
2911 opts = fixkeepchangesopts(ui, opts)
2875 localupdate = True
2912 localupdate = True
2876 if opts.get('name'):
2913 if opts.get('name'):
2877 q = queue(ui, repo.baseui, repo.path, repo.join(opts.get('name')))
2914 q = queue(ui, repo.baseui, repo.path, repo.join(opts.get('name')))
2878 ui.warn(_('using patch queue: %s\n') % q.path)
2915 ui.warn(_('using patch queue: %s\n') % q.path)
2879 localupdate = False
2916 localupdate = False
2880 else:
2917 else:
2881 q = repo.mq
2918 q = repo.mq
2882 ret = q.pop(repo, patch, force=opts.get('force'), update=localupdate,
2919 ret = q.pop(repo, patch, force=opts.get('force'), update=localupdate,
2883 all=opts.get('all'), nobackup=opts.get('no_backup'),
2920 all=opts.get('all'), nobackup=opts.get('no_backup'),
2884 keepchanges=opts.get('keep_changes'))
2921 keepchanges=opts.get('keep_changes'))
2885 q.savedirty()
2922 q.savedirty()
2886 return ret
2923 return ret
2887
2924
2888 @command("qrename|qmv", [], _('hg qrename PATCH1 [PATCH2]'))
2925 @command("qrename|qmv", [], _('hg qrename PATCH1 [PATCH2]'))
2889 def rename(ui, repo, patch, name=None, **opts):
2926 def rename(ui, repo, patch, name=None, **opts):
2890 """rename a patch
2927 """rename a patch
2891
2928
2892 With one argument, renames the current patch to PATCH1.
2929 With one argument, renames the current patch to PATCH1.
2893 With two arguments, renames PATCH1 to PATCH2.
2930 With two arguments, renames PATCH1 to PATCH2.
2894
2931
2895 Returns 0 on success."""
2932 Returns 0 on success."""
2896 q = repo.mq
2933 q = repo.mq
2897 if not name:
2934 if not name:
2898 name = patch
2935 name = patch
2899 patch = None
2936 patch = None
2900
2937
2901 if patch:
2938 if patch:
2902 patch = q.lookup(patch)
2939 patch = q.lookup(patch)
2903 else:
2940 else:
2904 if not q.applied:
2941 if not q.applied:
2905 ui.write(_('no patches applied\n'))
2942 ui.write(_('no patches applied\n'))
2906 return
2943 return
2907 patch = q.lookup('qtip')
2944 patch = q.lookup('qtip')
2908 absdest = q.join(name)
2945 absdest = q.join(name)
2909 if os.path.isdir(absdest):
2946 if os.path.isdir(absdest):
2910 name = normname(os.path.join(name, os.path.basename(patch)))
2947 name = normname(os.path.join(name, os.path.basename(patch)))
2911 absdest = q.join(name)
2948 absdest = q.join(name)
2912 q.checkpatchname(name)
2949 q.checkpatchname(name)
2913
2950
2914 ui.note(_('renaming %s to %s\n') % (patch, name))
2951 ui.note(_('renaming %s to %s\n') % (patch, name))
2915 i = q.findseries(patch)
2952 i = q.findseries(patch)
2916 guards = q.guard_re.findall(q.fullseries[i])
2953 guards = q.guard_re.findall(q.fullseries[i])
2917 q.fullseries[i] = name + ''.join([' #' + g for g in guards])
2954 q.fullseries[i] = name + ''.join([' #' + g for g in guards])
2918 q.parseseries()
2955 q.parseseries()
2919 q.seriesdirty = True
2956 q.seriesdirty = True
2920
2957
2921 info = q.isapplied(patch)
2958 info = q.isapplied(patch)
2922 if info:
2959 if info:
2923 q.applied[info[0]] = statusentry(info[1], name)
2960 q.applied[info[0]] = statusentry(info[1], name)
2924 q.applieddirty = True
2961 q.applieddirty = True
2925
2962
2926 destdir = os.path.dirname(absdest)
2963 destdir = os.path.dirname(absdest)
2927 if not os.path.isdir(destdir):
2964 if not os.path.isdir(destdir):
2928 os.makedirs(destdir)
2965 os.makedirs(destdir)
2929 util.rename(q.join(patch), absdest)
2966 util.rename(q.join(patch), absdest)
2930 r = q.qrepo()
2967 r = q.qrepo()
2931 if r and patch in r.dirstate:
2968 if r and patch in r.dirstate:
2932 wctx = r[None]
2969 wctx = r[None]
2933 wlock = r.wlock()
2970 wlock = r.wlock()
2934 try:
2971 try:
2935 if r.dirstate[patch] == 'a':
2972 if r.dirstate[patch] == 'a':
2936 r.dirstate.drop(patch)
2973 r.dirstate.drop(patch)
2937 r.dirstate.add(name)
2974 r.dirstate.add(name)
2938 else:
2975 else:
2939 wctx.copy(patch, name)
2976 wctx.copy(patch, name)
2940 wctx.forget([patch])
2977 wctx.forget([patch])
2941 finally:
2978 finally:
2942 wlock.release()
2979 wlock.release()
2943
2980
2944 q.savedirty()
2981 q.savedirty()
2945
2982
2946 @command("qrestore",
2983 @command("qrestore",
2947 [('d', 'delete', None, _('delete save entry')),
2984 [('d', 'delete', None, _('delete save entry')),
2948 ('u', 'update', None, _('update queue working directory'))],
2985 ('u', 'update', None, _('update queue working directory'))],
2949 _('hg qrestore [-d] [-u] REV'))
2986 _('hg qrestore [-d] [-u] REV'))
2950 def restore(ui, repo, rev, **opts):
2987 def restore(ui, repo, rev, **opts):
2951 """restore the queue state saved by a revision (DEPRECATED)
2988 """restore the queue state saved by a revision (DEPRECATED)
2952
2989
2953 This command is deprecated, use :hg:`rebase` instead."""
2990 This command is deprecated, use :hg:`rebase` instead."""
2954 rev = repo.lookup(rev)
2991 rev = repo.lookup(rev)
2955 q = repo.mq
2992 q = repo.mq
2956 q.restore(repo, rev, delete=opts.get('delete'),
2993 q.restore(repo, rev, delete=opts.get('delete'),
2957 qupdate=opts.get('update'))
2994 qupdate=opts.get('update'))
2958 q.savedirty()
2995 q.savedirty()
2959 return 0
2996 return 0
2960
2997
2961 @command("qsave",
2998 @command("qsave",
2962 [('c', 'copy', None, _('copy patch directory')),
2999 [('c', 'copy', None, _('copy patch directory')),
2963 ('n', 'name', '',
3000 ('n', 'name', '',
2964 _('copy directory name'), _('NAME')),
3001 _('copy directory name'), _('NAME')),
2965 ('e', 'empty', None, _('clear queue status file')),
3002 ('e', 'empty', None, _('clear queue status file')),
2966 ('f', 'force', None, _('force copy'))] + commands.commitopts,
3003 ('f', 'force', None, _('force copy'))] + commands.commitopts,
2967 _('hg qsave [-m TEXT] [-l FILE] [-c] [-n NAME] [-e] [-f]'))
3004 _('hg qsave [-m TEXT] [-l FILE] [-c] [-n NAME] [-e] [-f]'))
2968 def save(ui, repo, **opts):
3005 def save(ui, repo, **opts):
2969 """save current queue state (DEPRECATED)
3006 """save current queue state (DEPRECATED)
2970
3007
2971 This command is deprecated, use :hg:`rebase` instead."""
3008 This command is deprecated, use :hg:`rebase` instead."""
2972 q = repo.mq
3009 q = repo.mq
2973 message = cmdutil.logmessage(ui, opts)
3010 message = cmdutil.logmessage(ui, opts)
2974 ret = q.save(repo, msg=message)
3011 ret = q.save(repo, msg=message)
2975 if ret:
3012 if ret:
2976 return ret
3013 return ret
2977 q.savedirty() # save to .hg/patches before copying
3014 q.savedirty() # save to .hg/patches before copying
2978 if opts.get('copy'):
3015 if opts.get('copy'):
2979 path = q.path
3016 path = q.path
2980 if opts.get('name'):
3017 if opts.get('name'):
2981 newpath = os.path.join(q.basepath, opts.get('name'))
3018 newpath = os.path.join(q.basepath, opts.get('name'))
2982 if os.path.exists(newpath):
3019 if os.path.exists(newpath):
2983 if not os.path.isdir(newpath):
3020 if not os.path.isdir(newpath):
2984 raise util.Abort(_('destination %s exists and is not '
3021 raise util.Abort(_('destination %s exists and is not '
2985 'a directory') % newpath)
3022 'a directory') % newpath)
2986 if not opts.get('force'):
3023 if not opts.get('force'):
2987 raise util.Abort(_('destination %s exists, '
3024 raise util.Abort(_('destination %s exists, '
2988 'use -f to force') % newpath)
3025 'use -f to force') % newpath)
2989 else:
3026 else:
2990 newpath = savename(path)
3027 newpath = savename(path)
2991 ui.warn(_("copy %s to %s\n") % (path, newpath))
3028 ui.warn(_("copy %s to %s\n") % (path, newpath))
2992 util.copyfiles(path, newpath)
3029 util.copyfiles(path, newpath)
2993 if opts.get('empty'):
3030 if opts.get('empty'):
2994 del q.applied[:]
3031 del q.applied[:]
2995 q.applieddirty = True
3032 q.applieddirty = True
2996 q.savedirty()
3033 q.savedirty()
2997 return 0
3034 return 0
2998
3035
2999
3036
3000 @command("qselect",
3037 @command("qselect",
3001 [('n', 'none', None, _('disable all guards')),
3038 [('n', 'none', None, _('disable all guards')),
3002 ('s', 'series', None, _('list all guards in series file')),
3039 ('s', 'series', None, _('list all guards in series file')),
3003 ('', 'pop', None, _('pop to before first guarded applied patch')),
3040 ('', 'pop', None, _('pop to before first guarded applied patch')),
3004 ('', 'reapply', None, _('pop, then reapply patches'))],
3041 ('', 'reapply', None, _('pop, then reapply patches'))],
3005 _('hg qselect [OPTION]... [GUARD]...'))
3042 _('hg qselect [OPTION]... [GUARD]...'))
3006 def select(ui, repo, *args, **opts):
3043 def select(ui, repo, *args, **opts):
3007 '''set or print guarded patches to push
3044 '''set or print guarded patches to push
3008
3045
3009 Use the :hg:`qguard` command to set or print guards on patch, then use
3046 Use the :hg:`qguard` command to set or print guards on patch, then use
3010 qselect to tell mq which guards to use. A patch will be pushed if
3047 qselect to tell mq which guards to use. A patch will be pushed if
3011 it has no guards or any positive guards match the currently
3048 it has no guards or any positive guards match the currently
3012 selected guard, but will not be pushed if any negative guards
3049 selected guard, but will not be pushed if any negative guards
3013 match the current guard. For example::
3050 match the current guard. For example::
3014
3051
3015 qguard foo.patch -- -stable (negative guard)
3052 qguard foo.patch -- -stable (negative guard)
3016 qguard bar.patch +stable (positive guard)
3053 qguard bar.patch +stable (positive guard)
3017 qselect stable
3054 qselect stable
3018
3055
3019 This activates the "stable" guard. mq will skip foo.patch (because
3056 This activates the "stable" guard. mq will skip foo.patch (because
3020 it has a negative match) but push bar.patch (because it has a
3057 it has a negative match) but push bar.patch (because it has a
3021 positive match).
3058 positive match).
3022
3059
3023 With no arguments, prints the currently active guards.
3060 With no arguments, prints the currently active guards.
3024 With one argument, sets the active guard.
3061 With one argument, sets the active guard.
3025
3062
3026 Use -n/--none to deactivate guards (no other arguments needed).
3063 Use -n/--none to deactivate guards (no other arguments needed).
3027 When no guards are active, patches with positive guards are
3064 When no guards are active, patches with positive guards are
3028 skipped and patches with negative guards are pushed.
3065 skipped and patches with negative guards are pushed.
3029
3066
3030 qselect can change the guards on applied patches. It does not pop
3067 qselect can change the guards on applied patches. It does not pop
3031 guarded patches by default. Use --pop to pop back to the last
3068 guarded patches by default. Use --pop to pop back to the last
3032 applied patch that is not guarded. Use --reapply (which implies
3069 applied patch that is not guarded. Use --reapply (which implies
3033 --pop) to push back to the current patch afterwards, but skip
3070 --pop) to push back to the current patch afterwards, but skip
3034 guarded patches.
3071 guarded patches.
3035
3072
3036 Use -s/--series to print a list of all guards in the series file
3073 Use -s/--series to print a list of all guards in the series file
3037 (no other arguments needed). Use -v for more information.
3074 (no other arguments needed). Use -v for more information.
3038
3075
3039 Returns 0 on success.'''
3076 Returns 0 on success.'''
3040
3077
3041 q = repo.mq
3078 q = repo.mq
3042 guards = q.active()
3079 guards = q.active()
3043 pushable = lambda i: q.pushable(q.applied[i].name)[0]
3080 pushable = lambda i: q.pushable(q.applied[i].name)[0]
3044 if args or opts.get('none'):
3081 if args or opts.get('none'):
3045 old_unapplied = q.unapplied(repo)
3082 old_unapplied = q.unapplied(repo)
3046 old_guarded = [i for i in xrange(len(q.applied)) if not pushable(i)]
3083 old_guarded = [i for i in xrange(len(q.applied)) if not pushable(i)]
3047 q.setactive(args)
3084 q.setactive(args)
3048 q.savedirty()
3085 q.savedirty()
3049 if not args:
3086 if not args:
3050 ui.status(_('guards deactivated\n'))
3087 ui.status(_('guards deactivated\n'))
3051 if not opts.get('pop') and not opts.get('reapply'):
3088 if not opts.get('pop') and not opts.get('reapply'):
3052 unapplied = q.unapplied(repo)
3089 unapplied = q.unapplied(repo)
3053 guarded = [i for i in xrange(len(q.applied)) if not pushable(i)]
3090 guarded = [i for i in xrange(len(q.applied)) if not pushable(i)]
3054 if len(unapplied) != len(old_unapplied):
3091 if len(unapplied) != len(old_unapplied):
3055 ui.status(_('number of unguarded, unapplied patches has '
3092 ui.status(_('number of unguarded, unapplied patches has '
3056 'changed from %d to %d\n') %
3093 'changed from %d to %d\n') %
3057 (len(old_unapplied), len(unapplied)))
3094 (len(old_unapplied), len(unapplied)))
3058 if len(guarded) != len(old_guarded):
3095 if len(guarded) != len(old_guarded):
3059 ui.status(_('number of guarded, applied patches has changed '
3096 ui.status(_('number of guarded, applied patches has changed '
3060 'from %d to %d\n') %
3097 'from %d to %d\n') %
3061 (len(old_guarded), len(guarded)))
3098 (len(old_guarded), len(guarded)))
3062 elif opts.get('series'):
3099 elif opts.get('series'):
3063 guards = {}
3100 guards = {}
3064 noguards = 0
3101 noguards = 0
3065 for gs in q.seriesguards:
3102 for gs in q.seriesguards:
3066 if not gs:
3103 if not gs:
3067 noguards += 1
3104 noguards += 1
3068 for g in gs:
3105 for g in gs:
3069 guards.setdefault(g, 0)
3106 guards.setdefault(g, 0)
3070 guards[g] += 1
3107 guards[g] += 1
3071 if ui.verbose:
3108 if ui.verbose:
3072 guards['NONE'] = noguards
3109 guards['NONE'] = noguards
3073 guards = guards.items()
3110 guards = guards.items()
3074 guards.sort(key=lambda x: x[0][1:])
3111 guards.sort(key=lambda x: x[0][1:])
3075 if guards:
3112 if guards:
3076 ui.note(_('guards in series file:\n'))
3113 ui.note(_('guards in series file:\n'))
3077 for guard, count in guards:
3114 for guard, count in guards:
3078 ui.note('%2d ' % count)
3115 ui.note('%2d ' % count)
3079 ui.write(guard, '\n')
3116 ui.write(guard, '\n')
3080 else:
3117 else:
3081 ui.note(_('no guards in series file\n'))
3118 ui.note(_('no guards in series file\n'))
3082 else:
3119 else:
3083 if guards:
3120 if guards:
3084 ui.note(_('active guards:\n'))
3121 ui.note(_('active guards:\n'))
3085 for g in guards:
3122 for g in guards:
3086 ui.write(g, '\n')
3123 ui.write(g, '\n')
3087 else:
3124 else:
3088 ui.write(_('no active guards\n'))
3125 ui.write(_('no active guards\n'))
3089 reapply = opts.get('reapply') and q.applied and q.applied[-1].name
3126 reapply = opts.get('reapply') and q.applied and q.applied[-1].name
3090 popped = False
3127 popped = False
3091 if opts.get('pop') or opts.get('reapply'):
3128 if opts.get('pop') or opts.get('reapply'):
3092 for i in xrange(len(q.applied)):
3129 for i in xrange(len(q.applied)):
3093 if not pushable(i):
3130 if not pushable(i):
3094 ui.status(_('popping guarded patches\n'))
3131 ui.status(_('popping guarded patches\n'))
3095 popped = True
3132 popped = True
3096 if i == 0:
3133 if i == 0:
3097 q.pop(repo, all=True)
3134 q.pop(repo, all=True)
3098 else:
3135 else:
3099 q.pop(repo, q.applied[i - 1].name)
3136 q.pop(repo, q.applied[i - 1].name)
3100 break
3137 break
3101 if popped:
3138 if popped:
3102 try:
3139 try:
3103 if reapply:
3140 if reapply:
3104 ui.status(_('reapplying unguarded patches\n'))
3141 ui.status(_('reapplying unguarded patches\n'))
3105 q.push(repo, reapply)
3142 q.push(repo, reapply)
3106 finally:
3143 finally:
3107 q.savedirty()
3144 q.savedirty()
3108
3145
3109 @command("qfinish",
3146 @command("qfinish",
3110 [('a', 'applied', None, _('finish all applied changesets'))],
3147 [('a', 'applied', None, _('finish all applied changesets'))],
3111 _('hg qfinish [-a] [REV]...'))
3148 _('hg qfinish [-a] [REV]...'))
3112 def finish(ui, repo, *revrange, **opts):
3149 def finish(ui, repo, *revrange, **opts):
3113 """move applied patches into repository history
3150 """move applied patches into repository history
3114
3151
3115 Finishes the specified revisions (corresponding to applied
3152 Finishes the specified revisions (corresponding to applied
3116 patches) by moving them out of mq control into regular repository
3153 patches) by moving them out of mq control into regular repository
3117 history.
3154 history.
3118
3155
3119 Accepts a revision range or the -a/--applied option. If --applied
3156 Accepts a revision range or the -a/--applied option. If --applied
3120 is specified, all applied mq revisions are removed from mq
3157 is specified, all applied mq revisions are removed from mq
3121 control. Otherwise, the given revisions must be at the base of the
3158 control. Otherwise, the given revisions must be at the base of the
3122 stack of applied patches.
3159 stack of applied patches.
3123
3160
3124 This can be especially useful if your changes have been applied to
3161 This can be especially useful if your changes have been applied to
3125 an upstream repository, or if you are about to push your changes
3162 an upstream repository, or if you are about to push your changes
3126 to upstream.
3163 to upstream.
3127
3164
3128 Returns 0 on success.
3165 Returns 0 on success.
3129 """
3166 """
3130 if not opts.get('applied') and not revrange:
3167 if not opts.get('applied') and not revrange:
3131 raise util.Abort(_('no revisions specified'))
3168 raise util.Abort(_('no revisions specified'))
3132 elif opts.get('applied'):
3169 elif opts.get('applied'):
3133 revrange = ('qbase::qtip',) + revrange
3170 revrange = ('qbase::qtip',) + revrange
3134
3171
3135 q = repo.mq
3172 q = repo.mq
3136 if not q.applied:
3173 if not q.applied:
3137 ui.status(_('no patches applied\n'))
3174 ui.status(_('no patches applied\n'))
3138 return 0
3175 return 0
3139
3176
3140 revs = scmutil.revrange(repo, revrange)
3177 revs = scmutil.revrange(repo, revrange)
3141 if repo['.'].rev() in revs and repo[None].files():
3178 if repo['.'].rev() in revs and repo[None].files():
3142 ui.warn(_('warning: uncommitted changes in the working directory\n'))
3179 ui.warn(_('warning: uncommitted changes in the working directory\n'))
3143 # queue.finish may changes phases but leave the responsibility to lock the
3180 # queue.finish may changes phases but leave the responsibility to lock the
3144 # repo to the caller to avoid deadlock with wlock. This command code is
3181 # repo to the caller to avoid deadlock with wlock. This command code is
3145 # responsibility for this locking.
3182 # responsibility for this locking.
3146 lock = repo.lock()
3183 lock = repo.lock()
3147 try:
3184 try:
3148 q.finish(repo, revs)
3185 q.finish(repo, revs)
3149 q.savedirty()
3186 q.savedirty()
3150 finally:
3187 finally:
3151 lock.release()
3188 lock.release()
3152 return 0
3189 return 0
3153
3190
3154 @command("qqueue",
3191 @command("qqueue",
3155 [('l', 'list', False, _('list all available queues')),
3192 [('l', 'list', False, _('list all available queues')),
3156 ('', 'active', False, _('print name of active queue')),
3193 ('', 'active', False, _('print name of active queue')),
3157 ('c', 'create', False, _('create new queue')),
3194 ('c', 'create', False, _('create new queue')),
3158 ('', 'rename', False, _('rename active queue')),
3195 ('', 'rename', False, _('rename active queue')),
3159 ('', 'delete', False, _('delete reference to queue')),
3196 ('', 'delete', False, _('delete reference to queue')),
3160 ('', 'purge', False, _('delete queue, and remove patch dir')),
3197 ('', 'purge', False, _('delete queue, and remove patch dir')),
3161 ],
3198 ],
3162 _('[OPTION] [QUEUE]'))
3199 _('[OPTION] [QUEUE]'))
3163 def qqueue(ui, repo, name=None, **opts):
3200 def qqueue(ui, repo, name=None, **opts):
3164 '''manage multiple patch queues
3201 '''manage multiple patch queues
3165
3202
3166 Supports switching between different patch queues, as well as creating
3203 Supports switching between different patch queues, as well as creating
3167 new patch queues and deleting existing ones.
3204 new patch queues and deleting existing ones.
3168
3205
3169 Omitting a queue name or specifying -l/--list will show you the registered
3206 Omitting a queue name or specifying -l/--list will show you the registered
3170 queues - by default the "normal" patches queue is registered. The currently
3207 queues - by default the "normal" patches queue is registered. The currently
3171 active queue will be marked with "(active)". Specifying --active will print
3208 active queue will be marked with "(active)". Specifying --active will print
3172 only the name of the active queue.
3209 only the name of the active queue.
3173
3210
3174 To create a new queue, use -c/--create. The queue is automatically made
3211 To create a new queue, use -c/--create. The queue is automatically made
3175 active, except in the case where there are applied patches from the
3212 active, except in the case where there are applied patches from the
3176 currently active queue in the repository. Then the queue will only be
3213 currently active queue in the repository. Then the queue will only be
3177 created and switching will fail.
3214 created and switching will fail.
3178
3215
3179 To delete an existing queue, use --delete. You cannot delete the currently
3216 To delete an existing queue, use --delete. You cannot delete the currently
3180 active queue.
3217 active queue.
3181
3218
3182 Returns 0 on success.
3219 Returns 0 on success.
3183 '''
3220 '''
3184 q = repo.mq
3221 q = repo.mq
3185 _defaultqueue = 'patches'
3222 _defaultqueue = 'patches'
3186 _allqueues = 'patches.queues'
3223 _allqueues = 'patches.queues'
3187 _activequeue = 'patches.queue'
3224 _activequeue = 'patches.queue'
3188
3225
3189 def _getcurrent():
3226 def _getcurrent():
3190 cur = os.path.basename(q.path)
3227 cur = os.path.basename(q.path)
3191 if cur.startswith('patches-'):
3228 if cur.startswith('patches-'):
3192 cur = cur[8:]
3229 cur = cur[8:]
3193 return cur
3230 return cur
3194
3231
3195 def _noqueues():
3232 def _noqueues():
3196 try:
3233 try:
3197 fh = repo.opener(_allqueues, 'r')
3234 fh = repo.opener(_allqueues, 'r')
3198 fh.close()
3235 fh.close()
3199 except IOError:
3236 except IOError:
3200 return True
3237 return True
3201
3238
3202 return False
3239 return False
3203
3240
3204 def _getqueues():
3241 def _getqueues():
3205 current = _getcurrent()
3242 current = _getcurrent()
3206
3243
3207 try:
3244 try:
3208 fh = repo.opener(_allqueues, 'r')
3245 fh = repo.opener(_allqueues, 'r')
3209 queues = [queue.strip() for queue in fh if queue.strip()]
3246 queues = [queue.strip() for queue in fh if queue.strip()]
3210 fh.close()
3247 fh.close()
3211 if current not in queues:
3248 if current not in queues:
3212 queues.append(current)
3249 queues.append(current)
3213 except IOError:
3250 except IOError:
3214 queues = [_defaultqueue]
3251 queues = [_defaultqueue]
3215
3252
3216 return sorted(queues)
3253 return sorted(queues)
3217
3254
3218 def _setactive(name):
3255 def _setactive(name):
3219 if q.applied:
3256 if q.applied:
3220 raise util.Abort(_('new queue created, but cannot make active '
3257 raise util.Abort(_('new queue created, but cannot make active '
3221 'as patches are applied'))
3258 'as patches are applied'))
3222 _setactivenocheck(name)
3259 _setactivenocheck(name)
3223
3260
3224 def _setactivenocheck(name):
3261 def _setactivenocheck(name):
3225 fh = repo.opener(_activequeue, 'w')
3262 fh = repo.opener(_activequeue, 'w')
3226 if name != 'patches':
3263 if name != 'patches':
3227 fh.write(name)
3264 fh.write(name)
3228 fh.close()
3265 fh.close()
3229
3266
3230 def _addqueue(name):
3267 def _addqueue(name):
3231 fh = repo.opener(_allqueues, 'a')
3268 fh = repo.opener(_allqueues, 'a')
3232 fh.write('%s\n' % (name,))
3269 fh.write('%s\n' % (name,))
3233 fh.close()
3270 fh.close()
3234
3271
3235 def _queuedir(name):
3272 def _queuedir(name):
3236 if name == 'patches':
3273 if name == 'patches':
3237 return repo.join('patches')
3274 return repo.join('patches')
3238 else:
3275 else:
3239 return repo.join('patches-' + name)
3276 return repo.join('patches-' + name)
3240
3277
3241 def _validname(name):
3278 def _validname(name):
3242 for n in name:
3279 for n in name:
3243 if n in ':\\/.':
3280 if n in ':\\/.':
3244 return False
3281 return False
3245 return True
3282 return True
3246
3283
3247 def _delete(name):
3284 def _delete(name):
3248 if name not in existing:
3285 if name not in existing:
3249 raise util.Abort(_('cannot delete queue that does not exist'))
3286 raise util.Abort(_('cannot delete queue that does not exist'))
3250
3287
3251 current = _getcurrent()
3288 current = _getcurrent()
3252
3289
3253 if name == current:
3290 if name == current:
3254 raise util.Abort(_('cannot delete currently active queue'))
3291 raise util.Abort(_('cannot delete currently active queue'))
3255
3292
3256 fh = repo.opener('patches.queues.new', 'w')
3293 fh = repo.opener('patches.queues.new', 'w')
3257 for queue in existing:
3294 for queue in existing:
3258 if queue == name:
3295 if queue == name:
3259 continue
3296 continue
3260 fh.write('%s\n' % (queue,))
3297 fh.write('%s\n' % (queue,))
3261 fh.close()
3298 fh.close()
3262 util.rename(repo.join('patches.queues.new'), repo.join(_allqueues))
3299 util.rename(repo.join('patches.queues.new'), repo.join(_allqueues))
3263
3300
3264 if not name or opts.get('list') or opts.get('active'):
3301 if not name or opts.get('list') or opts.get('active'):
3265 current = _getcurrent()
3302 current = _getcurrent()
3266 if opts.get('active'):
3303 if opts.get('active'):
3267 ui.write('%s\n' % (current,))
3304 ui.write('%s\n' % (current,))
3268 return
3305 return
3269 for queue in _getqueues():
3306 for queue in _getqueues():
3270 ui.write('%s' % (queue,))
3307 ui.write('%s' % (queue,))
3271 if queue == current and not ui.quiet:
3308 if queue == current and not ui.quiet:
3272 ui.write(_(' (active)\n'))
3309 ui.write(_(' (active)\n'))
3273 else:
3310 else:
3274 ui.write('\n')
3311 ui.write('\n')
3275 return
3312 return
3276
3313
3277 if not _validname(name):
3314 if not _validname(name):
3278 raise util.Abort(
3315 raise util.Abort(
3279 _('invalid queue name, may not contain the characters ":\\/."'))
3316 _('invalid queue name, may not contain the characters ":\\/."'))
3280
3317
3281 existing = _getqueues()
3318 existing = _getqueues()
3282
3319
3283 if opts.get('create'):
3320 if opts.get('create'):
3284 if name in existing:
3321 if name in existing:
3285 raise util.Abort(_('queue "%s" already exists') % name)
3322 raise util.Abort(_('queue "%s" already exists') % name)
3286 if _noqueues():
3323 if _noqueues():
3287 _addqueue(_defaultqueue)
3324 _addqueue(_defaultqueue)
3288 _addqueue(name)
3325 _addqueue(name)
3289 _setactive(name)
3326 _setactive(name)
3290 elif opts.get('rename'):
3327 elif opts.get('rename'):
3291 current = _getcurrent()
3328 current = _getcurrent()
3292 if name == current:
3329 if name == current:
3293 raise util.Abort(_('can\'t rename "%s" to its current name') % name)
3330 raise util.Abort(_('can\'t rename "%s" to its current name') % name)
3294 if name in existing:
3331 if name in existing:
3295 raise util.Abort(_('queue "%s" already exists') % name)
3332 raise util.Abort(_('queue "%s" already exists') % name)
3296
3333
3297 olddir = _queuedir(current)
3334 olddir = _queuedir(current)
3298 newdir = _queuedir(name)
3335 newdir = _queuedir(name)
3299
3336
3300 if os.path.exists(newdir):
3337 if os.path.exists(newdir):
3301 raise util.Abort(_('non-queue directory "%s" already exists') %
3338 raise util.Abort(_('non-queue directory "%s" already exists') %
3302 newdir)
3339 newdir)
3303
3340
3304 fh = repo.opener('patches.queues.new', 'w')
3341 fh = repo.opener('patches.queues.new', 'w')
3305 for queue in existing:
3342 for queue in existing:
3306 if queue == current:
3343 if queue == current:
3307 fh.write('%s\n' % (name,))
3344 fh.write('%s\n' % (name,))
3308 if os.path.exists(olddir):
3345 if os.path.exists(olddir):
3309 util.rename(olddir, newdir)
3346 util.rename(olddir, newdir)
3310 else:
3347 else:
3311 fh.write('%s\n' % (queue,))
3348 fh.write('%s\n' % (queue,))
3312 fh.close()
3349 fh.close()
3313 util.rename(repo.join('patches.queues.new'), repo.join(_allqueues))
3350 util.rename(repo.join('patches.queues.new'), repo.join(_allqueues))
3314 _setactivenocheck(name)
3351 _setactivenocheck(name)
3315 elif opts.get('delete'):
3352 elif opts.get('delete'):
3316 _delete(name)
3353 _delete(name)
3317 elif opts.get('purge'):
3354 elif opts.get('purge'):
3318 if name in existing:
3355 if name in existing:
3319 _delete(name)
3356 _delete(name)
3320 qdir = _queuedir(name)
3357 qdir = _queuedir(name)
3321 if os.path.exists(qdir):
3358 if os.path.exists(qdir):
3322 shutil.rmtree(qdir)
3359 shutil.rmtree(qdir)
3323 else:
3360 else:
3324 if name not in existing:
3361 if name not in existing:
3325 raise util.Abort(_('use --create to create a new queue'))
3362 raise util.Abort(_('use --create to create a new queue'))
3326 _setactive(name)
3363 _setactive(name)
3327
3364
3328 def mqphasedefaults(repo, roots):
3365 def mqphasedefaults(repo, roots):
3329 """callback used to set mq changeset as secret when no phase data exists"""
3366 """callback used to set mq changeset as secret when no phase data exists"""
3330 if repo.mq.applied:
3367 if repo.mq.applied:
3331 if repo.ui.configbool('mq', 'secret', False):
3368 if repo.ui.configbool('mq', 'secret', False):
3332 mqphase = phases.secret
3369 mqphase = phases.secret
3333 else:
3370 else:
3334 mqphase = phases.draft
3371 mqphase = phases.draft
3335 qbase = repo[repo.mq.applied[0].node]
3372 qbase = repo[repo.mq.applied[0].node]
3336 roots[mqphase].add(qbase.node())
3373 roots[mqphase].add(qbase.node())
3337 return roots
3374 return roots
3338
3375
3339 def reposetup(ui, repo):
3376 def reposetup(ui, repo):
3340 class mqrepo(repo.__class__):
3377 class mqrepo(repo.__class__):
3341 @localrepo.unfilteredpropertycache
3378 @localrepo.unfilteredpropertycache
3342 def mq(self):
3379 def mq(self):
3343 return queue(self.ui, self.baseui, self.path)
3380 return queue(self.ui, self.baseui, self.path)
3344
3381
3345 def invalidateall(self):
3382 def invalidateall(self):
3346 super(mqrepo, self).invalidateall()
3383 super(mqrepo, self).invalidateall()
3347 if localrepo.hasunfilteredcache(self, 'mq'):
3384 if localrepo.hasunfilteredcache(self, 'mq'):
3348 # recreate mq in case queue path was changed
3385 # recreate mq in case queue path was changed
3349 delattr(self.unfiltered(), 'mq')
3386 delattr(self.unfiltered(), 'mq')
3350
3387
3351 def abortifwdirpatched(self, errmsg, force=False):
3388 def abortifwdirpatched(self, errmsg, force=False):
3352 if self.mq.applied and self.mq.checkapplied and not force:
3389 if self.mq.applied and self.mq.checkapplied and not force:
3353 parents = self.dirstate.parents()
3390 parents = self.dirstate.parents()
3354 patches = [s.node for s in self.mq.applied]
3391 patches = [s.node for s in self.mq.applied]
3355 if parents[0] in patches or parents[1] in patches:
3392 if parents[0] in patches or parents[1] in patches:
3356 raise util.Abort(errmsg)
3393 raise util.Abort(errmsg)
3357
3394
3358 def commit(self, text="", user=None, date=None, match=None,
3395 def commit(self, text="", user=None, date=None, match=None,
3359 force=False, editor=False, extra={}):
3396 force=False, editor=False, extra={}):
3360 self.abortifwdirpatched(
3397 self.abortifwdirpatched(
3361 _('cannot commit over an applied mq patch'),
3398 _('cannot commit over an applied mq patch'),
3362 force)
3399 force)
3363
3400
3364 return super(mqrepo, self).commit(text, user, date, match, force,
3401 return super(mqrepo, self).commit(text, user, date, match, force,
3365 editor, extra)
3402 editor, extra)
3366
3403
3367 def checkpush(self, pushop):
3404 def checkpush(self, pushop):
3368 if self.mq.applied and self.mq.checkapplied and not pushop.force:
3405 if self.mq.applied and self.mq.checkapplied and not pushop.force:
3369 outapplied = [e.node for e in self.mq.applied]
3406 outapplied = [e.node for e in self.mq.applied]
3370 if pushop.revs:
3407 if pushop.revs:
3371 # Assume applied patches have no non-patch descendants and
3408 # Assume applied patches have no non-patch descendants and
3372 # are not on remote already. Filtering any changeset not
3409 # are not on remote already. Filtering any changeset not
3373 # pushed.
3410 # pushed.
3374 heads = set(pushop.revs)
3411 heads = set(pushop.revs)
3375 for node in reversed(outapplied):
3412 for node in reversed(outapplied):
3376 if node in heads:
3413 if node in heads:
3377 break
3414 break
3378 else:
3415 else:
3379 outapplied.pop()
3416 outapplied.pop()
3380 # looking for pushed and shared changeset
3417 # looking for pushed and shared changeset
3381 for node in outapplied:
3418 for node in outapplied:
3382 if self[node].phase() < phases.secret:
3419 if self[node].phase() < phases.secret:
3383 raise util.Abort(_('source has mq patches applied'))
3420 raise util.Abort(_('source has mq patches applied'))
3384 # no non-secret patches pushed
3421 # no non-secret patches pushed
3385 super(mqrepo, self).checkpush(pushop)
3422 super(mqrepo, self).checkpush(pushop)
3386
3423
3387 def _findtags(self):
3424 def _findtags(self):
3388 '''augment tags from base class with patch tags'''
3425 '''augment tags from base class with patch tags'''
3389 result = super(mqrepo, self)._findtags()
3426 result = super(mqrepo, self)._findtags()
3390
3427
3391 q = self.mq
3428 q = self.mq
3392 if not q.applied:
3429 if not q.applied:
3393 return result
3430 return result
3394
3431
3395 mqtags = [(patch.node, patch.name) for patch in q.applied]
3432 mqtags = [(patch.node, patch.name) for patch in q.applied]
3396
3433
3397 try:
3434 try:
3398 # for now ignore filtering business
3435 # for now ignore filtering business
3399 self.unfiltered().changelog.rev(mqtags[-1][0])
3436 self.unfiltered().changelog.rev(mqtags[-1][0])
3400 except error.LookupError:
3437 except error.LookupError:
3401 self.ui.warn(_('mq status file refers to unknown node %s\n')
3438 self.ui.warn(_('mq status file refers to unknown node %s\n')
3402 % short(mqtags[-1][0]))
3439 % short(mqtags[-1][0]))
3403 return result
3440 return result
3404
3441
3405 # do not add fake tags for filtered revisions
3442 # do not add fake tags for filtered revisions
3406 included = self.changelog.hasnode
3443 included = self.changelog.hasnode
3407 mqtags = [mqt for mqt in mqtags if included(mqt[0])]
3444 mqtags = [mqt for mqt in mqtags if included(mqt[0])]
3408 if not mqtags:
3445 if not mqtags:
3409 return result
3446 return result
3410
3447
3411 mqtags.append((mqtags[-1][0], 'qtip'))
3448 mqtags.append((mqtags[-1][0], 'qtip'))
3412 mqtags.append((mqtags[0][0], 'qbase'))
3449 mqtags.append((mqtags[0][0], 'qbase'))
3413 mqtags.append((self.changelog.parents(mqtags[0][0])[0], 'qparent'))
3450 mqtags.append((self.changelog.parents(mqtags[0][0])[0], 'qparent'))
3414 tags = result[0]
3451 tags = result[0]
3415 for patch in mqtags:
3452 for patch in mqtags:
3416 if patch[1] in tags:
3453 if patch[1] in tags:
3417 self.ui.warn(_('tag %s overrides mq patch of the same '
3454 self.ui.warn(_('tag %s overrides mq patch of the same '
3418 'name\n') % patch[1])
3455 'name\n') % patch[1])
3419 else:
3456 else:
3420 tags[patch[1]] = patch[0]
3457 tags[patch[1]] = patch[0]
3421
3458
3422 return result
3459 return result
3423
3460
3424 if repo.local():
3461 if repo.local():
3425 repo.__class__ = mqrepo
3462 repo.__class__ = mqrepo
3426
3463
3427 repo._phasedefaults.append(mqphasedefaults)
3464 repo._phasedefaults.append(mqphasedefaults)
3428
3465
3429 def mqimport(orig, ui, repo, *args, **kwargs):
3466 def mqimport(orig, ui, repo, *args, **kwargs):
3430 if (util.safehasattr(repo, 'abortifwdirpatched')
3467 if (util.safehasattr(repo, 'abortifwdirpatched')
3431 and not kwargs.get('no_commit', False)):
3468 and not kwargs.get('no_commit', False)):
3432 repo.abortifwdirpatched(_('cannot import over an applied patch'),
3469 repo.abortifwdirpatched(_('cannot import over an applied patch'),
3433 kwargs.get('force'))
3470 kwargs.get('force'))
3434 return orig(ui, repo, *args, **kwargs)
3471 return orig(ui, repo, *args, **kwargs)
3435
3472
3436 def mqinit(orig, ui, *args, **kwargs):
3473 def mqinit(orig, ui, *args, **kwargs):
3437 mq = kwargs.pop('mq', None)
3474 mq = kwargs.pop('mq', None)
3438
3475
3439 if not mq:
3476 if not mq:
3440 return orig(ui, *args, **kwargs)
3477 return orig(ui, *args, **kwargs)
3441
3478
3442 if args:
3479 if args:
3443 repopath = args[0]
3480 repopath = args[0]
3444 if not hg.islocal(repopath):
3481 if not hg.islocal(repopath):
3445 raise util.Abort(_('only a local queue repository '
3482 raise util.Abort(_('only a local queue repository '
3446 'may be initialized'))
3483 'may be initialized'))
3447 else:
3484 else:
3448 repopath = cmdutil.findrepo(os.getcwd())
3485 repopath = cmdutil.findrepo(os.getcwd())
3449 if not repopath:
3486 if not repopath:
3450 raise util.Abort(_('there is no Mercurial repository here '
3487 raise util.Abort(_('there is no Mercurial repository here '
3451 '(.hg not found)'))
3488 '(.hg not found)'))
3452 repo = hg.repository(ui, repopath)
3489 repo = hg.repository(ui, repopath)
3453 return qinit(ui, repo, True)
3490 return qinit(ui, repo, True)
3454
3491
3455 def mqcommand(orig, ui, repo, *args, **kwargs):
3492 def mqcommand(orig, ui, repo, *args, **kwargs):
3456 """Add --mq option to operate on patch repository instead of main"""
3493 """Add --mq option to operate on patch repository instead of main"""
3457
3494
3458 # some commands do not like getting unknown options
3495 # some commands do not like getting unknown options
3459 mq = kwargs.pop('mq', None)
3496 mq = kwargs.pop('mq', None)
3460
3497
3461 if not mq:
3498 if not mq:
3462 return orig(ui, repo, *args, **kwargs)
3499 return orig(ui, repo, *args, **kwargs)
3463
3500
3464 q = repo.mq
3501 q = repo.mq
3465 r = q.qrepo()
3502 r = q.qrepo()
3466 if not r:
3503 if not r:
3467 raise util.Abort(_('no queue repository'))
3504 raise util.Abort(_('no queue repository'))
3468 return orig(r.ui, r, *args, **kwargs)
3505 return orig(r.ui, r, *args, **kwargs)
3469
3506
3470 def summaryhook(ui, repo):
3507 def summaryhook(ui, repo):
3471 q = repo.mq
3508 q = repo.mq
3472 m = []
3509 m = []
3473 a, u = len(q.applied), len(q.unapplied(repo))
3510 a, u = len(q.applied), len(q.unapplied(repo))
3474 if a:
3511 if a:
3475 m.append(ui.label(_("%d applied"), 'qseries.applied') % a)
3512 m.append(ui.label(_("%d applied"), 'qseries.applied') % a)
3476 if u:
3513 if u:
3477 m.append(ui.label(_("%d unapplied"), 'qseries.unapplied') % u)
3514 m.append(ui.label(_("%d unapplied"), 'qseries.unapplied') % u)
3478 if m:
3515 if m:
3479 # i18n: column positioning for "hg summary"
3516 # i18n: column positioning for "hg summary"
3480 ui.write(_("mq: %s\n") % ', '.join(m))
3517 ui.write(_("mq: %s\n") % ', '.join(m))
3481 else:
3518 else:
3482 # i18n: column positioning for "hg summary"
3519 # i18n: column positioning for "hg summary"
3483 ui.note(_("mq: (empty queue)\n"))
3520 ui.note(_("mq: (empty queue)\n"))
3484
3521
3485 def revsetmq(repo, subset, x):
3522 def revsetmq(repo, subset, x):
3486 """``mq()``
3523 """``mq()``
3487 Changesets managed by MQ.
3524 Changesets managed by MQ.
3488 """
3525 """
3489 revset.getargs(x, 0, 0, _("mq takes no arguments"))
3526 revset.getargs(x, 0, 0, _("mq takes no arguments"))
3490 applied = set([repo[r.node].rev() for r in repo.mq.applied])
3527 applied = set([repo[r.node].rev() for r in repo.mq.applied])
3491 return revset.baseset([r for r in subset if r in applied])
3528 return revset.baseset([r for r in subset if r in applied])
3492
3529
3493 # tell hggettext to extract docstrings from these functions:
3530 # tell hggettext to extract docstrings from these functions:
3494 i18nfunctions = [revsetmq]
3531 i18nfunctions = [revsetmq]
3495
3532
3496 def extsetup(ui):
3533 def extsetup(ui):
3497 # Ensure mq wrappers are called first, regardless of extension load order by
3534 # Ensure mq wrappers are called first, regardless of extension load order by
3498 # NOT wrapping in uisetup() and instead deferring to init stage two here.
3535 # NOT wrapping in uisetup() and instead deferring to init stage two here.
3499 mqopt = [('', 'mq', None, _("operate on patch repository"))]
3536 mqopt = [('', 'mq', None, _("operate on patch repository"))]
3500
3537
3501 extensions.wrapcommand(commands.table, 'import', mqimport)
3538 extensions.wrapcommand(commands.table, 'import', mqimport)
3502 cmdutil.summaryhooks.add('mq', summaryhook)
3539 cmdutil.summaryhooks.add('mq', summaryhook)
3503
3540
3504 entry = extensions.wrapcommand(commands.table, 'init', mqinit)
3541 entry = extensions.wrapcommand(commands.table, 'init', mqinit)
3505 entry[1].extend(mqopt)
3542 entry[1].extend(mqopt)
3506
3543
3507 nowrap = set(commands.norepo.split(" "))
3544 nowrap = set(commands.norepo.split(" "))
3508
3545
3509 def dotable(cmdtable):
3546 def dotable(cmdtable):
3510 for cmd in cmdtable.keys():
3547 for cmd in cmdtable.keys():
3511 cmd = cmdutil.parsealiases(cmd)[0]
3548 cmd = cmdutil.parsealiases(cmd)[0]
3512 if cmd in nowrap:
3549 if cmd in nowrap:
3513 continue
3550 continue
3514 entry = extensions.wrapcommand(cmdtable, cmd, mqcommand)
3551 entry = extensions.wrapcommand(cmdtable, cmd, mqcommand)
3515 entry[1].extend(mqopt)
3552 entry[1].extend(mqopt)
3516
3553
3517 dotable(commands.table)
3554 dotable(commands.table)
3518
3555
3519 for extname, extmodule in extensions.extensions():
3556 for extname, extmodule in extensions.extensions():
3520 if extmodule.__file__ != __file__:
3557 if extmodule.__file__ != __file__:
3521 dotable(getattr(extmodule, 'cmdtable', {}))
3558 dotable(getattr(extmodule, 'cmdtable', {}))
3522
3559
3523 revset.symbols['mq'] = revsetmq
3560 revset.symbols['mq'] = revsetmq
3524
3561
3525 colortable = {'qguard.negative': 'red',
3562 colortable = {'qguard.negative': 'red',
3526 'qguard.positive': 'yellow',
3563 'qguard.positive': 'yellow',
3527 'qguard.unguarded': 'green',
3564 'qguard.unguarded': 'green',
3528 'qseries.applied': 'blue bold underline',
3565 'qseries.applied': 'blue bold underline',
3529 'qseries.guarded': 'black bold',
3566 'qseries.guarded': 'black bold',
3530 'qseries.missing': 'red bold',
3567 'qseries.missing': 'red bold',
3531 'qseries.unapplied': 'black bold'}
3568 'qseries.unapplied': 'black bold'}
@@ -1,901 +1,901 b''
1
1
2 $ cat <<EOF >> $HGRCPATH
2 $ cat <<EOF >> $HGRCPATH
3 > [extensions]
3 > [extensions]
4 > mq =
4 > mq =
5 > [diff]
5 > [diff]
6 > nodates = true
6 > nodates = true
7 > EOF
7 > EOF
8 $ catpatch() {
8 $ catpatch() {
9 > cat .hg/patches/$1.patch | sed -e "s/^diff \-r [0-9a-f]* /diff -r ... /" \
9 > cat .hg/patches/$1.patch | sed -e "s/^diff \-r [0-9a-f]* /diff -r ... /" \
10 > -e "s/^\(# Parent \).*/\1/"
10 > -e "s/^\(# Parent \).*/\1/"
11 > }
11 > }
12 $ catlog() {
12 $ catlog() {
13 > catpatch $1
13 > catpatch $1
14 > hg log --template "{rev}: {desc} - {author}\n"
14 > hg log --template "{rev}: {desc} - {author}\n"
15 > }
15 > }
16 $ catlogd() {
16 $ catlogd() {
17 > catpatch $1
17 > catpatch $1
18 > hg log --template "{rev}: {desc} - {author} - {date}\n"
18 > hg log --template "{rev}: {desc} - {author} - {date}\n"
19 > }
19 > }
20 $ drop() {
20 $ drop() {
21 > hg qpop
21 > hg qpop
22 > hg qdel $1.patch
22 > hg qdel $1.patch
23 > }
23 > }
24 $ runtest() {
24 $ runtest() {
25 > echo ==== init
25 > echo ==== init
26 > hg init a
26 > hg init a
27 > cd a
27 > cd a
28 > hg qinit
28 > hg qinit
29 >
29 >
30 >
30 >
31 > echo ==== qnew -d
31 > echo ==== qnew -d
32 > hg qnew -d '3 0' 1.patch
32 > hg qnew -d '3 0' 1.patch
33 > catlogd 1
33 > catlogd 1
34 >
34 >
35 > echo ==== qref
35 > echo ==== qref
36 > echo "1" >1
36 > echo "1" >1
37 > hg add
37 > hg add
38 > hg qref
38 > hg qref
39 > catlogd 1
39 > catlogd 1
40 >
40 >
41 > echo ==== qref -d
41 > echo ==== qref -d
42 > hg qref -d '4 0'
42 > hg qref -d '4 0'
43 > catlogd 1
43 > catlogd 1
44 >
44 >
45 >
45 >
46 > echo ==== qnew
46 > echo ==== qnew
47 > hg qnew 2.patch
47 > hg qnew 2.patch
48 > echo "2" >2
48 > echo "2" >2
49 > hg add
49 > hg add
50 > hg qref
50 > hg qref
51 > catlog 2
51 > catlog 2
52 >
52 >
53 > echo ==== qref -d
53 > echo ==== qref -d
54 > hg qref -d '5 0'
54 > hg qref -d '5 0'
55 > catlog 2
55 > catlog 2
56 >
56 >
57 > drop 2
57 > drop 2
58 >
58 >
59 >
59 >
60 > echo ==== qnew -d -m
60 > echo ==== qnew -d -m
61 > hg qnew -d '6 0' -m "Three" 3.patch
61 > hg qnew -d '6 0' -m "Three" 3.patch
62 > catlogd 3
62 > catlogd 3
63 >
63 >
64 > echo ==== qref
64 > echo ==== qref
65 > echo "3" >3
65 > echo "3" >3
66 > hg add
66 > hg add
67 > hg qref
67 > hg qref
68 > catlogd 3
68 > catlogd 3
69 >
69 >
70 > echo ==== qref -m
70 > echo ==== qref -m
71 > hg qref -m "Drei"
71 > hg qref -m "Drei"
72 > catlogd 3
72 > catlogd 3
73 >
73 >
74 > echo ==== qref -d
74 > echo ==== qref -d
75 > hg qref -d '7 0'
75 > hg qref -d '7 0'
76 > catlogd 3
76 > catlogd 3
77 >
77 >
78 > echo ==== qref -d -m
78 > echo ==== qref -d -m
79 > hg qref -d '8 0' -m "Three (again)"
79 > hg qref -d '8 0' -m "Three (again)"
80 > catlogd 3
80 > catlogd 3
81 >
81 >
82 >
82 >
83 > echo ==== qnew -m
83 > echo ==== qnew -m
84 > hg qnew -m "Four" 4.patch
84 > hg qnew -m "Four" 4.patch
85 > echo "4" >4
85 > echo "4" >4
86 > hg add
86 > hg add
87 > hg qref
87 > hg qref
88 > catlog 4
88 > catlog 4
89 >
89 >
90 > echo ==== qref -d
90 > echo ==== qref -d
91 > hg qref -d '9 0'
91 > hg qref -d '9 0'
92 > catlog 4
92 > catlog 4
93 >
93 >
94 > drop 4
94 > drop 4
95 >
95 >
96 >
96 >
97 > echo ==== qnew with HG header
97 > echo ==== qnew with HG header
98 > hg qnew --config 'mq.plain=true' 5.patch
98 > hg qnew --config 'mq.plain=true' 5.patch
99 > hg qpop
99 > hg qpop
100 > echo "# HG changeset patch" >>.hg/patches/5.patch
100 > echo "# HG changeset patch" >>.hg/patches/5.patch
101 > echo "# Date 10 0" >>.hg/patches/5.patch
101 > echo "# Date 10 0" >>.hg/patches/5.patch
102 > hg qpush 2>&1 | grep 'Now at'
102 > hg qpush 2>&1 | grep 'Now at'
103 > catlogd 5
103 > catlogd 5
104 >
104 >
105 > echo ==== hg qref
105 > echo ==== hg qref
106 > echo "5" >5
106 > echo "5" >5
107 > hg add
107 > hg add
108 > hg qref
108 > hg qref
109 > catlogd 5
109 > catlogd 5
110 >
110 >
111 > echo ==== hg qref -d
111 > echo ==== hg qref -d
112 > hg qref -d '11 0'
112 > hg qref -d '11 0'
113 > catlogd 5
113 > catlogd 5
114 >
114 >
115 >
115 >
116 > echo ==== qnew with plain header
116 > echo ==== qnew with plain header
117 > hg qnew --config 'mq.plain=true' -d '12 0' 6.patch
117 > hg qnew --config 'mq.plain=true' -d '12 0' 6.patch
118 > hg qpop
118 > hg qpop
119 > hg qpush 2>&1 | grep 'now at'
119 > hg qpush 2>&1 | grep 'now at'
120 > catlog 6
120 > catlog 6
121 >
121 >
122 > echo ==== hg qref
122 > echo ==== hg qref
123 > echo "6" >6
123 > echo "6" >6
124 > hg add
124 > hg add
125 > hg qref
125 > hg qref
126 > catlogd 6
126 > catlogd 6
127 >
127 >
128 > echo ==== hg qref -d
128 > echo ==== hg qref -d
129 > hg qref -d '13 0'
129 > hg qref -d '13 0'
130 > catlogd 6
130 > catlogd 6
131 >
131 >
132 > drop 6
132 > drop 6
133 >
133 >
134 >
134 >
135 > echo ==== qnew -u
135 > echo ==== qnew -u
136 > hg qnew -u jane 6.patch
136 > hg qnew -u jane 6.patch
137 > echo "6" >6
137 > echo "6" >6
138 > hg add
138 > hg add
139 > hg qref
139 > hg qref
140 > catlog 6
140 > catlog 6
141 >
141 >
142 > echo ==== qref -d
142 > echo ==== qref -d
143 > hg qref -d '12 0'
143 > hg qref -d '12 0'
144 > catlog 6
144 > catlog 6
145 >
145 >
146 > drop 6
146 > drop 6
147 >
147 >
148 >
148 >
149 > echo ==== qnew -d
149 > echo ==== qnew -d
150 > hg qnew -d '13 0' 7.patch
150 > hg qnew -d '13 0' 7.patch
151 > echo "7" >7
151 > echo "7" >7
152 > hg add
152 > hg add
153 > hg qref
153 > hg qref
154 > catlog 7
154 > catlog 7
155 >
155 >
156 > echo ==== qref -u
156 > echo ==== qref -u
157 > hg qref -u john
157 > hg qref -u john
158 > catlogd 7
158 > catlogd 7
159 >
159 >
160 >
160 >
161 > echo ==== qnew
161 > echo ==== qnew
162 > hg qnew 8.patch
162 > hg qnew 8.patch
163 > echo "8" >8
163 > echo "8" >8
164 > hg add
164 > hg add
165 > hg qref
165 > hg qref
166 > catlog 8
166 > catlog 8
167 >
167 >
168 > echo ==== qref -u -d
168 > echo ==== qref -u -d
169 > hg qref -u john -d '14 0'
169 > hg qref -u john -d '14 0'
170 > catlog 8
170 > catlog 8
171 >
171 >
172 > drop 8
172 > drop 8
173 >
173 >
174 >
174 >
175 > echo ==== qnew -m
175 > echo ==== qnew -m
176 > hg qnew -m "Nine" 9.patch
176 > hg qnew -m "Nine" 9.patch
177 > echo "9" >9
177 > echo "9" >9
178 > hg add
178 > hg add
179 > hg qref
179 > hg qref
180 > catlog 9
180 > catlog 9
181 >
181 >
182 > echo ==== qref -u -d
182 > echo ==== qref -u -d
183 > hg qref -u john -d '15 0'
183 > hg qref -u john -d '15 0'
184 > catlog 9
184 > catlog 9
185 >
185 >
186 > drop 9
186 > drop 9
187 >
187 >
188 >
188 >
189 > echo ==== "qpop -a / qpush -a"
189 > echo ==== "qpop -a / qpush -a"
190 > hg qpop -a
190 > hg qpop -a
191 > hg qpush -a
191 > hg qpush -a
192 > hg log --template "{rev}: {desc} - {author} - {date}\n"
192 > hg log --template "{rev}: {desc} - {author} - {date}\n"
193 > }
193 > }
194
194
195 ======= plain headers
195 ======= plain headers
196
196
197 $ echo "[mq]" >> $HGRCPATH
197 $ echo "[mq]" >> $HGRCPATH
198 $ echo "plain=true" >> $HGRCPATH
198 $ echo "plain=true" >> $HGRCPATH
199 $ mkdir sandbox
199 $ mkdir sandbox
200 $ (cd sandbox ; runtest)
200 $ (cd sandbox ; runtest)
201 ==== init
201 ==== init
202 ==== qnew -d
202 ==== qnew -d
203 Date: 3 0
203 Date: 3 0
204
204
205 0: [mq]: 1.patch - test - 3.00
205 0: [mq]: 1.patch - test - 3.00
206 ==== qref
206 ==== qref
207 adding 1
207 adding 1
208 Date: 3 0
208 Date: 3 0
209
209
210 diff -r ... 1
210 diff -r ... 1
211 --- /dev/null
211 --- /dev/null
212 +++ b/1
212 +++ b/1
213 @@ -0,0 +1,1 @@
213 @@ -0,0 +1,1 @@
214 +1
214 +1
215 0: [mq]: 1.patch - test - 3.00
215 0: [mq]: 1.patch - test - 3.00
216 ==== qref -d
216 ==== qref -d
217 Date: 4 0
217 Date: 4 0
218
218
219 diff -r ... 1
219 diff -r ... 1
220 --- /dev/null
220 --- /dev/null
221 +++ b/1
221 +++ b/1
222 @@ -0,0 +1,1 @@
222 @@ -0,0 +1,1 @@
223 +1
223 +1
224 0: [mq]: 1.patch - test - 4.00
224 0: [mq]: 1.patch - test - 4.00
225 ==== qnew
225 ==== qnew
226 adding 2
226 adding 2
227 diff -r ... 2
227 diff -r ... 2
228 --- /dev/null
228 --- /dev/null
229 +++ b/2
229 +++ b/2
230 @@ -0,0 +1,1 @@
230 @@ -0,0 +1,1 @@
231 +2
231 +2
232 1: [mq]: 2.patch - test
232 1: [mq]: 2.patch - test
233 0: [mq]: 1.patch - test
233 0: [mq]: 1.patch - test
234 ==== qref -d
234 ==== qref -d
235 Date: 5 0
235 Date: 5 0
236
236
237 diff -r ... 2
237 diff -r ... 2
238 --- /dev/null
238 --- /dev/null
239 +++ b/2
239 +++ b/2
240 @@ -0,0 +1,1 @@
240 @@ -0,0 +1,1 @@
241 +2
241 +2
242 1: [mq]: 2.patch - test
242 1: [mq]: 2.patch - test
243 0: [mq]: 1.patch - test
243 0: [mq]: 1.patch - test
244 popping 2.patch
244 popping 2.patch
245 now at: 1.patch
245 now at: 1.patch
246 ==== qnew -d -m
246 ==== qnew -d -m
247 Date: 6 0
247 Date: 6 0
248
248
249 Three
249 Three
250
250
251 1: Three - test - 6.00
251 1: Three - test - 6.00
252 0: [mq]: 1.patch - test - 4.00
252 0: [mq]: 1.patch - test - 4.00
253 ==== qref
253 ==== qref
254 adding 3
254 adding 3
255 Date: 6 0
255 Date: 6 0
256
256
257 Three
257 Three
258
258
259 diff -r ... 3
259 diff -r ... 3
260 --- /dev/null
260 --- /dev/null
261 +++ b/3
261 +++ b/3
262 @@ -0,0 +1,1 @@
262 @@ -0,0 +1,1 @@
263 +3
263 +3
264 1: Three - test - 6.00
264 1: Three - test - 6.00
265 0: [mq]: 1.patch - test - 4.00
265 0: [mq]: 1.patch - test - 4.00
266 ==== qref -m
266 ==== qref -m
267 Date: 6 0
267 Date: 6 0
268
268
269 Drei
269 Drei
270
270
271 diff -r ... 3
271 diff -r ... 3
272 --- /dev/null
272 --- /dev/null
273 +++ b/3
273 +++ b/3
274 @@ -0,0 +1,1 @@
274 @@ -0,0 +1,1 @@
275 +3
275 +3
276 1: Drei - test - 6.00
276 1: Drei - test - 6.00
277 0: [mq]: 1.patch - test - 4.00
277 0: [mq]: 1.patch - test - 4.00
278 ==== qref -d
278 ==== qref -d
279 Date: 7 0
279 Date: 7 0
280
280
281 Drei
281 Drei
282
282
283 diff -r ... 3
283 diff -r ... 3
284 --- /dev/null
284 --- /dev/null
285 +++ b/3
285 +++ b/3
286 @@ -0,0 +1,1 @@
286 @@ -0,0 +1,1 @@
287 +3
287 +3
288 1: Drei - test - 7.00
288 1: Drei - test - 7.00
289 0: [mq]: 1.patch - test - 4.00
289 0: [mq]: 1.patch - test - 4.00
290 ==== qref -d -m
290 ==== qref -d -m
291 Date: 8 0
291 Date: 8 0
292
292
293 Three (again)
293 Three (again)
294
294
295 diff -r ... 3
295 diff -r ... 3
296 --- /dev/null
296 --- /dev/null
297 +++ b/3
297 +++ b/3
298 @@ -0,0 +1,1 @@
298 @@ -0,0 +1,1 @@
299 +3
299 +3
300 1: Three (again) - test - 8.00
300 1: Three (again) - test - 8.00
301 0: [mq]: 1.patch - test - 4.00
301 0: [mq]: 1.patch - test - 4.00
302 ==== qnew -m
302 ==== qnew -m
303 adding 4
303 adding 4
304 Four
304 Four
305
305
306 diff -r ... 4
306 diff -r ... 4
307 --- /dev/null
307 --- /dev/null
308 +++ b/4
308 +++ b/4
309 @@ -0,0 +1,1 @@
309 @@ -0,0 +1,1 @@
310 +4
310 +4
311 2: Four - test
311 2: Four - test
312 1: Three (again) - test
312 1: Three (again) - test
313 0: [mq]: 1.patch - test
313 0: [mq]: 1.patch - test
314 ==== qref -d
314 ==== qref -d
315 Date: 9 0
315 Date: 9 0
316
316
317 Four
317 Four
318
318
319 diff -r ... 4
319 diff -r ... 4
320 --- /dev/null
320 --- /dev/null
321 +++ b/4
321 +++ b/4
322 @@ -0,0 +1,1 @@
322 @@ -0,0 +1,1 @@
323 +4
323 +4
324 2: Four - test
324 2: Four - test
325 1: Three (again) - test
325 1: Three (again) - test
326 0: [mq]: 1.patch - test
326 0: [mq]: 1.patch - test
327 popping 4.patch
327 popping 4.patch
328 now at: 3.patch
328 now at: 3.patch
329 ==== qnew with HG header
329 ==== qnew with HG header
330 popping 5.patch
330 popping 5.patch
331 now at: 3.patch
331 now at: 3.patch
332 # HG changeset patch
332 # HG changeset patch
333 # Date 10 0
333 # Date 10 0
334 2: imported patch 5.patch - test - 10.00
334 2: imported patch 5.patch - test - 10.00
335 1: Three (again) - test - 8.00
335 1: Three (again) - test - 8.00
336 0: [mq]: 1.patch - test - 4.00
336 0: [mq]: 1.patch - test - 4.00
337 ==== hg qref
337 ==== hg qref
338 adding 5
338 adding 5
339 # HG changeset patch
339 # HG changeset patch
340 # Date 10 0
340 # Date 10 0
341 # Parent
341 # Parent
342
342
343 diff -r ... 5
343 diff -r ... 5
344 --- /dev/null
344 --- /dev/null
345 +++ b/5
345 +++ b/5
346 @@ -0,0 +1,1 @@
346 @@ -0,0 +1,1 @@
347 +5
347 +5
348 2: [mq]: 5.patch - test - 10.00
348 2: [mq]: 5.patch - test - 10.00
349 1: Three (again) - test - 8.00
349 1: Three (again) - test - 8.00
350 0: [mq]: 1.patch - test - 4.00
350 0: [mq]: 1.patch - test - 4.00
351 ==== hg qref -d
351 ==== hg qref -d
352 # HG changeset patch
352 # HG changeset patch
353 # Date 11 0
353 # Date 11 0
354 # Parent
354 # Parent
355
355
356 diff -r ... 5
356 diff -r ... 5
357 --- /dev/null
357 --- /dev/null
358 +++ b/5
358 +++ b/5
359 @@ -0,0 +1,1 @@
359 @@ -0,0 +1,1 @@
360 +5
360 +5
361 2: [mq]: 5.patch - test - 11.00
361 2: [mq]: 5.patch - test - 11.00
362 1: Three (again) - test - 8.00
362 1: Three (again) - test - 8.00
363 0: [mq]: 1.patch - test - 4.00
363 0: [mq]: 1.patch - test - 4.00
364 ==== qnew with plain header
364 ==== qnew with plain header
365 popping 6.patch
365 popping 6.patch
366 now at: 5.patch
366 now at: 5.patch
367 now at: 6.patch
367 now at: 6.patch
368 Date: 12 0
368 Date: 12 0
369
369
370 3: imported patch 6.patch - test
370 3: imported patch 6.patch - test
371 2: [mq]: 5.patch - test
371 2: [mq]: 5.patch - test
372 1: Three (again) - test
372 1: Three (again) - test
373 0: [mq]: 1.patch - test
373 0: [mq]: 1.patch - test
374 ==== hg qref
374 ==== hg qref
375 adding 6
375 adding 6
376 Date: 12 0
376 Date: 12 0
377
377
378 diff -r ... 6
378 diff -r ... 6
379 --- /dev/null
379 --- /dev/null
380 +++ b/6
380 +++ b/6
381 @@ -0,0 +1,1 @@
381 @@ -0,0 +1,1 @@
382 +6
382 +6
383 3: [mq]: 6.patch - test - 12.00
383 3: [mq]: 6.patch - test - 12.00
384 2: [mq]: 5.patch - test - 11.00
384 2: [mq]: 5.patch - test - 11.00
385 1: Three (again) - test - 8.00
385 1: Three (again) - test - 8.00
386 0: [mq]: 1.patch - test - 4.00
386 0: [mq]: 1.patch - test - 4.00
387 ==== hg qref -d
387 ==== hg qref -d
388 Date: 13 0
388 Date: 13 0
389
389
390 diff -r ... 6
390 diff -r ... 6
391 --- /dev/null
391 --- /dev/null
392 +++ b/6
392 +++ b/6
393 @@ -0,0 +1,1 @@
393 @@ -0,0 +1,1 @@
394 +6
394 +6
395 3: [mq]: 6.patch - test - 13.00
395 3: [mq]: 6.patch - test - 13.00
396 2: [mq]: 5.patch - test - 11.00
396 2: [mq]: 5.patch - test - 11.00
397 1: Three (again) - test - 8.00
397 1: Three (again) - test - 8.00
398 0: [mq]: 1.patch - test - 4.00
398 0: [mq]: 1.patch - test - 4.00
399 popping 6.patch
399 popping 6.patch
400 now at: 5.patch
400 now at: 5.patch
401 ==== qnew -u
401 ==== qnew -u
402 adding 6
402 adding 6
403 From: jane
403 From: jane
404
404
405 diff -r ... 6
405 diff -r ... 6
406 --- /dev/null
406 --- /dev/null
407 +++ b/6
407 +++ b/6
408 @@ -0,0 +1,1 @@
408 @@ -0,0 +1,1 @@
409 +6
409 +6
410 3: [mq]: 6.patch - jane
410 3: [mq]: 6.patch - jane
411 2: [mq]: 5.patch - test
411 2: [mq]: 5.patch - test
412 1: Three (again) - test
412 1: Three (again) - test
413 0: [mq]: 1.patch - test
413 0: [mq]: 1.patch - test
414 ==== qref -d
414 ==== qref -d
415 From: jane
415 Date: 12 0
416 Date: 12 0
416 From: jane
417
417
418 diff -r ... 6
418 diff -r ... 6
419 --- /dev/null
419 --- /dev/null
420 +++ b/6
420 +++ b/6
421 @@ -0,0 +1,1 @@
421 @@ -0,0 +1,1 @@
422 +6
422 +6
423 3: [mq]: 6.patch - jane
423 3: [mq]: 6.patch - jane
424 2: [mq]: 5.patch - test
424 2: [mq]: 5.patch - test
425 1: Three (again) - test
425 1: Three (again) - test
426 0: [mq]: 1.patch - test
426 0: [mq]: 1.patch - test
427 popping 6.patch
427 popping 6.patch
428 now at: 5.patch
428 now at: 5.patch
429 ==== qnew -d
429 ==== qnew -d
430 adding 7
430 adding 7
431 Date: 13 0
431 Date: 13 0
432
432
433 diff -r ... 7
433 diff -r ... 7
434 --- /dev/null
434 --- /dev/null
435 +++ b/7
435 +++ b/7
436 @@ -0,0 +1,1 @@
436 @@ -0,0 +1,1 @@
437 +7
437 +7
438 3: [mq]: 7.patch - test
438 3: [mq]: 7.patch - test
439 2: [mq]: 5.patch - test
439 2: [mq]: 5.patch - test
440 1: Three (again) - test
440 1: Three (again) - test
441 0: [mq]: 1.patch - test
441 0: [mq]: 1.patch - test
442 ==== qref -u
442 ==== qref -u
443 From: john
443 From: john
444 Date: 13 0
444 Date: 13 0
445
445
446 diff -r ... 7
446 diff -r ... 7
447 --- /dev/null
447 --- /dev/null
448 +++ b/7
448 +++ b/7
449 @@ -0,0 +1,1 @@
449 @@ -0,0 +1,1 @@
450 +7
450 +7
451 3: [mq]: 7.patch - john - 13.00
451 3: [mq]: 7.patch - john - 13.00
452 2: [mq]: 5.patch - test - 11.00
452 2: [mq]: 5.patch - test - 11.00
453 1: Three (again) - test - 8.00
453 1: Three (again) - test - 8.00
454 0: [mq]: 1.patch - test - 4.00
454 0: [mq]: 1.patch - test - 4.00
455 ==== qnew
455 ==== qnew
456 adding 8
456 adding 8
457 diff -r ... 8
457 diff -r ... 8
458 --- /dev/null
458 --- /dev/null
459 +++ b/8
459 +++ b/8
460 @@ -0,0 +1,1 @@
460 @@ -0,0 +1,1 @@
461 +8
461 +8
462 4: [mq]: 8.patch - test
462 4: [mq]: 8.patch - test
463 3: [mq]: 7.patch - john
463 3: [mq]: 7.patch - john
464 2: [mq]: 5.patch - test
464 2: [mq]: 5.patch - test
465 1: Three (again) - test
465 1: Three (again) - test
466 0: [mq]: 1.patch - test
466 0: [mq]: 1.patch - test
467 ==== qref -u -d
467 ==== qref -u -d
468 From: john
468 Date: 14 0
469 Date: 14 0
469 From: john
470
470
471 diff -r ... 8
471 diff -r ... 8
472 --- /dev/null
472 --- /dev/null
473 +++ b/8
473 +++ b/8
474 @@ -0,0 +1,1 @@
474 @@ -0,0 +1,1 @@
475 +8
475 +8
476 4: [mq]: 8.patch - john
476 4: [mq]: 8.patch - john
477 3: [mq]: 7.patch - john
477 3: [mq]: 7.patch - john
478 2: [mq]: 5.patch - test
478 2: [mq]: 5.patch - test
479 1: Three (again) - test
479 1: Three (again) - test
480 0: [mq]: 1.patch - test
480 0: [mq]: 1.patch - test
481 popping 8.patch
481 popping 8.patch
482 now at: 7.patch
482 now at: 7.patch
483 ==== qnew -m
483 ==== qnew -m
484 adding 9
484 adding 9
485 Nine
485 Nine
486
486
487 diff -r ... 9
487 diff -r ... 9
488 --- /dev/null
488 --- /dev/null
489 +++ b/9
489 +++ b/9
490 @@ -0,0 +1,1 @@
490 @@ -0,0 +1,1 @@
491 +9
491 +9
492 4: Nine - test
492 4: Nine - test
493 3: [mq]: 7.patch - john
493 3: [mq]: 7.patch - john
494 2: [mq]: 5.patch - test
494 2: [mq]: 5.patch - test
495 1: Three (again) - test
495 1: Three (again) - test
496 0: [mq]: 1.patch - test
496 0: [mq]: 1.patch - test
497 ==== qref -u -d
497 ==== qref -u -d
498 From: john
498 Date: 15 0
499 Date: 15 0
499 From: john
500
500
501 Nine
501 Nine
502
502
503 diff -r ... 9
503 diff -r ... 9
504 --- /dev/null
504 --- /dev/null
505 +++ b/9
505 +++ b/9
506 @@ -0,0 +1,1 @@
506 @@ -0,0 +1,1 @@
507 +9
507 +9
508 4: Nine - john
508 4: Nine - john
509 3: [mq]: 7.patch - john
509 3: [mq]: 7.patch - john
510 2: [mq]: 5.patch - test
510 2: [mq]: 5.patch - test
511 1: Three (again) - test
511 1: Three (again) - test
512 0: [mq]: 1.patch - test
512 0: [mq]: 1.patch - test
513 popping 9.patch
513 popping 9.patch
514 now at: 7.patch
514 now at: 7.patch
515 ==== qpop -a / qpush -a
515 ==== qpop -a / qpush -a
516 popping 7.patch
516 popping 7.patch
517 popping 5.patch
517 popping 5.patch
518 popping 3.patch
518 popping 3.patch
519 popping 1.patch
519 popping 1.patch
520 patch queue now empty
520 patch queue now empty
521 applying 1.patch
521 applying 1.patch
522 applying 3.patch
522 applying 3.patch
523 applying 5.patch
523 applying 5.patch
524 applying 7.patch
524 applying 7.patch
525 now at: 7.patch
525 now at: 7.patch
526 3: imported patch 7.patch - john - 13.00
526 3: imported patch 7.patch - john - 13.00
527 2: imported patch 5.patch - test - 11.00
527 2: imported patch 5.patch - test - 11.00
528 1: Three (again) - test - 8.00
528 1: Three (again) - test - 8.00
529 0: imported patch 1.patch - test - 4.00
529 0: imported patch 1.patch - test - 4.00
530 $ rm -r sandbox
530 $ rm -r sandbox
531
531
532 ======= hg headers
532 ======= hg headers
533
533
534 $ echo "plain=false" >> $HGRCPATH
534 $ echo "plain=false" >> $HGRCPATH
535 $ mkdir sandbox
535 $ mkdir sandbox
536 $ (cd sandbox ; runtest)
536 $ (cd sandbox ; runtest)
537 ==== init
537 ==== init
538 ==== qnew -d
538 ==== qnew -d
539 # HG changeset patch
539 # HG changeset patch
540 # Date 3 0
540 # Date 3 0
541 # Parent
541 # Parent
542
542
543 0: [mq]: 1.patch - test - 3.00
543 0: [mq]: 1.patch - test - 3.00
544 ==== qref
544 ==== qref
545 adding 1
545 adding 1
546 # HG changeset patch
546 # HG changeset patch
547 # Date 3 0
547 # Date 3 0
548 # Parent
548 # Parent
549
549
550 diff -r ... 1
550 diff -r ... 1
551 --- /dev/null
551 --- /dev/null
552 +++ b/1
552 +++ b/1
553 @@ -0,0 +1,1 @@
553 @@ -0,0 +1,1 @@
554 +1
554 +1
555 0: [mq]: 1.patch - test - 3.00
555 0: [mq]: 1.patch - test - 3.00
556 ==== qref -d
556 ==== qref -d
557 # HG changeset patch
557 # HG changeset patch
558 # Date 4 0
558 # Date 4 0
559 # Parent
559 # Parent
560
560
561 diff -r ... 1
561 diff -r ... 1
562 --- /dev/null
562 --- /dev/null
563 +++ b/1
563 +++ b/1
564 @@ -0,0 +1,1 @@
564 @@ -0,0 +1,1 @@
565 +1
565 +1
566 0: [mq]: 1.patch - test - 4.00
566 0: [mq]: 1.patch - test - 4.00
567 ==== qnew
567 ==== qnew
568 adding 2
568 adding 2
569 # HG changeset patch
569 # HG changeset patch
570 # Parent
570 # Parent
571
571
572 diff -r ... 2
572 diff -r ... 2
573 --- /dev/null
573 --- /dev/null
574 +++ b/2
574 +++ b/2
575 @@ -0,0 +1,1 @@
575 @@ -0,0 +1,1 @@
576 +2
576 +2
577 1: [mq]: 2.patch - test
577 1: [mq]: 2.patch - test
578 0: [mq]: 1.patch - test
578 0: [mq]: 1.patch - test
579 ==== qref -d
579 ==== qref -d
580 # HG changeset patch
580 # HG changeset patch
581 # Date 5 0
581 # Date 5 0
582 # Parent
582 # Parent
583
583
584 diff -r ... 2
584 diff -r ... 2
585 --- /dev/null
585 --- /dev/null
586 +++ b/2
586 +++ b/2
587 @@ -0,0 +1,1 @@
587 @@ -0,0 +1,1 @@
588 +2
588 +2
589 1: [mq]: 2.patch - test
589 1: [mq]: 2.patch - test
590 0: [mq]: 1.patch - test
590 0: [mq]: 1.patch - test
591 popping 2.patch
591 popping 2.patch
592 now at: 1.patch
592 now at: 1.patch
593 ==== qnew -d -m
593 ==== qnew -d -m
594 # HG changeset patch
594 # HG changeset patch
595 # Date 6 0
595 # Date 6 0
596 # Parent
596 # Parent
597 Three
597 Three
598
598
599 1: Three - test - 6.00
599 1: Three - test - 6.00
600 0: [mq]: 1.patch - test - 4.00
600 0: [mq]: 1.patch - test - 4.00
601 ==== qref
601 ==== qref
602 adding 3
602 adding 3
603 # HG changeset patch
603 # HG changeset patch
604 # Date 6 0
604 # Date 6 0
605 # Parent
605 # Parent
606 Three
606 Three
607
607
608 diff -r ... 3
608 diff -r ... 3
609 --- /dev/null
609 --- /dev/null
610 +++ b/3
610 +++ b/3
611 @@ -0,0 +1,1 @@
611 @@ -0,0 +1,1 @@
612 +3
612 +3
613 1: Three - test - 6.00
613 1: Three - test - 6.00
614 0: [mq]: 1.patch - test - 4.00
614 0: [mq]: 1.patch - test - 4.00
615 ==== qref -m
615 ==== qref -m
616 # HG changeset patch
616 # HG changeset patch
617 # Date 6 0
617 # Date 6 0
618 # Parent
618 # Parent
619 Drei
619 Drei
620
620
621 diff -r ... 3
621 diff -r ... 3
622 --- /dev/null
622 --- /dev/null
623 +++ b/3
623 +++ b/3
624 @@ -0,0 +1,1 @@
624 @@ -0,0 +1,1 @@
625 +3
625 +3
626 1: Drei - test - 6.00
626 1: Drei - test - 6.00
627 0: [mq]: 1.patch - test - 4.00
627 0: [mq]: 1.patch - test - 4.00
628 ==== qref -d
628 ==== qref -d
629 # HG changeset patch
629 # HG changeset patch
630 # Date 7 0
630 # Date 7 0
631 # Parent
631 # Parent
632 Drei
632 Drei
633
633
634 diff -r ... 3
634 diff -r ... 3
635 --- /dev/null
635 --- /dev/null
636 +++ b/3
636 +++ b/3
637 @@ -0,0 +1,1 @@
637 @@ -0,0 +1,1 @@
638 +3
638 +3
639 1: Drei - test - 7.00
639 1: Drei - test - 7.00
640 0: [mq]: 1.patch - test - 4.00
640 0: [mq]: 1.patch - test - 4.00
641 ==== qref -d -m
641 ==== qref -d -m
642 # HG changeset patch
642 # HG changeset patch
643 # Date 8 0
643 # Date 8 0
644 # Parent
644 # Parent
645 Three (again)
645 Three (again)
646
646
647 diff -r ... 3
647 diff -r ... 3
648 --- /dev/null
648 --- /dev/null
649 +++ b/3
649 +++ b/3
650 @@ -0,0 +1,1 @@
650 @@ -0,0 +1,1 @@
651 +3
651 +3
652 1: Three (again) - test - 8.00
652 1: Three (again) - test - 8.00
653 0: [mq]: 1.patch - test - 4.00
653 0: [mq]: 1.patch - test - 4.00
654 ==== qnew -m
654 ==== qnew -m
655 adding 4
655 adding 4
656 # HG changeset patch
656 # HG changeset patch
657 # Parent
657 # Parent
658 Four
658 Four
659
659
660 diff -r ... 4
660 diff -r ... 4
661 --- /dev/null
661 --- /dev/null
662 +++ b/4
662 +++ b/4
663 @@ -0,0 +1,1 @@
663 @@ -0,0 +1,1 @@
664 +4
664 +4
665 2: Four - test
665 2: Four - test
666 1: Three (again) - test
666 1: Three (again) - test
667 0: [mq]: 1.patch - test
667 0: [mq]: 1.patch - test
668 ==== qref -d
668 ==== qref -d
669 # HG changeset patch
669 # HG changeset patch
670 # Date 9 0
670 # Date 9 0
671 # Parent
671 # Parent
672 Four
672 Four
673
673
674 diff -r ... 4
674 diff -r ... 4
675 --- /dev/null
675 --- /dev/null
676 +++ b/4
676 +++ b/4
677 @@ -0,0 +1,1 @@
677 @@ -0,0 +1,1 @@
678 +4
678 +4
679 2: Four - test
679 2: Four - test
680 1: Three (again) - test
680 1: Three (again) - test
681 0: [mq]: 1.patch - test
681 0: [mq]: 1.patch - test
682 popping 4.patch
682 popping 4.patch
683 now at: 3.patch
683 now at: 3.patch
684 ==== qnew with HG header
684 ==== qnew with HG header
685 popping 5.patch
685 popping 5.patch
686 now at: 3.patch
686 now at: 3.patch
687 # HG changeset patch
687 # HG changeset patch
688 # Date 10 0
688 # Date 10 0
689 2: imported patch 5.patch - test - 10.00
689 2: imported patch 5.patch - test - 10.00
690 1: Three (again) - test - 8.00
690 1: Three (again) - test - 8.00
691 0: [mq]: 1.patch - test - 4.00
691 0: [mq]: 1.patch - test - 4.00
692 ==== hg qref
692 ==== hg qref
693 adding 5
693 adding 5
694 # HG changeset patch
694 # HG changeset patch
695 # Date 10 0
695 # Date 10 0
696 # Parent
696 # Parent
697
697
698 diff -r ... 5
698 diff -r ... 5
699 --- /dev/null
699 --- /dev/null
700 +++ b/5
700 +++ b/5
701 @@ -0,0 +1,1 @@
701 @@ -0,0 +1,1 @@
702 +5
702 +5
703 2: [mq]: 5.patch - test - 10.00
703 2: [mq]: 5.patch - test - 10.00
704 1: Three (again) - test - 8.00
704 1: Three (again) - test - 8.00
705 0: [mq]: 1.patch - test - 4.00
705 0: [mq]: 1.patch - test - 4.00
706 ==== hg qref -d
706 ==== hg qref -d
707 # HG changeset patch
707 # HG changeset patch
708 # Date 11 0
708 # Date 11 0
709 # Parent
709 # Parent
710
710
711 diff -r ... 5
711 diff -r ... 5
712 --- /dev/null
712 --- /dev/null
713 +++ b/5
713 +++ b/5
714 @@ -0,0 +1,1 @@
714 @@ -0,0 +1,1 @@
715 +5
715 +5
716 2: [mq]: 5.patch - test - 11.00
716 2: [mq]: 5.patch - test - 11.00
717 1: Three (again) - test - 8.00
717 1: Three (again) - test - 8.00
718 0: [mq]: 1.patch - test - 4.00
718 0: [mq]: 1.patch - test - 4.00
719 ==== qnew with plain header
719 ==== qnew with plain header
720 popping 6.patch
720 popping 6.patch
721 now at: 5.patch
721 now at: 5.patch
722 now at: 6.patch
722 now at: 6.patch
723 Date: 12 0
723 Date: 12 0
724
724
725 3: imported patch 6.patch - test
725 3: imported patch 6.patch - test
726 2: [mq]: 5.patch - test
726 2: [mq]: 5.patch - test
727 1: Three (again) - test
727 1: Three (again) - test
728 0: [mq]: 1.patch - test
728 0: [mq]: 1.patch - test
729 ==== hg qref
729 ==== hg qref
730 adding 6
730 adding 6
731 Date: 12 0
731 Date: 12 0
732
732
733 diff -r ... 6
733 diff -r ... 6
734 --- /dev/null
734 --- /dev/null
735 +++ b/6
735 +++ b/6
736 @@ -0,0 +1,1 @@
736 @@ -0,0 +1,1 @@
737 +6
737 +6
738 3: [mq]: 6.patch - test - 12.00
738 3: [mq]: 6.patch - test - 12.00
739 2: [mq]: 5.patch - test - 11.00
739 2: [mq]: 5.patch - test - 11.00
740 1: Three (again) - test - 8.00
740 1: Three (again) - test - 8.00
741 0: [mq]: 1.patch - test - 4.00
741 0: [mq]: 1.patch - test - 4.00
742 ==== hg qref -d
742 ==== hg qref -d
743 Date: 13 0
743 Date: 13 0
744
744
745 diff -r ... 6
745 diff -r ... 6
746 --- /dev/null
746 --- /dev/null
747 +++ b/6
747 +++ b/6
748 @@ -0,0 +1,1 @@
748 @@ -0,0 +1,1 @@
749 +6
749 +6
750 3: [mq]: 6.patch - test - 13.00
750 3: [mq]: 6.patch - test - 13.00
751 2: [mq]: 5.patch - test - 11.00
751 2: [mq]: 5.patch - test - 11.00
752 1: Three (again) - test - 8.00
752 1: Three (again) - test - 8.00
753 0: [mq]: 1.patch - test - 4.00
753 0: [mq]: 1.patch - test - 4.00
754 popping 6.patch
754 popping 6.patch
755 now at: 5.patch
755 now at: 5.patch
756 ==== qnew -u
756 ==== qnew -u
757 adding 6
757 adding 6
758 # HG changeset patch
758 # HG changeset patch
759 # User jane
759 # User jane
760 # Parent
760 # Parent
761
761
762 diff -r ... 6
762 diff -r ... 6
763 --- /dev/null
763 --- /dev/null
764 +++ b/6
764 +++ b/6
765 @@ -0,0 +1,1 @@
765 @@ -0,0 +1,1 @@
766 +6
766 +6
767 3: [mq]: 6.patch - jane
767 3: [mq]: 6.patch - jane
768 2: [mq]: 5.patch - test
768 2: [mq]: 5.patch - test
769 1: Three (again) - test
769 1: Three (again) - test
770 0: [mq]: 1.patch - test
770 0: [mq]: 1.patch - test
771 ==== qref -d
771 ==== qref -d
772 # HG changeset patch
772 # HG changeset patch
773 # User jane
773 # User jane
774 # Date 12 0
774 # Date 12 0
775 # Parent
775 # Parent
776
776
777 diff -r ... 6
777 diff -r ... 6
778 --- /dev/null
778 --- /dev/null
779 +++ b/6
779 +++ b/6
780 @@ -0,0 +1,1 @@
780 @@ -0,0 +1,1 @@
781 +6
781 +6
782 3: [mq]: 6.patch - jane
782 3: [mq]: 6.patch - jane
783 2: [mq]: 5.patch - test
783 2: [mq]: 5.patch - test
784 1: Three (again) - test
784 1: Three (again) - test
785 0: [mq]: 1.patch - test
785 0: [mq]: 1.patch - test
786 popping 6.patch
786 popping 6.patch
787 now at: 5.patch
787 now at: 5.patch
788 ==== qnew -d
788 ==== qnew -d
789 adding 7
789 adding 7
790 # HG changeset patch
790 # HG changeset patch
791 # Date 13 0
791 # Date 13 0
792 # Parent
792 # Parent
793
793
794 diff -r ... 7
794 diff -r ... 7
795 --- /dev/null
795 --- /dev/null
796 +++ b/7
796 +++ b/7
797 @@ -0,0 +1,1 @@
797 @@ -0,0 +1,1 @@
798 +7
798 +7
799 3: [mq]: 7.patch - test
799 3: [mq]: 7.patch - test
800 2: [mq]: 5.patch - test
800 2: [mq]: 5.patch - test
801 1: Three (again) - test
801 1: Three (again) - test
802 0: [mq]: 1.patch - test
802 0: [mq]: 1.patch - test
803 ==== qref -u
803 ==== qref -u
804 # HG changeset patch
804 # HG changeset patch
805 # User john
805 # User john
806 # Date 13 0
806 # Date 13 0
807 # Parent
807 # Parent
808
808
809 diff -r ... 7
809 diff -r ... 7
810 --- /dev/null
810 --- /dev/null
811 +++ b/7
811 +++ b/7
812 @@ -0,0 +1,1 @@
812 @@ -0,0 +1,1 @@
813 +7
813 +7
814 3: [mq]: 7.patch - john - 13.00
814 3: [mq]: 7.patch - john - 13.00
815 2: [mq]: 5.patch - test - 11.00
815 2: [mq]: 5.patch - test - 11.00
816 1: Three (again) - test - 8.00
816 1: Three (again) - test - 8.00
817 0: [mq]: 1.patch - test - 4.00
817 0: [mq]: 1.patch - test - 4.00
818 ==== qnew
818 ==== qnew
819 adding 8
819 adding 8
820 # HG changeset patch
820 # HG changeset patch
821 # Parent
821 # Parent
822
822
823 diff -r ... 8
823 diff -r ... 8
824 --- /dev/null
824 --- /dev/null
825 +++ b/8
825 +++ b/8
826 @@ -0,0 +1,1 @@
826 @@ -0,0 +1,1 @@
827 +8
827 +8
828 4: [mq]: 8.patch - test
828 4: [mq]: 8.patch - test
829 3: [mq]: 7.patch - john
829 3: [mq]: 7.patch - john
830 2: [mq]: 5.patch - test
830 2: [mq]: 5.patch - test
831 1: Three (again) - test
831 1: Three (again) - test
832 0: [mq]: 1.patch - test
832 0: [mq]: 1.patch - test
833 ==== qref -u -d
833 ==== qref -u -d
834 # HG changeset patch
834 # HG changeset patch
835 # User john
835 # User john
836 # Date 14 0
836 # Date 14 0
837 # Parent
837 # Parent
838
838
839 diff -r ... 8
839 diff -r ... 8
840 --- /dev/null
840 --- /dev/null
841 +++ b/8
841 +++ b/8
842 @@ -0,0 +1,1 @@
842 @@ -0,0 +1,1 @@
843 +8
843 +8
844 4: [mq]: 8.patch - john
844 4: [mq]: 8.patch - john
845 3: [mq]: 7.patch - john
845 3: [mq]: 7.patch - john
846 2: [mq]: 5.patch - test
846 2: [mq]: 5.patch - test
847 1: Three (again) - test
847 1: Three (again) - test
848 0: [mq]: 1.patch - test
848 0: [mq]: 1.patch - test
849 popping 8.patch
849 popping 8.patch
850 now at: 7.patch
850 now at: 7.patch
851 ==== qnew -m
851 ==== qnew -m
852 adding 9
852 adding 9
853 # HG changeset patch
853 # HG changeset patch
854 # Parent
854 # Parent
855 Nine
855 Nine
856
856
857 diff -r ... 9
857 diff -r ... 9
858 --- /dev/null
858 --- /dev/null
859 +++ b/9
859 +++ b/9
860 @@ -0,0 +1,1 @@
860 @@ -0,0 +1,1 @@
861 +9
861 +9
862 4: Nine - test
862 4: Nine - test
863 3: [mq]: 7.patch - john
863 3: [mq]: 7.patch - john
864 2: [mq]: 5.patch - test
864 2: [mq]: 5.patch - test
865 1: Three (again) - test
865 1: Three (again) - test
866 0: [mq]: 1.patch - test
866 0: [mq]: 1.patch - test
867 ==== qref -u -d
867 ==== qref -u -d
868 # HG changeset patch
868 # HG changeset patch
869 # User john
869 # User john
870 # Date 15 0
870 # Date 15 0
871 # Parent
871 # Parent
872 Nine
872 Nine
873
873
874 diff -r ... 9
874 diff -r ... 9
875 --- /dev/null
875 --- /dev/null
876 +++ b/9
876 +++ b/9
877 @@ -0,0 +1,1 @@
877 @@ -0,0 +1,1 @@
878 +9
878 +9
879 4: Nine - john
879 4: Nine - john
880 3: [mq]: 7.patch - john
880 3: [mq]: 7.patch - john
881 2: [mq]: 5.patch - test
881 2: [mq]: 5.patch - test
882 1: Three (again) - test
882 1: Three (again) - test
883 0: [mq]: 1.patch - test
883 0: [mq]: 1.patch - test
884 popping 9.patch
884 popping 9.patch
885 now at: 7.patch
885 now at: 7.patch
886 ==== qpop -a / qpush -a
886 ==== qpop -a / qpush -a
887 popping 7.patch
887 popping 7.patch
888 popping 5.patch
888 popping 5.patch
889 popping 3.patch
889 popping 3.patch
890 popping 1.patch
890 popping 1.patch
891 patch queue now empty
891 patch queue now empty
892 applying 1.patch
892 applying 1.patch
893 applying 3.patch
893 applying 3.patch
894 applying 5.patch
894 applying 5.patch
895 applying 7.patch
895 applying 7.patch
896 now at: 7.patch
896 now at: 7.patch
897 3: imported patch 7.patch - john - 13.00
897 3: imported patch 7.patch - john - 13.00
898 2: imported patch 5.patch - test - 11.00
898 2: imported patch 5.patch - test - 11.00
899 1: Three (again) - test - 8.00
899 1: Three (again) - test - 8.00
900 0: imported patch 1.patch - test - 4.00
900 0: imported patch 1.patch - test - 4.00
901 $ rm -r sandbox
901 $ rm -r sandbox
General Comments 0
You need to be logged in to leave comments. Login now