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