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