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