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