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