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