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