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