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