##// END OF EJS Templates
mq: support qnew -I/-X and file name lists
Brendan Cully -
r4713:c29ee52e default
parent child Browse files
Show More
@@ -1,2188 +1,2200 b''
1 # queue.py - patch queues for mercurial
1 # queue.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
5 # This software may be used and distributed according to the terms
6 # of the GNU General Public License, incorporated herein by reference.
6 # of the GNU General Public License, incorporated herein by reference.
7
7
8 '''patch management and development
8 '''patch management and development
9
9
10 This extension lets you work with a stack of patches in a Mercurial
10 This extension lets you work with a stack of patches in a Mercurial
11 repository. It manages two stacks of patches - all known patches, and
11 repository. It manages two stacks of patches - all known patches, and
12 applied patches (subset of known patches).
12 applied patches (subset of known patches).
13
13
14 Known patches are represented as patch files in the .hg/patches
14 Known patches are represented as patch files in the .hg/patches
15 directory. Applied patches are both patch files and changesets.
15 directory. Applied patches are both patch files and changesets.
16
16
17 Common tasks (use "hg help command" for more details):
17 Common tasks (use "hg help command" for more details):
18
18
19 prepare repository to work with patches qinit
19 prepare repository to work with patches qinit
20 create new patch qnew
20 create new patch qnew
21 import existing patch qimport
21 import existing patch qimport
22
22
23 print patch series qseries
23 print patch series qseries
24 print applied patches qapplied
24 print applied patches qapplied
25 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 import commands, cmdutil, hg, patch, revlog, util
33 from mercurial import commands, cmdutil, hg, patch, revlog, util
34 from mercurial import repair
34 from mercurial import repair
35 import os, sys, re, errno
35 import os, sys, re, errno
36
36
37 commands.norepo += " qclone qversion"
37 commands.norepo += " qclone qversion"
38
38
39 # Patch names looks like unix-file names.
39 # Patch names looks like unix-file names.
40 # They must be joinable with queue directory and result in the patch path.
40 # They must be joinable with queue directory and result in the patch path.
41 normname = util.normpath
41 normname = util.normpath
42
42
43 class statusentry:
43 class statusentry:
44 def __init__(self, rev, name=None):
44 def __init__(self, rev, name=None):
45 if not name:
45 if not name:
46 fields = rev.split(':', 1)
46 fields = rev.split(':', 1)
47 if len(fields) == 2:
47 if len(fields) == 2:
48 self.rev, self.name = fields
48 self.rev, self.name = fields
49 else:
49 else:
50 self.rev, self.name = None, None
50 self.rev, self.name = None, None
51 else:
51 else:
52 self.rev, self.name = rev, name
52 self.rev, self.name = rev, name
53
53
54 def __str__(self):
54 def __str__(self):
55 return self.rev + ':' + self.name
55 return self.rev + ':' + self.name
56
56
57 class queue:
57 class queue:
58 def __init__(self, ui, path, patchdir=None):
58 def __init__(self, ui, path, patchdir=None):
59 self.basepath = path
59 self.basepath = path
60 self.path = patchdir or os.path.join(path, "patches")
60 self.path = patchdir or os.path.join(path, "patches")
61 self.opener = util.opener(self.path)
61 self.opener = util.opener(self.path)
62 self.ui = ui
62 self.ui = ui
63 self.applied = []
63 self.applied = []
64 self.full_series = []
64 self.full_series = []
65 self.applied_dirty = 0
65 self.applied_dirty = 0
66 self.series_dirty = 0
66 self.series_dirty = 0
67 self.series_path = "series"
67 self.series_path = "series"
68 self.status_path = "status"
68 self.status_path = "status"
69 self.guards_path = "guards"
69 self.guards_path = "guards"
70 self.active_guards = None
70 self.active_guards = None
71 self.guards_dirty = False
71 self.guards_dirty = False
72 self._diffopts = None
72 self._diffopts = None
73
73
74 if os.path.exists(self.join(self.series_path)):
74 if os.path.exists(self.join(self.series_path)):
75 self.full_series = self.opener(self.series_path).read().splitlines()
75 self.full_series = self.opener(self.series_path).read().splitlines()
76 self.parse_series()
76 self.parse_series()
77
77
78 if os.path.exists(self.join(self.status_path)):
78 if os.path.exists(self.join(self.status_path)):
79 lines = self.opener(self.status_path).read().splitlines()
79 lines = self.opener(self.status_path).read().splitlines()
80 self.applied = [statusentry(l) for l in lines]
80 self.applied = [statusentry(l) for l in lines]
81
81
82 def diffopts(self):
82 def diffopts(self):
83 if self._diffopts is None:
83 if self._diffopts is None:
84 self._diffopts = patch.diffopts(self.ui)
84 self._diffopts = patch.diffopts(self.ui)
85 return self._diffopts
85 return self._diffopts
86
86
87 def join(self, *p):
87 def join(self, *p):
88 return os.path.join(self.path, *p)
88 return os.path.join(self.path, *p)
89
89
90 def find_series(self, patch):
90 def find_series(self, patch):
91 pre = re.compile("(\s*)([^#]+)")
91 pre = re.compile("(\s*)([^#]+)")
92 index = 0
92 index = 0
93 for l in self.full_series:
93 for l in self.full_series:
94 m = pre.match(l)
94 m = pre.match(l)
95 if m:
95 if m:
96 s = m.group(2)
96 s = m.group(2)
97 s = s.rstrip()
97 s = s.rstrip()
98 if s == patch:
98 if s == patch:
99 return index
99 return index
100 index += 1
100 index += 1
101 return None
101 return None
102
102
103 guard_re = re.compile(r'\s?#([-+][^-+# \t\r\n\f][^# \t\r\n\f]*)')
103 guard_re = re.compile(r'\s?#([-+][^-+# \t\r\n\f][^# \t\r\n\f]*)')
104
104
105 def parse_series(self):
105 def parse_series(self):
106 self.series = []
106 self.series = []
107 self.series_guards = []
107 self.series_guards = []
108 for l in self.full_series:
108 for l in self.full_series:
109 h = l.find('#')
109 h = l.find('#')
110 if h == -1:
110 if h == -1:
111 patch = l
111 patch = l
112 comment = ''
112 comment = ''
113 elif h == 0:
113 elif h == 0:
114 continue
114 continue
115 else:
115 else:
116 patch = l[:h]
116 patch = l[:h]
117 comment = l[h:]
117 comment = l[h:]
118 patch = patch.strip()
118 patch = patch.strip()
119 if patch:
119 if patch:
120 if patch in self.series:
120 if patch in self.series:
121 raise util.Abort(_('%s appears more than once in %s') %
121 raise util.Abort(_('%s appears more than once in %s') %
122 (patch, self.join(self.series_path)))
122 (patch, self.join(self.series_path)))
123 self.series.append(patch)
123 self.series.append(patch)
124 self.series_guards.append(self.guard_re.findall(comment))
124 self.series_guards.append(self.guard_re.findall(comment))
125
125
126 def check_guard(self, guard):
126 def check_guard(self, guard):
127 bad_chars = '# \t\r\n\f'
127 bad_chars = '# \t\r\n\f'
128 first = guard[0]
128 first = guard[0]
129 for c in '-+':
129 for c in '-+':
130 if first == c:
130 if first == c:
131 return (_('guard %r starts with invalid character: %r') %
131 return (_('guard %r starts with invalid character: %r') %
132 (guard, c))
132 (guard, c))
133 for c in bad_chars:
133 for c in bad_chars:
134 if c in guard:
134 if c in guard:
135 return _('invalid character in guard %r: %r') % (guard, c)
135 return _('invalid character in guard %r: %r') % (guard, c)
136
136
137 def set_active(self, guards):
137 def set_active(self, guards):
138 for guard in guards:
138 for guard in guards:
139 bad = self.check_guard(guard)
139 bad = self.check_guard(guard)
140 if bad:
140 if bad:
141 raise util.Abort(bad)
141 raise util.Abort(bad)
142 guards = dict.fromkeys(guards).keys()
142 guards = dict.fromkeys(guards).keys()
143 guards.sort()
143 guards.sort()
144 self.ui.debug('active guards: %s\n' % ' '.join(guards))
144 self.ui.debug('active guards: %s\n' % ' '.join(guards))
145 self.active_guards = guards
145 self.active_guards = guards
146 self.guards_dirty = True
146 self.guards_dirty = True
147
147
148 def active(self):
148 def active(self):
149 if self.active_guards is None:
149 if self.active_guards is None:
150 self.active_guards = []
150 self.active_guards = []
151 try:
151 try:
152 guards = self.opener(self.guards_path).read().split()
152 guards = self.opener(self.guards_path).read().split()
153 except IOError, err:
153 except IOError, err:
154 if err.errno != errno.ENOENT: raise
154 if err.errno != errno.ENOENT: raise
155 guards = []
155 guards = []
156 for i, guard in enumerate(guards):
156 for i, guard in enumerate(guards):
157 bad = self.check_guard(guard)
157 bad = self.check_guard(guard)
158 if bad:
158 if bad:
159 self.ui.warn('%s:%d: %s\n' %
159 self.ui.warn('%s:%d: %s\n' %
160 (self.join(self.guards_path), i + 1, bad))
160 (self.join(self.guards_path), i + 1, bad))
161 else:
161 else:
162 self.active_guards.append(guard)
162 self.active_guards.append(guard)
163 return self.active_guards
163 return self.active_guards
164
164
165 def set_guards(self, idx, guards):
165 def set_guards(self, idx, guards):
166 for g in guards:
166 for g in guards:
167 if len(g) < 2:
167 if len(g) < 2:
168 raise util.Abort(_('guard %r too short') % g)
168 raise util.Abort(_('guard %r too short') % g)
169 if g[0] not in '-+':
169 if g[0] not in '-+':
170 raise util.Abort(_('guard %r starts with invalid char') % g)
170 raise util.Abort(_('guard %r starts with invalid char') % g)
171 bad = self.check_guard(g[1:])
171 bad = self.check_guard(g[1:])
172 if bad:
172 if bad:
173 raise util.Abort(bad)
173 raise util.Abort(bad)
174 drop = self.guard_re.sub('', self.full_series[idx])
174 drop = self.guard_re.sub('', self.full_series[idx])
175 self.full_series[idx] = drop + ''.join([' #' + g for g in guards])
175 self.full_series[idx] = drop + ''.join([' #' + g for g in guards])
176 self.parse_series()
176 self.parse_series()
177 self.series_dirty = True
177 self.series_dirty = True
178
178
179 def pushable(self, idx):
179 def pushable(self, idx):
180 if isinstance(idx, str):
180 if isinstance(idx, str):
181 idx = self.series.index(idx)
181 idx = self.series.index(idx)
182 patchguards = self.series_guards[idx]
182 patchguards = self.series_guards[idx]
183 if not patchguards:
183 if not patchguards:
184 return True, None
184 return True, None
185 default = False
185 default = False
186 guards = self.active()
186 guards = self.active()
187 exactneg = [g for g in patchguards if g[0] == '-' and g[1:] in guards]
187 exactneg = [g for g in patchguards if g[0] == '-' and g[1:] in guards]
188 if exactneg:
188 if exactneg:
189 return False, exactneg[0]
189 return False, exactneg[0]
190 pos = [g for g in patchguards if g[0] == '+']
190 pos = [g for g in patchguards if g[0] == '+']
191 exactpos = [g for g in pos if g[1:] in guards]
191 exactpos = [g for g in pos if g[1:] in guards]
192 if pos:
192 if pos:
193 if exactpos:
193 if exactpos:
194 return True, exactpos[0]
194 return True, exactpos[0]
195 return False, pos
195 return False, pos
196 return True, ''
196 return True, ''
197
197
198 def explain_pushable(self, idx, all_patches=False):
198 def explain_pushable(self, idx, all_patches=False):
199 write = all_patches and self.ui.write or self.ui.warn
199 write = all_patches and self.ui.write or self.ui.warn
200 if all_patches or self.ui.verbose:
200 if all_patches or self.ui.verbose:
201 if isinstance(idx, str):
201 if isinstance(idx, str):
202 idx = self.series.index(idx)
202 idx = self.series.index(idx)
203 pushable, why = self.pushable(idx)
203 pushable, why = self.pushable(idx)
204 if all_patches and pushable:
204 if all_patches and pushable:
205 if why is None:
205 if why is None:
206 write(_('allowing %s - no guards in effect\n') %
206 write(_('allowing %s - no guards in effect\n') %
207 self.series[idx])
207 self.series[idx])
208 else:
208 else:
209 if not why:
209 if not why:
210 write(_('allowing %s - no matching negative guards\n') %
210 write(_('allowing %s - no matching negative guards\n') %
211 self.series[idx])
211 self.series[idx])
212 else:
212 else:
213 write(_('allowing %s - guarded by %r\n') %
213 write(_('allowing %s - guarded by %r\n') %
214 (self.series[idx], why))
214 (self.series[idx], why))
215 if not pushable:
215 if not pushable:
216 if why:
216 if why:
217 write(_('skipping %s - guarded by %r\n') %
217 write(_('skipping %s - guarded by %r\n') %
218 (self.series[idx], why))
218 (self.series[idx], why))
219 else:
219 else:
220 write(_('skipping %s - no matching guards\n') %
220 write(_('skipping %s - no matching guards\n') %
221 self.series[idx])
221 self.series[idx])
222
222
223 def save_dirty(self):
223 def save_dirty(self):
224 def write_list(items, path):
224 def write_list(items, path):
225 fp = self.opener(path, 'w')
225 fp = self.opener(path, 'w')
226 for i in items:
226 for i in items:
227 print >> fp, i
227 print >> fp, i
228 fp.close()
228 fp.close()
229 if self.applied_dirty: write_list(map(str, self.applied), self.status_path)
229 if self.applied_dirty: write_list(map(str, self.applied), self.status_path)
230 if self.series_dirty: write_list(self.full_series, self.series_path)
230 if self.series_dirty: write_list(self.full_series, self.series_path)
231 if self.guards_dirty: write_list(self.active_guards, self.guards_path)
231 if self.guards_dirty: write_list(self.active_guards, self.guards_path)
232
232
233 def readheaders(self, patch):
233 def readheaders(self, patch):
234 def eatdiff(lines):
234 def eatdiff(lines):
235 while lines:
235 while lines:
236 l = lines[-1]
236 l = lines[-1]
237 if (l.startswith("diff -") or
237 if (l.startswith("diff -") or
238 l.startswith("Index:") or
238 l.startswith("Index:") or
239 l.startswith("===========")):
239 l.startswith("===========")):
240 del lines[-1]
240 del lines[-1]
241 else:
241 else:
242 break
242 break
243 def eatempty(lines):
243 def eatempty(lines):
244 while lines:
244 while lines:
245 l = lines[-1]
245 l = lines[-1]
246 if re.match('\s*$', l):
246 if re.match('\s*$', l):
247 del lines[-1]
247 del lines[-1]
248 else:
248 else:
249 break
249 break
250
250
251 pf = self.join(patch)
251 pf = self.join(patch)
252 message = []
252 message = []
253 comments = []
253 comments = []
254 user = None
254 user = None
255 date = None
255 date = None
256 format = None
256 format = None
257 subject = None
257 subject = None
258 diffstart = 0
258 diffstart = 0
259
259
260 for line in file(pf):
260 for line in file(pf):
261 line = line.rstrip()
261 line = line.rstrip()
262 if line.startswith('diff --git'):
262 if line.startswith('diff --git'):
263 diffstart = 2
263 diffstart = 2
264 break
264 break
265 if diffstart:
265 if diffstart:
266 if line.startswith('+++ '):
266 if line.startswith('+++ '):
267 diffstart = 2
267 diffstart = 2
268 break
268 break
269 if line.startswith("--- "):
269 if line.startswith("--- "):
270 diffstart = 1
270 diffstart = 1
271 continue
271 continue
272 elif format == "hgpatch":
272 elif format == "hgpatch":
273 # parse values when importing the result of an hg export
273 # parse values when importing the result of an hg export
274 if line.startswith("# User "):
274 if line.startswith("# User "):
275 user = line[7:]
275 user = line[7:]
276 elif line.startswith("# Date "):
276 elif line.startswith("# Date "):
277 date = line[7:]
277 date = line[7:]
278 elif not line.startswith("# ") and line:
278 elif not line.startswith("# ") and line:
279 message.append(line)
279 message.append(line)
280 format = None
280 format = None
281 elif line == '# HG changeset patch':
281 elif line == '# HG changeset patch':
282 format = "hgpatch"
282 format = "hgpatch"
283 elif (format != "tagdone" and (line.startswith("Subject: ") or
283 elif (format != "tagdone" and (line.startswith("Subject: ") or
284 line.startswith("subject: "))):
284 line.startswith("subject: "))):
285 subject = line[9:]
285 subject = line[9:]
286 format = "tag"
286 format = "tag"
287 elif (format != "tagdone" and (line.startswith("From: ") or
287 elif (format != "tagdone" and (line.startswith("From: ") or
288 line.startswith("from: "))):
288 line.startswith("from: "))):
289 user = line[6:]
289 user = line[6:]
290 format = "tag"
290 format = "tag"
291 elif format == "tag" and line == "":
291 elif format == "tag" and line == "":
292 # when looking for tags (subject: from: etc) they
292 # when looking for tags (subject: from: etc) they
293 # end once you find a blank line in the source
293 # end once you find a blank line in the source
294 format = "tagdone"
294 format = "tagdone"
295 elif message or line:
295 elif message or line:
296 message.append(line)
296 message.append(line)
297 comments.append(line)
297 comments.append(line)
298
298
299 eatdiff(message)
299 eatdiff(message)
300 eatdiff(comments)
300 eatdiff(comments)
301 eatempty(message)
301 eatempty(message)
302 eatempty(comments)
302 eatempty(comments)
303
303
304 # make sure message isn't empty
304 # make sure message isn't empty
305 if format and format.startswith("tag") and subject:
305 if format and format.startswith("tag") and subject:
306 message.insert(0, "")
306 message.insert(0, "")
307 message.insert(0, subject)
307 message.insert(0, subject)
308 return (message, comments, user, date, diffstart > 1)
308 return (message, comments, user, date, diffstart > 1)
309
309
310 def removeundo(self, repo):
310 def removeundo(self, repo):
311 undo = repo.sjoin('undo')
311 undo = repo.sjoin('undo')
312 if not os.path.exists(undo):
312 if not os.path.exists(undo):
313 return
313 return
314 try:
314 try:
315 os.unlink(undo)
315 os.unlink(undo)
316 except OSError, inst:
316 except OSError, inst:
317 self.ui.warn('error removing undo: %s\n' % str(inst))
317 self.ui.warn('error removing undo: %s\n' % str(inst))
318
318
319 def printdiff(self, repo, node1, node2=None, files=None,
319 def printdiff(self, repo, node1, node2=None, files=None,
320 fp=None, changes=None, opts={}):
320 fp=None, changes=None, opts={}):
321 fns, matchfn, anypats = cmdutil.matchpats(repo, files, opts)
321 fns, matchfn, anypats = cmdutil.matchpats(repo, files, opts)
322
322
323 patch.diff(repo, node1, node2, fns, match=matchfn,
323 patch.diff(repo, node1, node2, fns, match=matchfn,
324 fp=fp, changes=changes, opts=self.diffopts())
324 fp=fp, changes=changes, opts=self.diffopts())
325
325
326 def mergeone(self, repo, mergeq, head, patch, rev, wlock):
326 def mergeone(self, repo, mergeq, head, patch, rev, wlock):
327 # first try just applying the patch
327 # first try just applying the patch
328 (err, n) = self.apply(repo, [ patch ], update_status=False,
328 (err, n) = self.apply(repo, [ patch ], update_status=False,
329 strict=True, merge=rev, wlock=wlock)
329 strict=True, merge=rev, wlock=wlock)
330
330
331 if err == 0:
331 if err == 0:
332 return (err, n)
332 return (err, n)
333
333
334 if n is None:
334 if n is None:
335 raise util.Abort(_("apply failed for patch %s") % patch)
335 raise util.Abort(_("apply failed for patch %s") % patch)
336
336
337 self.ui.warn("patch didn't work out, merging %s\n" % patch)
337 self.ui.warn("patch didn't work out, merging %s\n" % patch)
338
338
339 # apply failed, strip away that rev and merge.
339 # apply failed, strip away that rev and merge.
340 hg.clean(repo, head, wlock=wlock)
340 hg.clean(repo, head, wlock=wlock)
341 self.strip(repo, n, update=False, backup='strip', wlock=wlock)
341 self.strip(repo, n, update=False, backup='strip', wlock=wlock)
342
342
343 ctx = repo.changectx(rev)
343 ctx = repo.changectx(rev)
344 ret = hg.merge(repo, rev, wlock=wlock)
344 ret = hg.merge(repo, rev, wlock=wlock)
345 if ret:
345 if ret:
346 raise util.Abort(_("update returned %d") % ret)
346 raise util.Abort(_("update returned %d") % ret)
347 n = repo.commit(None, ctx.description(), ctx.user(),
347 n = repo.commit(None, ctx.description(), ctx.user(),
348 force=1, wlock=wlock)
348 force=1, wlock=wlock)
349 if n == None:
349 if n == None:
350 raise util.Abort(_("repo commit failed"))
350 raise util.Abort(_("repo commit failed"))
351 try:
351 try:
352 message, comments, user, date, patchfound = mergeq.readheaders(patch)
352 message, comments, user, date, patchfound = mergeq.readheaders(patch)
353 except:
353 except:
354 raise util.Abort(_("unable to read %s") % patch)
354 raise util.Abort(_("unable to read %s") % patch)
355
355
356 patchf = self.opener(patch, "w")
356 patchf = self.opener(patch, "w")
357 if comments:
357 if comments:
358 comments = "\n".join(comments) + '\n\n'
358 comments = "\n".join(comments) + '\n\n'
359 patchf.write(comments)
359 patchf.write(comments)
360 self.printdiff(repo, head, n, fp=patchf)
360 self.printdiff(repo, head, n, fp=patchf)
361 patchf.close()
361 patchf.close()
362 self.removeundo(repo)
362 self.removeundo(repo)
363 return (0, n)
363 return (0, n)
364
364
365 def qparents(self, repo, rev=None):
365 def qparents(self, repo, rev=None):
366 if rev is None:
366 if rev is None:
367 (p1, p2) = repo.dirstate.parents()
367 (p1, p2) = repo.dirstate.parents()
368 if p2 == revlog.nullid:
368 if p2 == revlog.nullid:
369 return p1
369 return p1
370 if len(self.applied) == 0:
370 if len(self.applied) == 0:
371 return None
371 return None
372 return revlog.bin(self.applied[-1].rev)
372 return revlog.bin(self.applied[-1].rev)
373 pp = repo.changelog.parents(rev)
373 pp = repo.changelog.parents(rev)
374 if pp[1] != revlog.nullid:
374 if pp[1] != revlog.nullid:
375 arevs = [ x.rev for x in self.applied ]
375 arevs = [ x.rev for x in self.applied ]
376 p0 = revlog.hex(pp[0])
376 p0 = revlog.hex(pp[0])
377 p1 = revlog.hex(pp[1])
377 p1 = revlog.hex(pp[1])
378 if p0 in arevs:
378 if p0 in arevs:
379 return pp[0]
379 return pp[0]
380 if p1 in arevs:
380 if p1 in arevs:
381 return pp[1]
381 return pp[1]
382 return pp[0]
382 return pp[0]
383
383
384 def mergepatch(self, repo, mergeq, series, wlock):
384 def mergepatch(self, repo, mergeq, series, wlock):
385 if len(self.applied) == 0:
385 if len(self.applied) == 0:
386 # each of the patches merged in will have two parents. This
386 # each of the patches merged in will have two parents. This
387 # can confuse the qrefresh, qdiff, and strip code because it
387 # can confuse the qrefresh, qdiff, and strip code because it
388 # needs to know which parent is actually in the patch queue.
388 # needs to know which parent is actually in the patch queue.
389 # so, we insert a merge marker with only one parent. This way
389 # so, we insert a merge marker with only one parent. This way
390 # the first patch in the queue is never a merge patch
390 # the first patch in the queue is never a merge patch
391 #
391 #
392 pname = ".hg.patches.merge.marker"
392 pname = ".hg.patches.merge.marker"
393 n = repo.commit(None, '[mq]: merge marker', user=None, force=1,
393 n = repo.commit(None, '[mq]: merge marker', user=None, force=1,
394 wlock=wlock)
394 wlock=wlock)
395 self.removeundo(repo)
395 self.removeundo(repo)
396 self.applied.append(statusentry(revlog.hex(n), pname))
396 self.applied.append(statusentry(revlog.hex(n), pname))
397 self.applied_dirty = 1
397 self.applied_dirty = 1
398
398
399 head = self.qparents(repo)
399 head = self.qparents(repo)
400
400
401 for patch in series:
401 for patch in series:
402 patch = mergeq.lookup(patch, strict=True)
402 patch = mergeq.lookup(patch, strict=True)
403 if not patch:
403 if not patch:
404 self.ui.warn("patch %s does not exist\n" % patch)
404 self.ui.warn("patch %s does not exist\n" % patch)
405 return (1, None)
405 return (1, None)
406 pushable, reason = self.pushable(patch)
406 pushable, reason = self.pushable(patch)
407 if not pushable:
407 if not pushable:
408 self.explain_pushable(patch, all_patches=True)
408 self.explain_pushable(patch, all_patches=True)
409 continue
409 continue
410 info = mergeq.isapplied(patch)
410 info = mergeq.isapplied(patch)
411 if not info:
411 if not info:
412 self.ui.warn("patch %s is not applied\n" % patch)
412 self.ui.warn("patch %s is not applied\n" % patch)
413 return (1, None)
413 return (1, None)
414 rev = revlog.bin(info[1])
414 rev = revlog.bin(info[1])
415 (err, head) = self.mergeone(repo, mergeq, head, patch, rev, wlock)
415 (err, head) = self.mergeone(repo, mergeq, head, patch, rev, wlock)
416 if head:
416 if head:
417 self.applied.append(statusentry(revlog.hex(head), patch))
417 self.applied.append(statusentry(revlog.hex(head), patch))
418 self.applied_dirty = 1
418 self.applied_dirty = 1
419 if err:
419 if err:
420 return (err, head)
420 return (err, head)
421 self.save_dirty()
421 self.save_dirty()
422 return (0, head)
422 return (0, head)
423
423
424 def patch(self, repo, patchfile):
424 def patch(self, repo, patchfile):
425 '''Apply patchfile to the working directory.
425 '''Apply patchfile to the working directory.
426 patchfile: file name of patch'''
426 patchfile: file name of patch'''
427 files = {}
427 files = {}
428 try:
428 try:
429 fuzz = patch.patch(patchfile, self.ui, strip=1, cwd=repo.root,
429 fuzz = patch.patch(patchfile, self.ui, strip=1, cwd=repo.root,
430 files=files)
430 files=files)
431 except Exception, inst:
431 except Exception, inst:
432 self.ui.note(str(inst) + '\n')
432 self.ui.note(str(inst) + '\n')
433 if not self.ui.verbose:
433 if not self.ui.verbose:
434 self.ui.warn("patch failed, unable to continue (try -v)\n")
434 self.ui.warn("patch failed, unable to continue (try -v)\n")
435 return (False, files, False)
435 return (False, files, False)
436
436
437 return (True, files, fuzz)
437 return (True, files, fuzz)
438
438
439 def apply(self, repo, series, list=False, update_status=True,
439 def apply(self, repo, series, list=False, update_status=True,
440 strict=False, patchdir=None, merge=None, wlock=None,
440 strict=False, patchdir=None, merge=None, wlock=None,
441 all_files={}):
441 all_files={}):
442 if not wlock:
442 if not wlock:
443 wlock = repo.wlock()
443 wlock = repo.wlock()
444 lock = repo.lock()
444 lock = repo.lock()
445 tr = repo.transaction()
445 tr = repo.transaction()
446 try:
446 try:
447 ret = self._apply(tr, repo, series, list, update_status,
447 ret = self._apply(tr, repo, series, list, update_status,
448 strict, patchdir, merge, wlock,
448 strict, patchdir, merge, wlock,
449 lock=lock, all_files=all_files)
449 lock=lock, all_files=all_files)
450 tr.close()
450 tr.close()
451 self.save_dirty()
451 self.save_dirty()
452 return ret
452 return ret
453 except:
453 except:
454 try:
454 try:
455 tr.abort()
455 tr.abort()
456 finally:
456 finally:
457 repo.invalidate()
457 repo.invalidate()
458 repo.dirstate.invalidate()
458 repo.dirstate.invalidate()
459 raise
459 raise
460
460
461 def _apply(self, tr, repo, series, list=False, update_status=True,
461 def _apply(self, tr, repo, series, list=False, update_status=True,
462 strict=False, patchdir=None, merge=None, wlock=None,
462 strict=False, patchdir=None, merge=None, wlock=None,
463 lock=None, all_files={}):
463 lock=None, all_files={}):
464 # TODO unify with commands.py
464 # TODO unify with commands.py
465 if not patchdir:
465 if not patchdir:
466 patchdir = self.path
466 patchdir = self.path
467 err = 0
467 err = 0
468 n = None
468 n = None
469 for patchname in series:
469 for patchname in series:
470 pushable, reason = self.pushable(patchname)
470 pushable, reason = self.pushable(patchname)
471 if not pushable:
471 if not pushable:
472 self.explain_pushable(patchname, all_patches=True)
472 self.explain_pushable(patchname, all_patches=True)
473 continue
473 continue
474 self.ui.warn("applying %s\n" % patchname)
474 self.ui.warn("applying %s\n" % patchname)
475 pf = os.path.join(patchdir, patchname)
475 pf = os.path.join(patchdir, patchname)
476
476
477 try:
477 try:
478 message, comments, user, date, patchfound = self.readheaders(patchname)
478 message, comments, user, date, patchfound = self.readheaders(patchname)
479 except:
479 except:
480 self.ui.warn("Unable to read %s\n" % patchname)
480 self.ui.warn("Unable to read %s\n" % patchname)
481 err = 1
481 err = 1
482 break
482 break
483
483
484 if not message:
484 if not message:
485 message = "imported patch %s\n" % patchname
485 message = "imported patch %s\n" % patchname
486 else:
486 else:
487 if list:
487 if list:
488 message.append("\nimported patch %s" % patchname)
488 message.append("\nimported patch %s" % patchname)
489 message = '\n'.join(message)
489 message = '\n'.join(message)
490
490
491 (patcherr, files, fuzz) = self.patch(repo, pf)
491 (patcherr, files, fuzz) = self.patch(repo, pf)
492 all_files.update(files)
492 all_files.update(files)
493 patcherr = not patcherr
493 patcherr = not patcherr
494
494
495 if merge and files:
495 if merge and files:
496 # Mark as removed/merged and update dirstate parent info
496 # Mark as removed/merged and update dirstate parent info
497 removed = []
497 removed = []
498 merged = []
498 merged = []
499 for f in files:
499 for f in files:
500 if os.path.exists(repo.dirstate.wjoin(f)):
500 if os.path.exists(repo.dirstate.wjoin(f)):
501 merged.append(f)
501 merged.append(f)
502 else:
502 else:
503 removed.append(f)
503 removed.append(f)
504 repo.dirstate.update(repo.dirstate.filterfiles(removed), 'r')
504 repo.dirstate.update(repo.dirstate.filterfiles(removed), 'r')
505 repo.dirstate.update(repo.dirstate.filterfiles(merged), 'm')
505 repo.dirstate.update(repo.dirstate.filterfiles(merged), 'm')
506 p1, p2 = repo.dirstate.parents()
506 p1, p2 = repo.dirstate.parents()
507 repo.dirstate.setparents(p1, merge)
507 repo.dirstate.setparents(p1, merge)
508 files = patch.updatedir(self.ui, repo, files, wlock=wlock)
508 files = patch.updatedir(self.ui, repo, files, wlock=wlock)
509 n = repo.commit(files, message, user, date, force=1, lock=lock,
509 n = repo.commit(files, message, user, date, force=1, lock=lock,
510 wlock=wlock)
510 wlock=wlock)
511
511
512 if n == None:
512 if n == None:
513 raise util.Abort(_("repo commit failed"))
513 raise util.Abort(_("repo commit failed"))
514
514
515 if update_status:
515 if update_status:
516 self.applied.append(statusentry(revlog.hex(n), patchname))
516 self.applied.append(statusentry(revlog.hex(n), patchname))
517
517
518 if patcherr:
518 if patcherr:
519 if not patchfound:
519 if not patchfound:
520 self.ui.warn("patch %s is empty\n" % patchname)
520 self.ui.warn("patch %s is empty\n" % patchname)
521 err = 0
521 err = 0
522 else:
522 else:
523 self.ui.warn("patch failed, rejects left in working dir\n")
523 self.ui.warn("patch failed, rejects left in working dir\n")
524 err = 1
524 err = 1
525 break
525 break
526
526
527 if fuzz and strict:
527 if fuzz and strict:
528 self.ui.warn("fuzz found when applying patch, stopping\n")
528 self.ui.warn("fuzz found when applying patch, stopping\n")
529 err = 1
529 err = 1
530 break
530 break
531 self.removeundo(repo)
531 self.removeundo(repo)
532 return (err, n)
532 return (err, n)
533
533
534 def delete(self, repo, patches, opts):
534 def delete(self, repo, patches, opts):
535 realpatches = []
535 realpatches = []
536 for patch in patches:
536 for patch in patches:
537 patch = self.lookup(patch, strict=True)
537 patch = self.lookup(patch, strict=True)
538 info = self.isapplied(patch)
538 info = self.isapplied(patch)
539 if info:
539 if info:
540 raise util.Abort(_("cannot delete applied patch %s") % patch)
540 raise util.Abort(_("cannot delete applied patch %s") % patch)
541 if patch not in self.series:
541 if patch not in self.series:
542 raise util.Abort(_("patch %s not in series file") % patch)
542 raise util.Abort(_("patch %s not in series file") % patch)
543 realpatches.append(patch)
543 realpatches.append(patch)
544
544
545 appliedbase = 0
545 appliedbase = 0
546 if opts.get('rev'):
546 if opts.get('rev'):
547 if not self.applied:
547 if not self.applied:
548 raise util.Abort(_('no patches applied'))
548 raise util.Abort(_('no patches applied'))
549 revs = cmdutil.revrange(repo, opts['rev'])
549 revs = cmdutil.revrange(repo, opts['rev'])
550 if len(revs) > 1 and revs[0] > revs[1]:
550 if len(revs) > 1 and revs[0] > revs[1]:
551 revs.reverse()
551 revs.reverse()
552 for rev in revs:
552 for rev in revs:
553 if appliedbase >= len(self.applied):
553 if appliedbase >= len(self.applied):
554 raise util.Abort(_("revision %d is not managed") % rev)
554 raise util.Abort(_("revision %d is not managed") % rev)
555
555
556 base = revlog.bin(self.applied[appliedbase].rev)
556 base = revlog.bin(self.applied[appliedbase].rev)
557 node = repo.changelog.node(rev)
557 node = repo.changelog.node(rev)
558 if node != base:
558 if node != base:
559 raise util.Abort(_("cannot delete revision %d above "
559 raise util.Abort(_("cannot delete revision %d above "
560 "applied patches") % rev)
560 "applied patches") % rev)
561 realpatches.append(self.applied[appliedbase].name)
561 realpatches.append(self.applied[appliedbase].name)
562 appliedbase += 1
562 appliedbase += 1
563
563
564 if not opts.get('keep'):
564 if not opts.get('keep'):
565 r = self.qrepo()
565 r = self.qrepo()
566 if r:
566 if r:
567 r.remove(realpatches, True)
567 r.remove(realpatches, True)
568 else:
568 else:
569 for p in realpatches:
569 for p in realpatches:
570 os.unlink(self.join(p))
570 os.unlink(self.join(p))
571
571
572 if appliedbase:
572 if appliedbase:
573 del self.applied[:appliedbase]
573 del self.applied[:appliedbase]
574 self.applied_dirty = 1
574 self.applied_dirty = 1
575 indices = [self.find_series(p) for p in realpatches]
575 indices = [self.find_series(p) for p in realpatches]
576 indices.sort()
576 indices.sort()
577 for i in indices[-1::-1]:
577 for i in indices[-1::-1]:
578 del self.full_series[i]
578 del self.full_series[i]
579 self.parse_series()
579 self.parse_series()
580 self.series_dirty = 1
580 self.series_dirty = 1
581
581
582 def check_toppatch(self, repo):
582 def check_toppatch(self, repo):
583 if len(self.applied) > 0:
583 if len(self.applied) > 0:
584 top = revlog.bin(self.applied[-1].rev)
584 top = revlog.bin(self.applied[-1].rev)
585 pp = repo.dirstate.parents()
585 pp = repo.dirstate.parents()
586 if top not in pp:
586 if top not in pp:
587 raise util.Abort(_("queue top not at same revision as working directory"))
587 raise util.Abort(_("queue top not at same revision as working directory"))
588 return top
588 return top
589 return None
589 return None
590 def check_localchanges(self, repo, force=False, refresh=True):
590 def check_localchanges(self, repo, force=False, refresh=True):
591 m, a, r, d = repo.status()[:4]
591 m, a, r, d = repo.status()[:4]
592 if m or a or r or d:
592 if m or a or r or d:
593 if not force:
593 if not force:
594 if refresh:
594 if refresh:
595 raise util.Abort(_("local changes found, refresh first"))
595 raise util.Abort(_("local changes found, refresh first"))
596 else:
596 else:
597 raise util.Abort(_("local changes found"))
597 raise util.Abort(_("local changes found"))
598 return m, a, r, d
598 return m, a, r, d
599 def new(self, repo, patch, msg=None, force=None):
599
600 def new(self, repo, patch, *pats, **opts):
601 msg = opts.get('msg')
602 force = opts.get('force')
600 if os.path.exists(self.join(patch)):
603 if os.path.exists(self.join(patch)):
601 raise util.Abort(_('patch "%s" already exists') % patch)
604 raise util.Abort(_('patch "%s" already exists') % patch)
605 if opts.get('include') or opts.get('exclude') or pats:
606 fns, match, anypats = cmdutil.matchpats(repo, pats, opts)
607 m, a, r, d = repo.status(files=fns, match=match)[:4]
608 else:
602 m, a, r, d = self.check_localchanges(repo, force)
609 m, a, r, d = self.check_localchanges(repo, force)
603 commitfiles = m + a + r
610 commitfiles = m + a + r
604 self.check_toppatch(repo)
611 self.check_toppatch(repo)
605 wlock = repo.wlock()
612 wlock = repo.wlock()
606 insert = self.full_series_end()
613 insert = self.full_series_end()
607 if msg:
614 if msg:
608 n = repo.commit(commitfiles, "[mq]: %s" % msg, force=True,
615 n = repo.commit(commitfiles, "[mq]: %s" % msg, force=True,
609 wlock=wlock)
616 wlock=wlock)
610 else:
617 else:
611 n = repo.commit(commitfiles,
618 n = repo.commit(commitfiles,
612 "New patch: %s" % patch, force=True, wlock=wlock)
619 "New patch: %s" % patch, force=True, wlock=wlock)
613 if n == None:
620 if n == None:
614 raise util.Abort(_("repo commit failed"))
621 raise util.Abort(_("repo commit failed"))
615 self.full_series[insert:insert] = [patch]
622 self.full_series[insert:insert] = [patch]
616 self.applied.append(statusentry(revlog.hex(n), patch))
623 self.applied.append(statusentry(revlog.hex(n), patch))
617 self.parse_series()
624 self.parse_series()
618 self.series_dirty = 1
625 self.series_dirty = 1
619 self.applied_dirty = 1
626 self.applied_dirty = 1
620 p = self.opener(patch, "w")
627 p = self.opener(patch, "w")
621 if msg:
628 if msg:
622 msg = msg + "\n"
629 msg = msg + "\n"
623 p.write(msg)
630 p.write(msg)
624 p.close()
631 p.close()
625 wlock = None
632 wlock = None
626 r = self.qrepo()
633 r = self.qrepo()
627 if r: r.add([patch])
634 if r: r.add([patch])
628 if commitfiles:
635 if commitfiles:
629 self.refresh(repo, short=True)
636 self.refresh(repo, short=True)
630 self.removeundo(repo)
637 self.removeundo(repo)
631
638
632 def strip(self, repo, rev, update=True, backup="all", wlock=None):
639 def strip(self, repo, rev, update=True, backup="all", wlock=None):
633 if not wlock:
640 if not wlock:
634 wlock = repo.wlock()
641 wlock = repo.wlock()
635 lock = repo.lock()
642 lock = repo.lock()
636
643
637 if update:
644 if update:
638 self.check_localchanges(repo, refresh=False)
645 self.check_localchanges(repo, refresh=False)
639 urev = self.qparents(repo, rev)
646 urev = self.qparents(repo, rev)
640 hg.clean(repo, urev, wlock=wlock)
647 hg.clean(repo, urev, wlock=wlock)
641 repo.dirstate.write()
648 repo.dirstate.write()
642
649
643 self.removeundo(repo)
650 self.removeundo(repo)
644 repair.strip(self.ui, repo, rev, backup)
651 repair.strip(self.ui, repo, rev, backup)
645
652
646 def isapplied(self, patch):
653 def isapplied(self, patch):
647 """returns (index, rev, patch)"""
654 """returns (index, rev, patch)"""
648 for i in xrange(len(self.applied)):
655 for i in xrange(len(self.applied)):
649 a = self.applied[i]
656 a = self.applied[i]
650 if a.name == patch:
657 if a.name == patch:
651 return (i, a.rev, a.name)
658 return (i, a.rev, a.name)
652 return None
659 return None
653
660
654 # if the exact patch name does not exist, we try a few
661 # if the exact patch name does not exist, we try a few
655 # variations. If strict is passed, we try only #1
662 # variations. If strict is passed, we try only #1
656 #
663 #
657 # 1) a number to indicate an offset in the series file
664 # 1) a number to indicate an offset in the series file
658 # 2) a unique substring of the patch name was given
665 # 2) a unique substring of the patch name was given
659 # 3) patchname[-+]num to indicate an offset in the series file
666 # 3) patchname[-+]num to indicate an offset in the series file
660 def lookup(self, patch, strict=False):
667 def lookup(self, patch, strict=False):
661 patch = patch and str(patch)
668 patch = patch and str(patch)
662
669
663 def partial_name(s):
670 def partial_name(s):
664 if s in self.series:
671 if s in self.series:
665 return s
672 return s
666 matches = [x for x in self.series if s in x]
673 matches = [x for x in self.series if s in x]
667 if len(matches) > 1:
674 if len(matches) > 1:
668 self.ui.warn(_('patch name "%s" is ambiguous:\n') % s)
675 self.ui.warn(_('patch name "%s" is ambiguous:\n') % s)
669 for m in matches:
676 for m in matches:
670 self.ui.warn(' %s\n' % m)
677 self.ui.warn(' %s\n' % m)
671 return None
678 return None
672 if matches:
679 if matches:
673 return matches[0]
680 return matches[0]
674 if len(self.series) > 0 and len(self.applied) > 0:
681 if len(self.series) > 0 and len(self.applied) > 0:
675 if s == 'qtip':
682 if s == 'qtip':
676 return self.series[self.series_end(True)-1]
683 return self.series[self.series_end(True)-1]
677 if s == 'qbase':
684 if s == 'qbase':
678 return self.series[0]
685 return self.series[0]
679 return None
686 return None
680 if patch == None:
687 if patch == None:
681 return None
688 return None
682
689
683 # we don't want to return a partial match until we make
690 # we don't want to return a partial match until we make
684 # sure the file name passed in does not exist (checked below)
691 # sure the file name passed in does not exist (checked below)
685 res = partial_name(patch)
692 res = partial_name(patch)
686 if res and res == patch:
693 if res and res == patch:
687 return res
694 return res
688
695
689 if not os.path.isfile(self.join(patch)):
696 if not os.path.isfile(self.join(patch)):
690 try:
697 try:
691 sno = int(patch)
698 sno = int(patch)
692 except(ValueError, OverflowError):
699 except(ValueError, OverflowError):
693 pass
700 pass
694 else:
701 else:
695 if sno < len(self.series):
702 if sno < len(self.series):
696 return self.series[sno]
703 return self.series[sno]
697 if not strict:
704 if not strict:
698 # return any partial match made above
705 # return any partial match made above
699 if res:
706 if res:
700 return res
707 return res
701 minus = patch.rfind('-')
708 minus = patch.rfind('-')
702 if minus >= 0:
709 if minus >= 0:
703 res = partial_name(patch[:minus])
710 res = partial_name(patch[:minus])
704 if res:
711 if res:
705 i = self.series.index(res)
712 i = self.series.index(res)
706 try:
713 try:
707 off = int(patch[minus+1:] or 1)
714 off = int(patch[minus+1:] or 1)
708 except(ValueError, OverflowError):
715 except(ValueError, OverflowError):
709 pass
716 pass
710 else:
717 else:
711 if i - off >= 0:
718 if i - off >= 0:
712 return self.series[i - off]
719 return self.series[i - off]
713 plus = patch.rfind('+')
720 plus = patch.rfind('+')
714 if plus >= 0:
721 if plus >= 0:
715 res = partial_name(patch[:plus])
722 res = partial_name(patch[:plus])
716 if res:
723 if res:
717 i = self.series.index(res)
724 i = self.series.index(res)
718 try:
725 try:
719 off = int(patch[plus+1:] or 1)
726 off = int(patch[plus+1:] or 1)
720 except(ValueError, OverflowError):
727 except(ValueError, OverflowError):
721 pass
728 pass
722 else:
729 else:
723 if i + off < len(self.series):
730 if i + off < len(self.series):
724 return self.series[i + off]
731 return self.series[i + off]
725 raise util.Abort(_("patch %s not in series") % patch)
732 raise util.Abort(_("patch %s not in series") % patch)
726
733
727 def push(self, repo, patch=None, force=False, list=False,
734 def push(self, repo, patch=None, force=False, list=False,
728 mergeq=None, wlock=None):
735 mergeq=None, wlock=None):
729 if not wlock:
736 if not wlock:
730 wlock = repo.wlock()
737 wlock = repo.wlock()
731 patch = self.lookup(patch)
738 patch = self.lookup(patch)
732 # Suppose our series file is: A B C and the current 'top' patch is B.
739 # Suppose our series file is: A B C and the current 'top' patch is B.
733 # qpush C should be performed (moving forward)
740 # qpush C should be performed (moving forward)
734 # qpush B is a NOP (no change)
741 # qpush B is a NOP (no change)
735 # qpush A is an error (can't go backwards with qpush)
742 # qpush A is an error (can't go backwards with qpush)
736 if patch:
743 if patch:
737 info = self.isapplied(patch)
744 info = self.isapplied(patch)
738 if info:
745 if info:
739 if info[0] < len(self.applied) - 1:
746 if info[0] < len(self.applied) - 1:
740 raise util.Abort(_("cannot push to a previous patch: %s") %
747 raise util.Abort(_("cannot push to a previous patch: %s") %
741 patch)
748 patch)
742 if info[0] < len(self.series) - 1:
749 if info[0] < len(self.series) - 1:
743 self.ui.warn(_('qpush: %s is already at the top\n') % patch)
750 self.ui.warn(_('qpush: %s is already at the top\n') % patch)
744 else:
751 else:
745 self.ui.warn(_('all patches are currently applied\n'))
752 self.ui.warn(_('all patches are currently applied\n'))
746 return
753 return
747
754
748 # Following the above example, starting at 'top' of B:
755 # Following the above example, starting at 'top' of B:
749 # qpush should be performed (pushes C), but a subsequent qpush without
756 # qpush should be performed (pushes C), but a subsequent qpush without
750 # an argument is an error (nothing to apply). This allows a loop
757 # an argument is an error (nothing to apply). This allows a loop
751 # of "...while hg qpush..." to work as it detects an error when done
758 # of "...while hg qpush..." to work as it detects an error when done
752 if self.series_end() == len(self.series):
759 if self.series_end() == len(self.series):
753 self.ui.warn(_('patch series already fully applied\n'))
760 self.ui.warn(_('patch series already fully applied\n'))
754 return 1
761 return 1
755 if not force:
762 if not force:
756 self.check_localchanges(repo)
763 self.check_localchanges(repo)
757
764
758 self.applied_dirty = 1;
765 self.applied_dirty = 1;
759 start = self.series_end()
766 start = self.series_end()
760 if start > 0:
767 if start > 0:
761 self.check_toppatch(repo)
768 self.check_toppatch(repo)
762 if not patch:
769 if not patch:
763 patch = self.series[start]
770 patch = self.series[start]
764 end = start + 1
771 end = start + 1
765 else:
772 else:
766 end = self.series.index(patch, start) + 1
773 end = self.series.index(patch, start) + 1
767 s = self.series[start:end]
774 s = self.series[start:end]
768 all_files = {}
775 all_files = {}
769 try:
776 try:
770 if mergeq:
777 if mergeq:
771 ret = self.mergepatch(repo, mergeq, s, wlock)
778 ret = self.mergepatch(repo, mergeq, s, wlock)
772 else:
779 else:
773 ret = self.apply(repo, s, list, wlock=wlock,
780 ret = self.apply(repo, s, list, wlock=wlock,
774 all_files=all_files)
781 all_files=all_files)
775 except:
782 except:
776 self.ui.warn(_('cleaning up working directory...'))
783 self.ui.warn(_('cleaning up working directory...'))
777 node = repo.dirstate.parents()[0]
784 node = repo.dirstate.parents()[0]
778 hg.revert(repo, node, None, wlock)
785 hg.revert(repo, node, None, wlock)
779 unknown = repo.status(wlock=wlock)[4]
786 unknown = repo.status(wlock=wlock)[4]
780 # only remove unknown files that we know we touched or
787 # only remove unknown files that we know we touched or
781 # created while patching
788 # created while patching
782 for f in unknown:
789 for f in unknown:
783 if f in all_files:
790 if f in all_files:
784 util.unlink(repo.wjoin(f))
791 util.unlink(repo.wjoin(f))
785 self.ui.warn(_('done\n'))
792 self.ui.warn(_('done\n'))
786 raise
793 raise
787 top = self.applied[-1].name
794 top = self.applied[-1].name
788 if ret[0]:
795 if ret[0]:
789 self.ui.write("Errors during apply, please fix and refresh %s\n" %
796 self.ui.write("Errors during apply, please fix and refresh %s\n" %
790 top)
797 top)
791 else:
798 else:
792 self.ui.write("Now at: %s\n" % top)
799 self.ui.write("Now at: %s\n" % top)
793 return ret[0]
800 return ret[0]
794
801
795 def pop(self, repo, patch=None, force=False, update=True, all=False,
802 def pop(self, repo, patch=None, force=False, update=True, all=False,
796 wlock=None):
803 wlock=None):
797 def getfile(f, rev):
804 def getfile(f, rev):
798 t = repo.file(f).read(rev)
805 t = repo.file(f).read(rev)
799 repo.wfile(f, "w").write(t)
806 repo.wfile(f, "w").write(t)
800
807
801 if not wlock:
808 if not wlock:
802 wlock = repo.wlock()
809 wlock = repo.wlock()
803 if patch:
810 if patch:
804 # index, rev, patch
811 # index, rev, patch
805 info = self.isapplied(patch)
812 info = self.isapplied(patch)
806 if not info:
813 if not info:
807 patch = self.lookup(patch)
814 patch = self.lookup(patch)
808 info = self.isapplied(patch)
815 info = self.isapplied(patch)
809 if not info:
816 if not info:
810 raise util.Abort(_("patch %s is not applied") % patch)
817 raise util.Abort(_("patch %s is not applied") % patch)
811
818
812 if len(self.applied) == 0:
819 if len(self.applied) == 0:
813 # Allow qpop -a to work repeatedly,
820 # Allow qpop -a to work repeatedly,
814 # but not qpop without an argument
821 # but not qpop without an argument
815 self.ui.warn(_("no patches applied\n"))
822 self.ui.warn(_("no patches applied\n"))
816 return not all
823 return not all
817
824
818 if not update:
825 if not update:
819 parents = repo.dirstate.parents()
826 parents = repo.dirstate.parents()
820 rr = [ revlog.bin(x.rev) for x in self.applied ]
827 rr = [ revlog.bin(x.rev) for x in self.applied ]
821 for p in parents:
828 for p in parents:
822 if p in rr:
829 if p in rr:
823 self.ui.warn("qpop: forcing dirstate update\n")
830 self.ui.warn("qpop: forcing dirstate update\n")
824 update = True
831 update = True
825
832
826 if not force and update:
833 if not force and update:
827 self.check_localchanges(repo)
834 self.check_localchanges(repo)
828
835
829 self.applied_dirty = 1;
836 self.applied_dirty = 1;
830 end = len(self.applied)
837 end = len(self.applied)
831 if not patch:
838 if not patch:
832 if all:
839 if all:
833 popi = 0
840 popi = 0
834 else:
841 else:
835 popi = len(self.applied) - 1
842 popi = len(self.applied) - 1
836 else:
843 else:
837 popi = info[0] + 1
844 popi = info[0] + 1
838 if popi >= end:
845 if popi >= end:
839 self.ui.warn("qpop: %s is already at the top\n" % patch)
846 self.ui.warn("qpop: %s is already at the top\n" % patch)
840 return
847 return
841 info = [ popi ] + [self.applied[popi].rev, self.applied[popi].name]
848 info = [ popi ] + [self.applied[popi].rev, self.applied[popi].name]
842
849
843 start = info[0]
850 start = info[0]
844 rev = revlog.bin(info[1])
851 rev = revlog.bin(info[1])
845
852
846 # we know there are no local changes, so we can make a simplified
853 # we know there are no local changes, so we can make a simplified
847 # form of hg.update.
854 # form of hg.update.
848 if update:
855 if update:
849 top = self.check_toppatch(repo)
856 top = self.check_toppatch(repo)
850 qp = self.qparents(repo, rev)
857 qp = self.qparents(repo, rev)
851 changes = repo.changelog.read(qp)
858 changes = repo.changelog.read(qp)
852 mmap = repo.manifest.read(changes[0])
859 mmap = repo.manifest.read(changes[0])
853 m, a, r, d, u = repo.status(qp, top)[:5]
860 m, a, r, d, u = repo.status(qp, top)[:5]
854 if d:
861 if d:
855 raise util.Abort("deletions found between repo revs")
862 raise util.Abort("deletions found between repo revs")
856 for f in m:
863 for f in m:
857 getfile(f, mmap[f])
864 getfile(f, mmap[f])
858 for f in r:
865 for f in r:
859 getfile(f, mmap[f])
866 getfile(f, mmap[f])
860 util.set_exec(repo.wjoin(f), mmap.execf(f))
867 util.set_exec(repo.wjoin(f), mmap.execf(f))
861 repo.dirstate.update(m + r, 'n')
868 repo.dirstate.update(m + r, 'n')
862 for f in a:
869 for f in a:
863 try:
870 try:
864 os.unlink(repo.wjoin(f))
871 os.unlink(repo.wjoin(f))
865 except OSError, e:
872 except OSError, e:
866 if e.errno != errno.ENOENT:
873 if e.errno != errno.ENOENT:
867 raise
874 raise
868 try: os.removedirs(os.path.dirname(repo.wjoin(f)))
875 try: os.removedirs(os.path.dirname(repo.wjoin(f)))
869 except: pass
876 except: pass
870 if a:
877 if a:
871 repo.dirstate.forget(a)
878 repo.dirstate.forget(a)
872 repo.dirstate.setparents(qp, revlog.nullid)
879 repo.dirstate.setparents(qp, revlog.nullid)
873 self.strip(repo, rev, update=False, backup='strip', wlock=wlock)
880 self.strip(repo, rev, update=False, backup='strip', wlock=wlock)
874 del self.applied[start:end]
881 del self.applied[start:end]
875 if len(self.applied):
882 if len(self.applied):
876 self.ui.write("Now at: %s\n" % self.applied[-1].name)
883 self.ui.write("Now at: %s\n" % self.applied[-1].name)
877 else:
884 else:
878 self.ui.write("Patch queue now empty\n")
885 self.ui.write("Patch queue now empty\n")
879
886
880 def diff(self, repo, pats, opts):
887 def diff(self, repo, pats, opts):
881 top = self.check_toppatch(repo)
888 top = self.check_toppatch(repo)
882 if not top:
889 if not top:
883 self.ui.write("No patches applied\n")
890 self.ui.write("No patches applied\n")
884 return
891 return
885 qp = self.qparents(repo, top)
892 qp = self.qparents(repo, top)
886 if opts.get('git'):
893 if opts.get('git'):
887 self.diffopts().git = True
894 self.diffopts().git = True
888 self.printdiff(repo, qp, files=pats, opts=opts)
895 self.printdiff(repo, qp, files=pats, opts=opts)
889
896
890 def refresh(self, repo, pats=None, **opts):
897 def refresh(self, repo, pats=None, **opts):
891 if len(self.applied) == 0:
898 if len(self.applied) == 0:
892 self.ui.write("No patches applied\n")
899 self.ui.write("No patches applied\n")
893 return 1
900 return 1
894 wlock = repo.wlock()
901 wlock = repo.wlock()
895 self.check_toppatch(repo)
902 self.check_toppatch(repo)
896 (top, patchfn) = (self.applied[-1].rev, self.applied[-1].name)
903 (top, patchfn) = (self.applied[-1].rev, self.applied[-1].name)
897 top = revlog.bin(top)
904 top = revlog.bin(top)
898 cparents = repo.changelog.parents(top)
905 cparents = repo.changelog.parents(top)
899 patchparent = self.qparents(repo, top)
906 patchparent = self.qparents(repo, top)
900 message, comments, user, date, patchfound = self.readheaders(patchfn)
907 message, comments, user, date, patchfound = self.readheaders(patchfn)
901
908
902 patchf = self.opener(patchfn, "w")
909 patchf = self.opener(patchfn, "w")
903 msg = opts.get('msg', '').rstrip()
910 msg = opts.get('msg', '').rstrip()
904 if msg:
911 if msg:
905 if comments:
912 if comments:
906 # Remove existing message.
913 # Remove existing message.
907 ci = 0
914 ci = 0
908 subj = None
915 subj = None
909 for mi in xrange(len(message)):
916 for mi in xrange(len(message)):
910 if comments[ci].lower().startswith('subject: '):
917 if comments[ci].lower().startswith('subject: '):
911 subj = comments[ci][9:]
918 subj = comments[ci][9:]
912 while message[mi] != comments[ci] and message[mi] != subj:
919 while message[mi] != comments[ci] and message[mi] != subj:
913 ci += 1
920 ci += 1
914 del comments[ci]
921 del comments[ci]
915 comments.append(msg)
922 comments.append(msg)
916 if comments:
923 if comments:
917 comments = "\n".join(comments) + '\n\n'
924 comments = "\n".join(comments) + '\n\n'
918 patchf.write(comments)
925 patchf.write(comments)
919
926
920 if opts.get('git'):
927 if opts.get('git'):
921 self.diffopts().git = True
928 self.diffopts().git = True
922 fns, matchfn, anypats = cmdutil.matchpats(repo, pats, opts)
929 fns, matchfn, anypats = cmdutil.matchpats(repo, pats, opts)
923 tip = repo.changelog.tip()
930 tip = repo.changelog.tip()
924 if top == tip:
931 if top == tip:
925 # if the top of our patch queue is also the tip, there is an
932 # if the top of our patch queue is also the tip, there is an
926 # optimization here. We update the dirstate in place and strip
933 # optimization here. We update the dirstate in place and strip
927 # off the tip commit. Then just commit the current directory
934 # off the tip commit. Then just commit the current directory
928 # tree. We can also send repo.commit the list of files
935 # tree. We can also send repo.commit the list of files
929 # changed to speed up the diff
936 # changed to speed up the diff
930 #
937 #
931 # in short mode, we only diff the files included in the
938 # in short mode, we only diff the files included in the
932 # patch already
939 # patch already
933 #
940 #
934 # this should really read:
941 # this should really read:
935 # mm, dd, aa, aa2, uu = repo.status(tip, patchparent)[:5]
942 # mm, dd, aa, aa2, uu = repo.status(tip, patchparent)[:5]
936 # but we do it backwards to take advantage of manifest/chlog
943 # but we do it backwards to take advantage of manifest/chlog
937 # caching against the next repo.status call
944 # caching against the next repo.status call
938 #
945 #
939 mm, aa, dd, aa2, uu = repo.status(patchparent, tip)[:5]
946 mm, aa, dd, aa2, uu = repo.status(patchparent, tip)[:5]
940 changes = repo.changelog.read(tip)
947 changes = repo.changelog.read(tip)
941 man = repo.manifest.read(changes[0])
948 man = repo.manifest.read(changes[0])
942 aaa = aa[:]
949 aaa = aa[:]
943 if opts.get('short'):
950 if opts.get('short'):
944 filelist = mm + aa + dd
951 filelist = mm + aa + dd
945 match = dict.fromkeys(filelist).__contains__
952 match = dict.fromkeys(filelist).__contains__
946 else:
953 else:
947 filelist = None
954 filelist = None
948 match = util.always
955 match = util.always
949 m, a, r, d, u = repo.status(files=filelist, match=match)[:5]
956 m, a, r, d, u = repo.status(files=filelist, match=match)[:5]
950
957
951 # we might end up with files that were added between tip and
958 # we might end up with files that were added between tip and
952 # the dirstate parent, but then changed in the local dirstate.
959 # the dirstate parent, but then changed in the local dirstate.
953 # in this case, we want them to only show up in the added section
960 # in this case, we want them to only show up in the added section
954 for x in m:
961 for x in m:
955 if x not in aa:
962 if x not in aa:
956 mm.append(x)
963 mm.append(x)
957 # we might end up with files added by the local dirstate that
964 # we might end up with files added by the local dirstate that
958 # were deleted by the patch. In this case, they should only
965 # were deleted by the patch. In this case, they should only
959 # show up in the changed section.
966 # show up in the changed section.
960 for x in a:
967 for x in a:
961 if x in dd:
968 if x in dd:
962 del dd[dd.index(x)]
969 del dd[dd.index(x)]
963 mm.append(x)
970 mm.append(x)
964 else:
971 else:
965 aa.append(x)
972 aa.append(x)
966 # make sure any files deleted in the local dirstate
973 # make sure any files deleted in the local dirstate
967 # are not in the add or change column of the patch
974 # are not in the add or change column of the patch
968 forget = []
975 forget = []
969 for x in d + r:
976 for x in d + r:
970 if x in aa:
977 if x in aa:
971 del aa[aa.index(x)]
978 del aa[aa.index(x)]
972 forget.append(x)
979 forget.append(x)
973 continue
980 continue
974 elif x in mm:
981 elif x in mm:
975 del mm[mm.index(x)]
982 del mm[mm.index(x)]
976 dd.append(x)
983 dd.append(x)
977
984
978 m = util.unique(mm)
985 m = util.unique(mm)
979 r = util.unique(dd)
986 r = util.unique(dd)
980 a = util.unique(aa)
987 a = util.unique(aa)
981 c = [filter(matchfn, l) for l in (m, a, r, [], u)]
988 c = [filter(matchfn, l) for l in (m, a, r, [], u)]
982 filelist = util.unique(c[0] + c[1] + c[2])
989 filelist = util.unique(c[0] + c[1] + c[2])
983 patch.diff(repo, patchparent, files=filelist, match=matchfn,
990 patch.diff(repo, patchparent, files=filelist, match=matchfn,
984 fp=patchf, changes=c, opts=self.diffopts())
991 fp=patchf, changes=c, opts=self.diffopts())
985 patchf.close()
992 patchf.close()
986
993
987 repo.dirstate.setparents(*cparents)
994 repo.dirstate.setparents(*cparents)
988 copies = {}
995 copies = {}
989 for dst in a:
996 for dst in a:
990 src = repo.dirstate.copied(dst)
997 src = repo.dirstate.copied(dst)
991 if src is None:
998 if src is None:
992 continue
999 continue
993 copies.setdefault(src, []).append(dst)
1000 copies.setdefault(src, []).append(dst)
994 repo.dirstate.update(a, 'a')
1001 repo.dirstate.update(a, 'a')
995 # remember the copies between patchparent and tip
1002 # remember the copies between patchparent and tip
996 # this may be slow, so don't do it if we're not tracking copies
1003 # this may be slow, so don't do it if we're not tracking copies
997 if self.diffopts().git:
1004 if self.diffopts().git:
998 for dst in aaa:
1005 for dst in aaa:
999 f = repo.file(dst)
1006 f = repo.file(dst)
1000 src = f.renamed(man[dst])
1007 src = f.renamed(man[dst])
1001 if src:
1008 if src:
1002 copies[src[0]] = copies.get(dst, [])
1009 copies[src[0]] = copies.get(dst, [])
1003 if dst in a:
1010 if dst in a:
1004 copies[src[0]].append(dst)
1011 copies[src[0]].append(dst)
1005 # we can't copy a file created by the patch itself
1012 # we can't copy a file created by the patch itself
1006 if dst in copies:
1013 if dst in copies:
1007 del copies[dst]
1014 del copies[dst]
1008 for src, dsts in copies.iteritems():
1015 for src, dsts in copies.iteritems():
1009 for dst in dsts:
1016 for dst in dsts:
1010 repo.dirstate.copy(src, dst)
1017 repo.dirstate.copy(src, dst)
1011 repo.dirstate.update(r, 'r')
1018 repo.dirstate.update(r, 'r')
1012 # if the patch excludes a modified file, mark that file with mtime=0
1019 # if the patch excludes a modified file, mark that file with mtime=0
1013 # so status can see it.
1020 # so status can see it.
1014 mm = []
1021 mm = []
1015 for i in xrange(len(m)-1, -1, -1):
1022 for i in xrange(len(m)-1, -1, -1):
1016 if not matchfn(m[i]):
1023 if not matchfn(m[i]):
1017 mm.append(m[i])
1024 mm.append(m[i])
1018 del m[i]
1025 del m[i]
1019 repo.dirstate.update(m, 'n')
1026 repo.dirstate.update(m, 'n')
1020 repo.dirstate.update(mm, 'n', st_mtime=-1, st_size=-1)
1027 repo.dirstate.update(mm, 'n', st_mtime=-1, st_size=-1)
1021 repo.dirstate.forget(forget)
1028 repo.dirstate.forget(forget)
1022
1029
1023 if not msg:
1030 if not msg:
1024 if not message:
1031 if not message:
1025 message = "patch queue: %s\n" % patchfn
1032 message = "patch queue: %s\n" % patchfn
1026 else:
1033 else:
1027 message = "\n".join(message)
1034 message = "\n".join(message)
1028 else:
1035 else:
1029 message = msg
1036 message = msg
1030
1037
1031 self.strip(repo, top, update=False, backup='strip', wlock=wlock)
1038 self.strip(repo, top, update=False, backup='strip', wlock=wlock)
1032 n = repo.commit(filelist, message, changes[1], match=matchfn,
1039 n = repo.commit(filelist, message, changes[1], match=matchfn,
1033 force=1, wlock=wlock)
1040 force=1, wlock=wlock)
1034 self.applied[-1] = statusentry(revlog.hex(n), patchfn)
1041 self.applied[-1] = statusentry(revlog.hex(n), patchfn)
1035 self.applied_dirty = 1
1042 self.applied_dirty = 1
1036 self.removeundo(repo)
1043 self.removeundo(repo)
1037 else:
1044 else:
1038 self.printdiff(repo, patchparent, fp=patchf)
1045 self.printdiff(repo, patchparent, fp=patchf)
1039 patchf.close()
1046 patchf.close()
1040 added = repo.status()[1]
1047 added = repo.status()[1]
1041 for a in added:
1048 for a in added:
1042 f = repo.wjoin(a)
1049 f = repo.wjoin(a)
1043 try:
1050 try:
1044 os.unlink(f)
1051 os.unlink(f)
1045 except OSError, e:
1052 except OSError, e:
1046 if e.errno != errno.ENOENT:
1053 if e.errno != errno.ENOENT:
1047 raise
1054 raise
1048 try: os.removedirs(os.path.dirname(f))
1055 try: os.removedirs(os.path.dirname(f))
1049 except: pass
1056 except: pass
1050 # forget the file copies in the dirstate
1057 # forget the file copies in the dirstate
1051 # push should readd the files later on
1058 # push should readd the files later on
1052 repo.dirstate.forget(added)
1059 repo.dirstate.forget(added)
1053 self.pop(repo, force=True, wlock=wlock)
1060 self.pop(repo, force=True, wlock=wlock)
1054 self.push(repo, force=True, wlock=wlock)
1061 self.push(repo, force=True, wlock=wlock)
1055
1062
1056 def init(self, repo, create=False):
1063 def init(self, repo, create=False):
1057 if not create and os.path.isdir(self.path):
1064 if not create and os.path.isdir(self.path):
1058 raise util.Abort(_("patch queue directory already exists"))
1065 raise util.Abort(_("patch queue directory already exists"))
1059 try:
1066 try:
1060 os.mkdir(self.path)
1067 os.mkdir(self.path)
1061 except OSError, inst:
1068 except OSError, inst:
1062 if inst.errno != errno.EEXIST or not create:
1069 if inst.errno != errno.EEXIST or not create:
1063 raise
1070 raise
1064 if create:
1071 if create:
1065 return self.qrepo(create=True)
1072 return self.qrepo(create=True)
1066
1073
1067 def unapplied(self, repo, patch=None):
1074 def unapplied(self, repo, patch=None):
1068 if patch and patch not in self.series:
1075 if patch and patch not in self.series:
1069 raise util.Abort(_("patch %s is not in series file") % patch)
1076 raise util.Abort(_("patch %s is not in series file") % patch)
1070 if not patch:
1077 if not patch:
1071 start = self.series_end()
1078 start = self.series_end()
1072 else:
1079 else:
1073 start = self.series.index(patch) + 1
1080 start = self.series.index(patch) + 1
1074 unapplied = []
1081 unapplied = []
1075 for i in xrange(start, len(self.series)):
1082 for i in xrange(start, len(self.series)):
1076 pushable, reason = self.pushable(i)
1083 pushable, reason = self.pushable(i)
1077 if pushable:
1084 if pushable:
1078 unapplied.append((i, self.series[i]))
1085 unapplied.append((i, self.series[i]))
1079 self.explain_pushable(i)
1086 self.explain_pushable(i)
1080 return unapplied
1087 return unapplied
1081
1088
1082 def qseries(self, repo, missing=None, start=0, length=None, status=None,
1089 def qseries(self, repo, missing=None, start=0, length=None, status=None,
1083 summary=False):
1090 summary=False):
1084 def displayname(patchname):
1091 def displayname(patchname):
1085 if summary:
1092 if summary:
1086 msg = self.readheaders(patchname)[0]
1093 msg = self.readheaders(patchname)[0]
1087 msg = msg and ': ' + msg[0] or ': '
1094 msg = msg and ': ' + msg[0] or ': '
1088 else:
1095 else:
1089 msg = ''
1096 msg = ''
1090 return '%s%s' % (patchname, msg)
1097 return '%s%s' % (patchname, msg)
1091
1098
1092 applied = dict.fromkeys([p.name for p in self.applied])
1099 applied = dict.fromkeys([p.name for p in self.applied])
1093 if length is None:
1100 if length is None:
1094 length = len(self.series) - start
1101 length = len(self.series) - start
1095 if not missing:
1102 if not missing:
1096 for i in xrange(start, start+length):
1103 for i in xrange(start, start+length):
1097 patch = self.series[i]
1104 patch = self.series[i]
1098 if patch in applied:
1105 if patch in applied:
1099 stat = 'A'
1106 stat = 'A'
1100 elif self.pushable(i)[0]:
1107 elif self.pushable(i)[0]:
1101 stat = 'U'
1108 stat = 'U'
1102 else:
1109 else:
1103 stat = 'G'
1110 stat = 'G'
1104 pfx = ''
1111 pfx = ''
1105 if self.ui.verbose:
1112 if self.ui.verbose:
1106 pfx = '%d %s ' % (i, stat)
1113 pfx = '%d %s ' % (i, stat)
1107 elif status and status != stat:
1114 elif status and status != stat:
1108 continue
1115 continue
1109 self.ui.write('%s%s\n' % (pfx, displayname(patch)))
1116 self.ui.write('%s%s\n' % (pfx, displayname(patch)))
1110 else:
1117 else:
1111 msng_list = []
1118 msng_list = []
1112 for root, dirs, files in os.walk(self.path):
1119 for root, dirs, files in os.walk(self.path):
1113 d = root[len(self.path) + 1:]
1120 d = root[len(self.path) + 1:]
1114 for f in files:
1121 for f in files:
1115 fl = os.path.join(d, f)
1122 fl = os.path.join(d, f)
1116 if (fl not in self.series and
1123 if (fl not in self.series and
1117 fl not in (self.status_path, self.series_path,
1124 fl not in (self.status_path, self.series_path,
1118 self.guards_path)
1125 self.guards_path)
1119 and not fl.startswith('.')):
1126 and not fl.startswith('.')):
1120 msng_list.append(fl)
1127 msng_list.append(fl)
1121 msng_list.sort()
1128 msng_list.sort()
1122 for x in msng_list:
1129 for x in msng_list:
1123 pfx = self.ui.verbose and ('D ') or ''
1130 pfx = self.ui.verbose and ('D ') or ''
1124 self.ui.write("%s%s\n" % (pfx, displayname(x)))
1131 self.ui.write("%s%s\n" % (pfx, displayname(x)))
1125
1132
1126 def issaveline(self, l):
1133 def issaveline(self, l):
1127 if l.name == '.hg.patches.save.line':
1134 if l.name == '.hg.patches.save.line':
1128 return True
1135 return True
1129
1136
1130 def qrepo(self, create=False):
1137 def qrepo(self, create=False):
1131 if create or os.path.isdir(self.join(".hg")):
1138 if create or os.path.isdir(self.join(".hg")):
1132 return hg.repository(self.ui, path=self.path, create=create)
1139 return hg.repository(self.ui, path=self.path, create=create)
1133
1140
1134 def restore(self, repo, rev, delete=None, qupdate=None):
1141 def restore(self, repo, rev, delete=None, qupdate=None):
1135 c = repo.changelog.read(rev)
1142 c = repo.changelog.read(rev)
1136 desc = c[4].strip()
1143 desc = c[4].strip()
1137 lines = desc.splitlines()
1144 lines = desc.splitlines()
1138 i = 0
1145 i = 0
1139 datastart = None
1146 datastart = None
1140 series = []
1147 series = []
1141 applied = []
1148 applied = []
1142 qpp = None
1149 qpp = None
1143 for i in xrange(0, len(lines)):
1150 for i in xrange(0, len(lines)):
1144 if lines[i] == 'Patch Data:':
1151 if lines[i] == 'Patch Data:':
1145 datastart = i + 1
1152 datastart = i + 1
1146 elif lines[i].startswith('Dirstate:'):
1153 elif lines[i].startswith('Dirstate:'):
1147 l = lines[i].rstrip()
1154 l = lines[i].rstrip()
1148 l = l[10:].split(' ')
1155 l = l[10:].split(' ')
1149 qpp = [ hg.bin(x) for x in l ]
1156 qpp = [ hg.bin(x) for x in l ]
1150 elif datastart != None:
1157 elif datastart != None:
1151 l = lines[i].rstrip()
1158 l = lines[i].rstrip()
1152 se = statusentry(l)
1159 se = statusentry(l)
1153 file_ = se.name
1160 file_ = se.name
1154 if se.rev:
1161 if se.rev:
1155 applied.append(se)
1162 applied.append(se)
1156 else:
1163 else:
1157 series.append(file_)
1164 series.append(file_)
1158 if datastart == None:
1165 if datastart == None:
1159 self.ui.warn("No saved patch data found\n")
1166 self.ui.warn("No saved patch data found\n")
1160 return 1
1167 return 1
1161 self.ui.warn("restoring status: %s\n" % lines[0])
1168 self.ui.warn("restoring status: %s\n" % lines[0])
1162 self.full_series = series
1169 self.full_series = series
1163 self.applied = applied
1170 self.applied = applied
1164 self.parse_series()
1171 self.parse_series()
1165 self.series_dirty = 1
1172 self.series_dirty = 1
1166 self.applied_dirty = 1
1173 self.applied_dirty = 1
1167 heads = repo.changelog.heads()
1174 heads = repo.changelog.heads()
1168 if delete:
1175 if delete:
1169 if rev not in heads:
1176 if rev not in heads:
1170 self.ui.warn("save entry has children, leaving it alone\n")
1177 self.ui.warn("save entry has children, leaving it alone\n")
1171 else:
1178 else:
1172 self.ui.warn("removing save entry %s\n" % hg.short(rev))
1179 self.ui.warn("removing save entry %s\n" % hg.short(rev))
1173 pp = repo.dirstate.parents()
1180 pp = repo.dirstate.parents()
1174 if rev in pp:
1181 if rev in pp:
1175 update = True
1182 update = True
1176 else:
1183 else:
1177 update = False
1184 update = False
1178 self.strip(repo, rev, update=update, backup='strip')
1185 self.strip(repo, rev, update=update, backup='strip')
1179 if qpp:
1186 if qpp:
1180 self.ui.warn("saved queue repository parents: %s %s\n" %
1187 self.ui.warn("saved queue repository parents: %s %s\n" %
1181 (hg.short(qpp[0]), hg.short(qpp[1])))
1188 (hg.short(qpp[0]), hg.short(qpp[1])))
1182 if qupdate:
1189 if qupdate:
1183 print "queue directory updating"
1190 print "queue directory updating"
1184 r = self.qrepo()
1191 r = self.qrepo()
1185 if not r:
1192 if not r:
1186 self.ui.warn("Unable to load queue repository\n")
1193 self.ui.warn("Unable to load queue repository\n")
1187 return 1
1194 return 1
1188 hg.clean(r, qpp[0])
1195 hg.clean(r, qpp[0])
1189
1196
1190 def save(self, repo, msg=None):
1197 def save(self, repo, msg=None):
1191 if len(self.applied) == 0:
1198 if len(self.applied) == 0:
1192 self.ui.warn("save: no patches applied, exiting\n")
1199 self.ui.warn("save: no patches applied, exiting\n")
1193 return 1
1200 return 1
1194 if self.issaveline(self.applied[-1]):
1201 if self.issaveline(self.applied[-1]):
1195 self.ui.warn("status is already saved\n")
1202 self.ui.warn("status is already saved\n")
1196 return 1
1203 return 1
1197
1204
1198 ar = [ ':' + x for x in self.full_series ]
1205 ar = [ ':' + x for x in self.full_series ]
1199 if not msg:
1206 if not msg:
1200 msg = "hg patches saved state"
1207 msg = "hg patches saved state"
1201 else:
1208 else:
1202 msg = "hg patches: " + msg.rstrip('\r\n')
1209 msg = "hg patches: " + msg.rstrip('\r\n')
1203 r = self.qrepo()
1210 r = self.qrepo()
1204 if r:
1211 if r:
1205 pp = r.dirstate.parents()
1212 pp = r.dirstate.parents()
1206 msg += "\nDirstate: %s %s" % (hg.hex(pp[0]), hg.hex(pp[1]))
1213 msg += "\nDirstate: %s %s" % (hg.hex(pp[0]), hg.hex(pp[1]))
1207 msg += "\n\nPatch Data:\n"
1214 msg += "\n\nPatch Data:\n"
1208 text = msg + "\n".join([str(x) for x in self.applied]) + '\n' + (ar and
1215 text = msg + "\n".join([str(x) for x in self.applied]) + '\n' + (ar and
1209 "\n".join(ar) + '\n' or "")
1216 "\n".join(ar) + '\n' or "")
1210 n = repo.commit(None, text, user=None, force=1)
1217 n = repo.commit(None, text, user=None, force=1)
1211 if not n:
1218 if not n:
1212 self.ui.warn("repo commit failed\n")
1219 self.ui.warn("repo commit failed\n")
1213 return 1
1220 return 1
1214 self.applied.append(statusentry(revlog.hex(n),'.hg.patches.save.line'))
1221 self.applied.append(statusentry(revlog.hex(n),'.hg.patches.save.line'))
1215 self.applied_dirty = 1
1222 self.applied_dirty = 1
1216 self.removeundo(repo)
1223 self.removeundo(repo)
1217
1224
1218 def full_series_end(self):
1225 def full_series_end(self):
1219 if len(self.applied) > 0:
1226 if len(self.applied) > 0:
1220 p = self.applied[-1].name
1227 p = self.applied[-1].name
1221 end = self.find_series(p)
1228 end = self.find_series(p)
1222 if end == None:
1229 if end == None:
1223 return len(self.full_series)
1230 return len(self.full_series)
1224 return end + 1
1231 return end + 1
1225 return 0
1232 return 0
1226
1233
1227 def series_end(self, all_patches=False):
1234 def series_end(self, all_patches=False):
1228 """If all_patches is False, return the index of the next pushable patch
1235 """If all_patches is False, return the index of the next pushable patch
1229 in the series, or the series length. If all_patches is True, return the
1236 in the series, or the series length. If all_patches is True, return the
1230 index of the first patch past the last applied one.
1237 index of the first patch past the last applied one.
1231 """
1238 """
1232 end = 0
1239 end = 0
1233 def next(start):
1240 def next(start):
1234 if all_patches:
1241 if all_patches:
1235 return start
1242 return start
1236 i = start
1243 i = start
1237 while i < len(self.series):
1244 while i < len(self.series):
1238 p, reason = self.pushable(i)
1245 p, reason = self.pushable(i)
1239 if p:
1246 if p:
1240 break
1247 break
1241 self.explain_pushable(i)
1248 self.explain_pushable(i)
1242 i += 1
1249 i += 1
1243 return i
1250 return i
1244 if len(self.applied) > 0:
1251 if len(self.applied) > 0:
1245 p = self.applied[-1].name
1252 p = self.applied[-1].name
1246 try:
1253 try:
1247 end = self.series.index(p)
1254 end = self.series.index(p)
1248 except ValueError:
1255 except ValueError:
1249 return 0
1256 return 0
1250 return next(end + 1)
1257 return next(end + 1)
1251 return next(end)
1258 return next(end)
1252
1259
1253 def appliedname(self, index):
1260 def appliedname(self, index):
1254 pname = self.applied[index].name
1261 pname = self.applied[index].name
1255 if not self.ui.verbose:
1262 if not self.ui.verbose:
1256 p = pname
1263 p = pname
1257 else:
1264 else:
1258 p = str(self.series.index(pname)) + " " + pname
1265 p = str(self.series.index(pname)) + " " + pname
1259 return p
1266 return p
1260
1267
1261 def qimport(self, repo, files, patchname=None, rev=None, existing=None,
1268 def qimport(self, repo, files, patchname=None, rev=None, existing=None,
1262 force=None, git=False):
1269 force=None, git=False):
1263 def checkseries(patchname):
1270 def checkseries(patchname):
1264 if patchname in self.series:
1271 if patchname in self.series:
1265 raise util.Abort(_('patch %s is already in the series file')
1272 raise util.Abort(_('patch %s is already in the series file')
1266 % patchname)
1273 % patchname)
1267 def checkfile(patchname):
1274 def checkfile(patchname):
1268 if not force and os.path.exists(self.join(patchname)):
1275 if not force and os.path.exists(self.join(patchname)):
1269 raise util.Abort(_('patch "%s" already exists')
1276 raise util.Abort(_('patch "%s" already exists')
1270 % patchname)
1277 % patchname)
1271
1278
1272 if rev:
1279 if rev:
1273 if files:
1280 if files:
1274 raise util.Abort(_('option "-r" not valid when importing '
1281 raise util.Abort(_('option "-r" not valid when importing '
1275 'files'))
1282 'files'))
1276 rev = cmdutil.revrange(repo, rev)
1283 rev = cmdutil.revrange(repo, rev)
1277 rev.sort(lambda x, y: cmp(y, x))
1284 rev.sort(lambda x, y: cmp(y, x))
1278 if (len(files) > 1 or len(rev) > 1) and patchname:
1285 if (len(files) > 1 or len(rev) > 1) and patchname:
1279 raise util.Abort(_('option "-n" not valid when importing multiple '
1286 raise util.Abort(_('option "-n" not valid when importing multiple '
1280 'patches'))
1287 'patches'))
1281 i = 0
1288 i = 0
1282 added = []
1289 added = []
1283 if rev:
1290 if rev:
1284 # If mq patches are applied, we can only import revisions
1291 # If mq patches are applied, we can only import revisions
1285 # that form a linear path to qbase.
1292 # that form a linear path to qbase.
1286 # Otherwise, they should form a linear path to a head.
1293 # Otherwise, they should form a linear path to a head.
1287 heads = repo.changelog.heads(repo.changelog.node(rev[-1]))
1294 heads = repo.changelog.heads(repo.changelog.node(rev[-1]))
1288 if len(heads) > 1:
1295 if len(heads) > 1:
1289 raise util.Abort(_('revision %d is the root of more than one '
1296 raise util.Abort(_('revision %d is the root of more than one '
1290 'branch') % rev[-1])
1297 'branch') % rev[-1])
1291 if self.applied:
1298 if self.applied:
1292 base = revlog.hex(repo.changelog.node(rev[0]))
1299 base = revlog.hex(repo.changelog.node(rev[0]))
1293 if base in [n.rev for n in self.applied]:
1300 if base in [n.rev for n in self.applied]:
1294 raise util.Abort(_('revision %d is already managed')
1301 raise util.Abort(_('revision %d is already managed')
1295 % rev[0])
1302 % rev[0])
1296 if heads != [revlog.bin(self.applied[-1].rev)]:
1303 if heads != [revlog.bin(self.applied[-1].rev)]:
1297 raise util.Abort(_('revision %d is not the parent of '
1304 raise util.Abort(_('revision %d is not the parent of '
1298 'the queue') % rev[0])
1305 'the queue') % rev[0])
1299 base = repo.changelog.rev(revlog.bin(self.applied[0].rev))
1306 base = repo.changelog.rev(revlog.bin(self.applied[0].rev))
1300 lastparent = repo.changelog.parentrevs(base)[0]
1307 lastparent = repo.changelog.parentrevs(base)[0]
1301 else:
1308 else:
1302 if heads != [repo.changelog.node(rev[0])]:
1309 if heads != [repo.changelog.node(rev[0])]:
1303 raise util.Abort(_('revision %d has unmanaged children')
1310 raise util.Abort(_('revision %d has unmanaged children')
1304 % rev[0])
1311 % rev[0])
1305 lastparent = None
1312 lastparent = None
1306
1313
1307 if git:
1314 if git:
1308 self.diffopts().git = True
1315 self.diffopts().git = True
1309
1316
1310 for r in rev:
1317 for r in rev:
1311 p1, p2 = repo.changelog.parentrevs(r)
1318 p1, p2 = repo.changelog.parentrevs(r)
1312 n = repo.changelog.node(r)
1319 n = repo.changelog.node(r)
1313 if p2 != revlog.nullrev:
1320 if p2 != revlog.nullrev:
1314 raise util.Abort(_('cannot import merge revision %d') % r)
1321 raise util.Abort(_('cannot import merge revision %d') % r)
1315 if lastparent and lastparent != r:
1322 if lastparent and lastparent != r:
1316 raise util.Abort(_('revision %d is not the parent of %d')
1323 raise util.Abort(_('revision %d is not the parent of %d')
1317 % (r, lastparent))
1324 % (r, lastparent))
1318 lastparent = p1
1325 lastparent = p1
1319
1326
1320 if not patchname:
1327 if not patchname:
1321 patchname = normname('%d.diff' % r)
1328 patchname = normname('%d.diff' % r)
1322 checkseries(patchname)
1329 checkseries(patchname)
1323 checkfile(patchname)
1330 checkfile(patchname)
1324 self.full_series.insert(0, patchname)
1331 self.full_series.insert(0, patchname)
1325
1332
1326 patchf = self.opener(patchname, "w")
1333 patchf = self.opener(patchname, "w")
1327 patch.export(repo, [n], fp=patchf, opts=self.diffopts())
1334 patch.export(repo, [n], fp=patchf, opts=self.diffopts())
1328 patchf.close()
1335 patchf.close()
1329
1336
1330 se = statusentry(revlog.hex(n), patchname)
1337 se = statusentry(revlog.hex(n), patchname)
1331 self.applied.insert(0, se)
1338 self.applied.insert(0, se)
1332
1339
1333 added.append(patchname)
1340 added.append(patchname)
1334 patchname = None
1341 patchname = None
1335 self.parse_series()
1342 self.parse_series()
1336 self.applied_dirty = 1
1343 self.applied_dirty = 1
1337
1344
1338 for filename in files:
1345 for filename in files:
1339 if existing:
1346 if existing:
1340 if filename == '-':
1347 if filename == '-':
1341 raise util.Abort(_('-e is incompatible with import from -'))
1348 raise util.Abort(_('-e is incompatible with import from -'))
1342 if not patchname:
1349 if not patchname:
1343 patchname = normname(filename)
1350 patchname = normname(filename)
1344 if not os.path.isfile(self.join(patchname)):
1351 if not os.path.isfile(self.join(patchname)):
1345 raise util.Abort(_("patch %s does not exist") % patchname)
1352 raise util.Abort(_("patch %s does not exist") % patchname)
1346 else:
1353 else:
1347 try:
1354 try:
1348 if filename == '-':
1355 if filename == '-':
1349 if not patchname:
1356 if not patchname:
1350 raise util.Abort(_('need --name to import a patch from -'))
1357 raise util.Abort(_('need --name to import a patch from -'))
1351 text = sys.stdin.read()
1358 text = sys.stdin.read()
1352 else:
1359 else:
1353 text = file(filename).read()
1360 text = file(filename).read()
1354 except IOError:
1361 except IOError:
1355 raise util.Abort(_("unable to read %s") % patchname)
1362 raise util.Abort(_("unable to read %s") % patchname)
1356 if not patchname:
1363 if not patchname:
1357 patchname = normname(os.path.basename(filename))
1364 patchname = normname(os.path.basename(filename))
1358 checkfile(patchname)
1365 checkfile(patchname)
1359 patchf = self.opener(patchname, "w")
1366 patchf = self.opener(patchname, "w")
1360 patchf.write(text)
1367 patchf.write(text)
1361 checkseries(patchname)
1368 checkseries(patchname)
1362 index = self.full_series_end() + i
1369 index = self.full_series_end() + i
1363 self.full_series[index:index] = [patchname]
1370 self.full_series[index:index] = [patchname]
1364 self.parse_series()
1371 self.parse_series()
1365 self.ui.warn("adding %s to series file\n" % patchname)
1372 self.ui.warn("adding %s to series file\n" % patchname)
1366 i += 1
1373 i += 1
1367 added.append(patchname)
1374 added.append(patchname)
1368 patchname = None
1375 patchname = None
1369 self.series_dirty = 1
1376 self.series_dirty = 1
1370 qrepo = self.qrepo()
1377 qrepo = self.qrepo()
1371 if qrepo:
1378 if qrepo:
1372 qrepo.add(added)
1379 qrepo.add(added)
1373
1380
1374 def delete(ui, repo, *patches, **opts):
1381 def delete(ui, repo, *patches, **opts):
1375 """remove patches from queue
1382 """remove patches from queue
1376
1383
1377 With --rev, mq will stop managing the named revisions. The
1384 With --rev, mq will stop managing the named revisions. The
1378 patches must be applied and at the base of the stack. This option
1385 patches must be applied and at the base of the stack. This option
1379 is useful when the patches have been applied upstream.
1386 is useful when the patches have been applied upstream.
1380
1387
1381 Otherwise, the patches must not be applied.
1388 Otherwise, the patches must not be applied.
1382
1389
1383 With --keep, the patch files are preserved in the patch directory."""
1390 With --keep, the patch files are preserved in the patch directory."""
1384 q = repo.mq
1391 q = repo.mq
1385 q.delete(repo, patches, opts)
1392 q.delete(repo, patches, opts)
1386 q.save_dirty()
1393 q.save_dirty()
1387 return 0
1394 return 0
1388
1395
1389 def applied(ui, repo, patch=None, **opts):
1396 def applied(ui, repo, patch=None, **opts):
1390 """print the patches already applied"""
1397 """print the patches already applied"""
1391 q = repo.mq
1398 q = repo.mq
1392 if patch:
1399 if patch:
1393 if patch not in q.series:
1400 if patch not in q.series:
1394 raise util.Abort(_("patch %s is not in series file") % patch)
1401 raise util.Abort(_("patch %s is not in series file") % patch)
1395 end = q.series.index(patch) + 1
1402 end = q.series.index(patch) + 1
1396 else:
1403 else:
1397 end = q.series_end(True)
1404 end = q.series_end(True)
1398 return q.qseries(repo, length=end, status='A', summary=opts.get('summary'))
1405 return q.qseries(repo, length=end, status='A', summary=opts.get('summary'))
1399
1406
1400 def unapplied(ui, repo, patch=None, **opts):
1407 def unapplied(ui, repo, patch=None, **opts):
1401 """print the patches not yet applied"""
1408 """print the patches not yet applied"""
1402 q = repo.mq
1409 q = repo.mq
1403 if patch:
1410 if patch:
1404 if patch not in q.series:
1411 if patch not in q.series:
1405 raise util.Abort(_("patch %s is not in series file") % patch)
1412 raise util.Abort(_("patch %s is not in series file") % patch)
1406 start = q.series.index(patch) + 1
1413 start = q.series.index(patch) + 1
1407 else:
1414 else:
1408 start = q.series_end(True)
1415 start = q.series_end(True)
1409 q.qseries(repo, start=start, status='U', summary=opts.get('summary'))
1416 q.qseries(repo, start=start, status='U', summary=opts.get('summary'))
1410
1417
1411 def qimport(ui, repo, *filename, **opts):
1418 def qimport(ui, repo, *filename, **opts):
1412 """import a patch
1419 """import a patch
1413
1420
1414 The patch will have the same name as its source file unless you
1421 The patch will have the same name as its source file unless you
1415 give it a new one with --name.
1422 give it a new one with --name.
1416
1423
1417 You can register an existing patch inside the patch directory
1424 You can register an existing patch inside the patch directory
1418 with the --existing flag.
1425 with the --existing flag.
1419
1426
1420 With --force, an existing patch of the same name will be overwritten.
1427 With --force, an existing patch of the same name will be overwritten.
1421
1428
1422 An existing changeset may be placed under mq control with --rev
1429 An existing changeset may be placed under mq control with --rev
1423 (e.g. qimport --rev tip -n patch will place tip under mq control).
1430 (e.g. qimport --rev tip -n patch will place tip under mq control).
1424 With --git, patches imported with --rev will use the git diff
1431 With --git, patches imported with --rev will use the git diff
1425 format.
1432 format.
1426 """
1433 """
1427 q = repo.mq
1434 q = repo.mq
1428 q.qimport(repo, filename, patchname=opts['name'],
1435 q.qimport(repo, filename, patchname=opts['name'],
1429 existing=opts['existing'], force=opts['force'], rev=opts['rev'],
1436 existing=opts['existing'], force=opts['force'], rev=opts['rev'],
1430 git=opts['git'])
1437 git=opts['git'])
1431 q.save_dirty()
1438 q.save_dirty()
1432 return 0
1439 return 0
1433
1440
1434 def init(ui, repo, **opts):
1441 def init(ui, repo, **opts):
1435 """init a new queue repository
1442 """init a new queue repository
1436
1443
1437 The queue repository is unversioned by default. If -c is
1444 The queue repository is unversioned by default. If -c is
1438 specified, qinit will create a separate nested repository
1445 specified, qinit will create a separate nested repository
1439 for patches (qinit -c may also be run later to convert
1446 for patches (qinit -c may also be run later to convert
1440 an unversioned patch repository into a versioned one).
1447 an unversioned patch repository into a versioned one).
1441 You can use qcommit to commit changes to this queue repository."""
1448 You can use qcommit to commit changes to this queue repository."""
1442 q = repo.mq
1449 q = repo.mq
1443 r = q.init(repo, create=opts['create_repo'])
1450 r = q.init(repo, create=opts['create_repo'])
1444 q.save_dirty()
1451 q.save_dirty()
1445 if r:
1452 if r:
1446 if not os.path.exists(r.wjoin('.hgignore')):
1453 if not os.path.exists(r.wjoin('.hgignore')):
1447 fp = r.wopener('.hgignore', 'w')
1454 fp = r.wopener('.hgignore', 'w')
1448 fp.write('syntax: glob\n')
1455 fp.write('syntax: glob\n')
1449 fp.write('status\n')
1456 fp.write('status\n')
1450 fp.write('guards\n')
1457 fp.write('guards\n')
1451 fp.close()
1458 fp.close()
1452 if not os.path.exists(r.wjoin('series')):
1459 if not os.path.exists(r.wjoin('series')):
1453 r.wopener('series', 'w').close()
1460 r.wopener('series', 'w').close()
1454 r.add(['.hgignore', 'series'])
1461 r.add(['.hgignore', 'series'])
1455 commands.add(ui, r)
1462 commands.add(ui, r)
1456 return 0
1463 return 0
1457
1464
1458 def clone(ui, source, dest=None, **opts):
1465 def clone(ui, source, dest=None, **opts):
1459 '''clone main and patch repository at same time
1466 '''clone main and patch repository at same time
1460
1467
1461 If source is local, destination will have no patches applied. If
1468 If source is local, destination will have no patches applied. If
1462 source is remote, this command can not check if patches are
1469 source is remote, this command can not check if patches are
1463 applied in source, so cannot guarantee that patches are not
1470 applied in source, so cannot guarantee that patches are not
1464 applied in destination. If you clone remote repository, be sure
1471 applied in destination. If you clone remote repository, be sure
1465 before that it has no patches applied.
1472 before that it has no patches applied.
1466
1473
1467 Source patch repository is looked for in <src>/.hg/patches by
1474 Source patch repository is looked for in <src>/.hg/patches by
1468 default. Use -p <url> to change.
1475 default. Use -p <url> to change.
1469 '''
1476 '''
1470 cmdutil.setremoteconfig(ui, opts)
1477 cmdutil.setremoteconfig(ui, opts)
1471 if dest is None:
1478 if dest is None:
1472 dest = hg.defaultdest(source)
1479 dest = hg.defaultdest(source)
1473 sr = hg.repository(ui, ui.expandpath(source))
1480 sr = hg.repository(ui, ui.expandpath(source))
1474 qbase, destrev = None, None
1481 qbase, destrev = None, None
1475 if sr.local():
1482 if sr.local():
1476 if sr.mq.applied:
1483 if sr.mq.applied:
1477 qbase = revlog.bin(sr.mq.applied[0].rev)
1484 qbase = revlog.bin(sr.mq.applied[0].rev)
1478 if not hg.islocal(dest):
1485 if not hg.islocal(dest):
1479 heads = dict.fromkeys(sr.heads())
1486 heads = dict.fromkeys(sr.heads())
1480 for h in sr.heads(qbase):
1487 for h in sr.heads(qbase):
1481 del heads[h]
1488 del heads[h]
1482 destrev = heads.keys()
1489 destrev = heads.keys()
1483 destrev.append(sr.changelog.parents(qbase)[0])
1490 destrev.append(sr.changelog.parents(qbase)[0])
1484 ui.note(_('cloning main repo\n'))
1491 ui.note(_('cloning main repo\n'))
1485 sr, dr = hg.clone(ui, sr.url(), dest,
1492 sr, dr = hg.clone(ui, sr.url(), dest,
1486 pull=opts['pull'],
1493 pull=opts['pull'],
1487 rev=destrev,
1494 rev=destrev,
1488 update=False,
1495 update=False,
1489 stream=opts['uncompressed'])
1496 stream=opts['uncompressed'])
1490 ui.note(_('cloning patch repo\n'))
1497 ui.note(_('cloning patch repo\n'))
1491 spr, dpr = hg.clone(ui, opts['patches'] or (sr.url() + '/.hg/patches'),
1498 spr, dpr = hg.clone(ui, opts['patches'] or (sr.url() + '/.hg/patches'),
1492 dr.url() + '/.hg/patches',
1499 dr.url() + '/.hg/patches',
1493 pull=opts['pull'],
1500 pull=opts['pull'],
1494 update=not opts['noupdate'],
1501 update=not opts['noupdate'],
1495 stream=opts['uncompressed'])
1502 stream=opts['uncompressed'])
1496 if dr.local():
1503 if dr.local():
1497 if qbase:
1504 if qbase:
1498 ui.note(_('stripping applied patches from destination repo\n'))
1505 ui.note(_('stripping applied patches from destination repo\n'))
1499 dr.mq.strip(dr, qbase, update=False, backup=None)
1506 dr.mq.strip(dr, qbase, update=False, backup=None)
1500 if not opts['noupdate']:
1507 if not opts['noupdate']:
1501 ui.note(_('updating destination repo\n'))
1508 ui.note(_('updating destination repo\n'))
1502 hg.update(dr, dr.changelog.tip())
1509 hg.update(dr, dr.changelog.tip())
1503
1510
1504 def commit(ui, repo, *pats, **opts):
1511 def commit(ui, repo, *pats, **opts):
1505 """commit changes in the queue repository"""
1512 """commit changes in the queue repository"""
1506 q = repo.mq
1513 q = repo.mq
1507 r = q.qrepo()
1514 r = q.qrepo()
1508 if not r: raise util.Abort('no queue repository')
1515 if not r: raise util.Abort('no queue repository')
1509 commands.commit(r.ui, r, *pats, **opts)
1516 commands.commit(r.ui, r, *pats, **opts)
1510
1517
1511 def series(ui, repo, **opts):
1518 def series(ui, repo, **opts):
1512 """print the entire series file"""
1519 """print the entire series file"""
1513 repo.mq.qseries(repo, missing=opts['missing'], summary=opts['summary'])
1520 repo.mq.qseries(repo, missing=opts['missing'], summary=opts['summary'])
1514 return 0
1521 return 0
1515
1522
1516 def top(ui, repo, **opts):
1523 def top(ui, repo, **opts):
1517 """print the name of the current patch"""
1524 """print the name of the current patch"""
1518 q = repo.mq
1525 q = repo.mq
1519 t = q.applied and q.series_end(True) or 0
1526 t = q.applied and q.series_end(True) or 0
1520 if t:
1527 if t:
1521 return q.qseries(repo, start=t-1, length=1, status='A',
1528 return q.qseries(repo, start=t-1, length=1, status='A',
1522 summary=opts.get('summary'))
1529 summary=opts.get('summary'))
1523 else:
1530 else:
1524 ui.write("No patches applied\n")
1531 ui.write("No patches applied\n")
1525 return 1
1532 return 1
1526
1533
1527 def next(ui, repo, **opts):
1534 def next(ui, repo, **opts):
1528 """print the name of the next patch"""
1535 """print the name of the next patch"""
1529 q = repo.mq
1536 q = repo.mq
1530 end = q.series_end()
1537 end = q.series_end()
1531 if end == len(q.series):
1538 if end == len(q.series):
1532 ui.write("All patches applied\n")
1539 ui.write("All patches applied\n")
1533 return 1
1540 return 1
1534 return q.qseries(repo, start=end, length=1, summary=opts.get('summary'))
1541 return q.qseries(repo, start=end, length=1, summary=opts.get('summary'))
1535
1542
1536 def prev(ui, repo, **opts):
1543 def prev(ui, repo, **opts):
1537 """print the name of the previous patch"""
1544 """print the name of the previous patch"""
1538 q = repo.mq
1545 q = repo.mq
1539 l = len(q.applied)
1546 l = len(q.applied)
1540 if l == 1:
1547 if l == 1:
1541 ui.write("Only one patch applied\n")
1548 ui.write("Only one patch applied\n")
1542 return 1
1549 return 1
1543 if not l:
1550 if not l:
1544 ui.write("No patches applied\n")
1551 ui.write("No patches applied\n")
1545 return 1
1552 return 1
1546 return q.qseries(repo, start=l-2, length=1, status='A',
1553 return q.qseries(repo, start=l-2, length=1, status='A',
1547 summary=opts.get('summary'))
1554 summary=opts.get('summary'))
1548
1555
1549 def new(ui, repo, patch, **opts):
1556 def new(ui, repo, patch, *args, **opts):
1550 """create a new patch
1557 """create a new patch
1551
1558
1552 qnew creates a new patch on top of the currently-applied patch
1559 qnew creates a new patch on top of the currently-applied patch
1553 (if any). It will refuse to run if there are any outstanding
1560 (if any). It will refuse to run if there are any outstanding
1554 changes unless -f is specified, in which case the patch will
1561 changes unless -f is specified, in which case the patch will
1555 be initialised with them.
1562 be initialised with them. You may also use -I, -X, and/or a list of
1563 files after the patch name to add only changes to matching files
1564 to the new patch, leaving the rest as uncommitted modifications.
1556
1565
1557 -e, -m or -l set the patch header as well as the commit message.
1566 -e, -m or -l set the patch header as well as the commit message.
1558 If none is specified, the patch header is empty and the
1567 If none is specified, the patch header is empty and the
1559 commit message is 'New patch: PATCH'"""
1568 commit message is 'New patch: PATCH'"""
1560 q = repo.mq
1569 q = repo.mq
1561 message = cmdutil.logmessage(opts)
1570 message = cmdutil.logmessage(opts)
1562 if opts['edit']:
1571 if opts['edit']:
1563 message = ui.edit(message, ui.username())
1572 message = ui.edit(message, ui.username())
1564 q.new(repo, patch, msg=message, force=opts['force'])
1573 opts['msg'] = message
1574 q.new(repo, patch, *args, **opts)
1565 q.save_dirty()
1575 q.save_dirty()
1566 return 0
1576 return 0
1567
1577
1568 def refresh(ui, repo, *pats, **opts):
1578 def refresh(ui, repo, *pats, **opts):
1569 """update the current patch
1579 """update the current patch
1570
1580
1571 If any file patterns are provided, the refreshed patch will contain only
1581 If any file patterns are provided, the refreshed patch will contain only
1572 the modifications that match those patterns; the remaining modifications
1582 the modifications that match those patterns; the remaining modifications
1573 will remain in the working directory.
1583 will remain in the working directory.
1574
1584
1575 hg add/remove/copy/rename work as usual, though you might want to use
1585 hg add/remove/copy/rename work as usual, though you might want to use
1576 git-style patches (--git or [diff] git=1) to track copies and renames.
1586 git-style patches (--git or [diff] git=1) to track copies and renames.
1577 """
1587 """
1578 q = repo.mq
1588 q = repo.mq
1579 message = cmdutil.logmessage(opts)
1589 message = cmdutil.logmessage(opts)
1580 if opts['edit']:
1590 if opts['edit']:
1581 if message:
1591 if message:
1582 raise util.Abort(_('option "-e" incompatible with "-m" or "-l"'))
1592 raise util.Abort(_('option "-e" incompatible with "-m" or "-l"'))
1583 patch = q.applied[-1].name
1593 patch = q.applied[-1].name
1584 (message, comment, user, date, hasdiff) = q.readheaders(patch)
1594 (message, comment, user, date, hasdiff) = q.readheaders(patch)
1585 message = ui.edit('\n'.join(message), user or ui.username())
1595 message = ui.edit('\n'.join(message), user or ui.username())
1586 ret = q.refresh(repo, pats, msg=message, **opts)
1596 ret = q.refresh(repo, pats, msg=message, **opts)
1587 q.save_dirty()
1597 q.save_dirty()
1588 return ret
1598 return ret
1589
1599
1590 def diff(ui, repo, *pats, **opts):
1600 def diff(ui, repo, *pats, **opts):
1591 """diff of the current patch"""
1601 """diff of the current patch"""
1592 repo.mq.diff(repo, pats, opts)
1602 repo.mq.diff(repo, pats, opts)
1593 return 0
1603 return 0
1594
1604
1595 def fold(ui, repo, *files, **opts):
1605 def fold(ui, repo, *files, **opts):
1596 """fold the named patches into the current patch
1606 """fold the named patches into the current patch
1597
1607
1598 Patches must not yet be applied. Each patch will be successively
1608 Patches must not yet be applied. Each patch will be successively
1599 applied to the current patch in the order given. If all the
1609 applied to the current patch in the order given. If all the
1600 patches apply successfully, the current patch will be refreshed
1610 patches apply successfully, the current patch will be refreshed
1601 with the new cumulative patch, and the folded patches will
1611 with the new cumulative patch, and the folded patches will
1602 be deleted. With -k/--keep, the folded patch files will not
1612 be deleted. With -k/--keep, the folded patch files will not
1603 be removed afterwards.
1613 be removed afterwards.
1604
1614
1605 The header for each folded patch will be concatenated with
1615 The header for each folded patch will be concatenated with
1606 the current patch header, separated by a line of '* * *'."""
1616 the current patch header, separated by a line of '* * *'."""
1607
1617
1608 q = repo.mq
1618 q = repo.mq
1609
1619
1610 if not files:
1620 if not files:
1611 raise util.Abort(_('qfold requires at least one patch name'))
1621 raise util.Abort(_('qfold requires at least one patch name'))
1612 if not q.check_toppatch(repo):
1622 if not q.check_toppatch(repo):
1613 raise util.Abort(_('No patches applied'))
1623 raise util.Abort(_('No patches applied'))
1614
1624
1615 message = cmdutil.logmessage(opts)
1625 message = cmdutil.logmessage(opts)
1616 if opts['edit']:
1626 if opts['edit']:
1617 if message:
1627 if message:
1618 raise util.Abort(_('option "-e" incompatible with "-m" or "-l"'))
1628 raise util.Abort(_('option "-e" incompatible with "-m" or "-l"'))
1619
1629
1620 parent = q.lookup('qtip')
1630 parent = q.lookup('qtip')
1621 patches = []
1631 patches = []
1622 messages = []
1632 messages = []
1623 for f in files:
1633 for f in files:
1624 p = q.lookup(f)
1634 p = q.lookup(f)
1625 if p in patches or p == parent:
1635 if p in patches or p == parent:
1626 ui.warn(_('Skipping already folded patch %s') % p)
1636 ui.warn(_('Skipping already folded patch %s') % p)
1627 if q.isapplied(p):
1637 if q.isapplied(p):
1628 raise util.Abort(_('qfold cannot fold already applied patch %s') % p)
1638 raise util.Abort(_('qfold cannot fold already applied patch %s') % p)
1629 patches.append(p)
1639 patches.append(p)
1630
1640
1631 for p in patches:
1641 for p in patches:
1632 if not message:
1642 if not message:
1633 messages.append(q.readheaders(p)[0])
1643 messages.append(q.readheaders(p)[0])
1634 pf = q.join(p)
1644 pf = q.join(p)
1635 (patchsuccess, files, fuzz) = q.patch(repo, pf)
1645 (patchsuccess, files, fuzz) = q.patch(repo, pf)
1636 if not patchsuccess:
1646 if not patchsuccess:
1637 raise util.Abort(_('Error folding patch %s') % p)
1647 raise util.Abort(_('Error folding patch %s') % p)
1638 patch.updatedir(ui, repo, files)
1648 patch.updatedir(ui, repo, files)
1639
1649
1640 if not message:
1650 if not message:
1641 message, comments, user = q.readheaders(parent)[0:3]
1651 message, comments, user = q.readheaders(parent)[0:3]
1642 for msg in messages:
1652 for msg in messages:
1643 message.append('* * *')
1653 message.append('* * *')
1644 message.extend(msg)
1654 message.extend(msg)
1645 message = '\n'.join(message)
1655 message = '\n'.join(message)
1646
1656
1647 if opts['edit']:
1657 if opts['edit']:
1648 message = ui.edit(message, user or ui.username())
1658 message = ui.edit(message, user or ui.username())
1649
1659
1650 q.refresh(repo, msg=message)
1660 q.refresh(repo, msg=message)
1651 q.delete(repo, patches, opts)
1661 q.delete(repo, patches, opts)
1652 q.save_dirty()
1662 q.save_dirty()
1653
1663
1654 def goto(ui, repo, patch, **opts):
1664 def goto(ui, repo, patch, **opts):
1655 '''push or pop patches until named patch is at top of stack'''
1665 '''push or pop patches until named patch is at top of stack'''
1656 q = repo.mq
1666 q = repo.mq
1657 patch = q.lookup(patch)
1667 patch = q.lookup(patch)
1658 if q.isapplied(patch):
1668 if q.isapplied(patch):
1659 ret = q.pop(repo, patch, force=opts['force'])
1669 ret = q.pop(repo, patch, force=opts['force'])
1660 else:
1670 else:
1661 ret = q.push(repo, patch, force=opts['force'])
1671 ret = q.push(repo, patch, force=opts['force'])
1662 q.save_dirty()
1672 q.save_dirty()
1663 return ret
1673 return ret
1664
1674
1665 def guard(ui, repo, *args, **opts):
1675 def guard(ui, repo, *args, **opts):
1666 '''set or print guards for a patch
1676 '''set or print guards for a patch
1667
1677
1668 Guards control whether a patch can be pushed. A patch with no
1678 Guards control whether a patch can be pushed. A patch with no
1669 guards is always pushed. A patch with a positive guard ("+foo") is
1679 guards is always pushed. A patch with a positive guard ("+foo") is
1670 pushed only if the qselect command has activated it. A patch with
1680 pushed only if the qselect command has activated it. A patch with
1671 a negative guard ("-foo") is never pushed if the qselect command
1681 a negative guard ("-foo") is never pushed if the qselect command
1672 has activated it.
1682 has activated it.
1673
1683
1674 With no arguments, print the currently active guards.
1684 With no arguments, print the currently active guards.
1675 With arguments, set guards for the named patch.
1685 With arguments, set guards for the named patch.
1676
1686
1677 To set a negative guard "-foo" on topmost patch ("--" is needed so
1687 To set a negative guard "-foo" on topmost patch ("--" is needed so
1678 hg will not interpret "-foo" as an option):
1688 hg will not interpret "-foo" as an option):
1679 hg qguard -- -foo
1689 hg qguard -- -foo
1680
1690
1681 To set guards on another patch:
1691 To set guards on another patch:
1682 hg qguard other.patch +2.6.17 -stable
1692 hg qguard other.patch +2.6.17 -stable
1683 '''
1693 '''
1684 def status(idx):
1694 def status(idx):
1685 guards = q.series_guards[idx] or ['unguarded']
1695 guards = q.series_guards[idx] or ['unguarded']
1686 ui.write('%s: %s\n' % (q.series[idx], ' '.join(guards)))
1696 ui.write('%s: %s\n' % (q.series[idx], ' '.join(guards)))
1687 q = repo.mq
1697 q = repo.mq
1688 patch = None
1698 patch = None
1689 args = list(args)
1699 args = list(args)
1690 if opts['list']:
1700 if opts['list']:
1691 if args or opts['none']:
1701 if args or opts['none']:
1692 raise util.Abort(_('cannot mix -l/--list with options or arguments'))
1702 raise util.Abort(_('cannot mix -l/--list with options or arguments'))
1693 for i in xrange(len(q.series)):
1703 for i in xrange(len(q.series)):
1694 status(i)
1704 status(i)
1695 return
1705 return
1696 if not args or args[0][0:1] in '-+':
1706 if not args or args[0][0:1] in '-+':
1697 if not q.applied:
1707 if not q.applied:
1698 raise util.Abort(_('no patches applied'))
1708 raise util.Abort(_('no patches applied'))
1699 patch = q.applied[-1].name
1709 patch = q.applied[-1].name
1700 if patch is None and args[0][0:1] not in '-+':
1710 if patch is None and args[0][0:1] not in '-+':
1701 patch = args.pop(0)
1711 patch = args.pop(0)
1702 if patch is None:
1712 if patch is None:
1703 raise util.Abort(_('no patch to work with'))
1713 raise util.Abort(_('no patch to work with'))
1704 if args or opts['none']:
1714 if args or opts['none']:
1705 idx = q.find_series(patch)
1715 idx = q.find_series(patch)
1706 if idx is None:
1716 if idx is None:
1707 raise util.Abort(_('no patch named %s') % patch)
1717 raise util.Abort(_('no patch named %s') % patch)
1708 q.set_guards(idx, args)
1718 q.set_guards(idx, args)
1709 q.save_dirty()
1719 q.save_dirty()
1710 else:
1720 else:
1711 status(q.series.index(q.lookup(patch)))
1721 status(q.series.index(q.lookup(patch)))
1712
1722
1713 def header(ui, repo, patch=None):
1723 def header(ui, repo, patch=None):
1714 """Print the header of the topmost or specified patch"""
1724 """Print the header of the topmost or specified patch"""
1715 q = repo.mq
1725 q = repo.mq
1716
1726
1717 if patch:
1727 if patch:
1718 patch = q.lookup(patch)
1728 patch = q.lookup(patch)
1719 else:
1729 else:
1720 if not q.applied:
1730 if not q.applied:
1721 ui.write('No patches applied\n')
1731 ui.write('No patches applied\n')
1722 return 1
1732 return 1
1723 patch = q.lookup('qtip')
1733 patch = q.lookup('qtip')
1724 message = repo.mq.readheaders(patch)[0]
1734 message = repo.mq.readheaders(patch)[0]
1725
1735
1726 ui.write('\n'.join(message) + '\n')
1736 ui.write('\n'.join(message) + '\n')
1727
1737
1728 def lastsavename(path):
1738 def lastsavename(path):
1729 (directory, base) = os.path.split(path)
1739 (directory, base) = os.path.split(path)
1730 names = os.listdir(directory)
1740 names = os.listdir(directory)
1731 namere = re.compile("%s.([0-9]+)" % base)
1741 namere = re.compile("%s.([0-9]+)" % base)
1732 maxindex = None
1742 maxindex = None
1733 maxname = None
1743 maxname = None
1734 for f in names:
1744 for f in names:
1735 m = namere.match(f)
1745 m = namere.match(f)
1736 if m:
1746 if m:
1737 index = int(m.group(1))
1747 index = int(m.group(1))
1738 if maxindex == None or index > maxindex:
1748 if maxindex == None or index > maxindex:
1739 maxindex = index
1749 maxindex = index
1740 maxname = f
1750 maxname = f
1741 if maxname:
1751 if maxname:
1742 return (os.path.join(directory, maxname), maxindex)
1752 return (os.path.join(directory, maxname), maxindex)
1743 return (None, None)
1753 return (None, None)
1744
1754
1745 def savename(path):
1755 def savename(path):
1746 (last, index) = lastsavename(path)
1756 (last, index) = lastsavename(path)
1747 if last is None:
1757 if last is None:
1748 index = 0
1758 index = 0
1749 newpath = path + ".%d" % (index + 1)
1759 newpath = path + ".%d" % (index + 1)
1750 return newpath
1760 return newpath
1751
1761
1752 def push(ui, repo, patch=None, **opts):
1762 def push(ui, repo, patch=None, **opts):
1753 """push the next patch onto the stack"""
1763 """push the next patch onto the stack"""
1754 q = repo.mq
1764 q = repo.mq
1755 mergeq = None
1765 mergeq = None
1756
1766
1757 if opts['all']:
1767 if opts['all']:
1758 if not q.series:
1768 if not q.series:
1759 ui.warn(_('no patches in series\n'))
1769 ui.warn(_('no patches in series\n'))
1760 return 0
1770 return 0
1761 patch = q.series[-1]
1771 patch = q.series[-1]
1762 if opts['merge']:
1772 if opts['merge']:
1763 if opts['name']:
1773 if opts['name']:
1764 newpath = opts['name']
1774 newpath = opts['name']
1765 else:
1775 else:
1766 newpath, i = lastsavename(q.path)
1776 newpath, i = lastsavename(q.path)
1767 if not newpath:
1777 if not newpath:
1768 ui.warn("no saved queues found, please use -n\n")
1778 ui.warn("no saved queues found, please use -n\n")
1769 return 1
1779 return 1
1770 mergeq = queue(ui, repo.join(""), newpath)
1780 mergeq = queue(ui, repo.join(""), newpath)
1771 ui.warn("merging with queue at: %s\n" % mergeq.path)
1781 ui.warn("merging with queue at: %s\n" % mergeq.path)
1772 ret = q.push(repo, patch, force=opts['force'], list=opts['list'],
1782 ret = q.push(repo, patch, force=opts['force'], list=opts['list'],
1773 mergeq=mergeq)
1783 mergeq=mergeq)
1774 return ret
1784 return ret
1775
1785
1776 def pop(ui, repo, patch=None, **opts):
1786 def pop(ui, repo, patch=None, **opts):
1777 """pop the current patch off the stack"""
1787 """pop the current patch off the stack"""
1778 localupdate = True
1788 localupdate = True
1779 if opts['name']:
1789 if opts['name']:
1780 q = queue(ui, repo.join(""), repo.join(opts['name']))
1790 q = queue(ui, repo.join(""), repo.join(opts['name']))
1781 ui.warn('using patch queue: %s\n' % q.path)
1791 ui.warn('using patch queue: %s\n' % q.path)
1782 localupdate = False
1792 localupdate = False
1783 else:
1793 else:
1784 q = repo.mq
1794 q = repo.mq
1785 ret = q.pop(repo, patch, force=opts['force'], update=localupdate,
1795 ret = q.pop(repo, patch, force=opts['force'], update=localupdate,
1786 all=opts['all'])
1796 all=opts['all'])
1787 q.save_dirty()
1797 q.save_dirty()
1788 return ret
1798 return ret
1789
1799
1790 def rename(ui, repo, patch, name=None, **opts):
1800 def rename(ui, repo, patch, name=None, **opts):
1791 """rename a patch
1801 """rename a patch
1792
1802
1793 With one argument, renames the current patch to PATCH1.
1803 With one argument, renames the current patch to PATCH1.
1794 With two arguments, renames PATCH1 to PATCH2."""
1804 With two arguments, renames PATCH1 to PATCH2."""
1795
1805
1796 q = repo.mq
1806 q = repo.mq
1797
1807
1798 if not name:
1808 if not name:
1799 name = patch
1809 name = patch
1800 patch = None
1810 patch = None
1801
1811
1802 if patch:
1812 if patch:
1803 patch = q.lookup(patch)
1813 patch = q.lookup(patch)
1804 else:
1814 else:
1805 if not q.applied:
1815 if not q.applied:
1806 ui.write(_('No patches applied\n'))
1816 ui.write(_('No patches applied\n'))
1807 return
1817 return
1808 patch = q.lookup('qtip')
1818 patch = q.lookup('qtip')
1809 absdest = q.join(name)
1819 absdest = q.join(name)
1810 if os.path.isdir(absdest):
1820 if os.path.isdir(absdest):
1811 name = normname(os.path.join(name, os.path.basename(patch)))
1821 name = normname(os.path.join(name, os.path.basename(patch)))
1812 absdest = q.join(name)
1822 absdest = q.join(name)
1813 if os.path.exists(absdest):
1823 if os.path.exists(absdest):
1814 raise util.Abort(_('%s already exists') % absdest)
1824 raise util.Abort(_('%s already exists') % absdest)
1815
1825
1816 if name in q.series:
1826 if name in q.series:
1817 raise util.Abort(_('A patch named %s already exists in the series file') % name)
1827 raise util.Abort(_('A patch named %s already exists in the series file') % name)
1818
1828
1819 if ui.verbose:
1829 if ui.verbose:
1820 ui.write('Renaming %s to %s\n' % (patch, name))
1830 ui.write('Renaming %s to %s\n' % (patch, name))
1821 i = q.find_series(patch)
1831 i = q.find_series(patch)
1822 guards = q.guard_re.findall(q.full_series[i])
1832 guards = q.guard_re.findall(q.full_series[i])
1823 q.full_series[i] = name + ''.join([' #' + g for g in guards])
1833 q.full_series[i] = name + ''.join([' #' + g for g in guards])
1824 q.parse_series()
1834 q.parse_series()
1825 q.series_dirty = 1
1835 q.series_dirty = 1
1826
1836
1827 info = q.isapplied(patch)
1837 info = q.isapplied(patch)
1828 if info:
1838 if info:
1829 q.applied[info[0]] = statusentry(info[1], name)
1839 q.applied[info[0]] = statusentry(info[1], name)
1830 q.applied_dirty = 1
1840 q.applied_dirty = 1
1831
1841
1832 util.rename(q.join(patch), absdest)
1842 util.rename(q.join(patch), absdest)
1833 r = q.qrepo()
1843 r = q.qrepo()
1834 if r:
1844 if r:
1835 wlock = r.wlock()
1845 wlock = r.wlock()
1836 if r.dirstate.state(name) == 'r':
1846 if r.dirstate.state(name) == 'r':
1837 r.undelete([name], wlock)
1847 r.undelete([name], wlock)
1838 r.copy(patch, name, wlock)
1848 r.copy(patch, name, wlock)
1839 r.remove([patch], False, wlock)
1849 r.remove([patch], False, wlock)
1840
1850
1841 q.save_dirty()
1851 q.save_dirty()
1842
1852
1843 def restore(ui, repo, rev, **opts):
1853 def restore(ui, repo, rev, **opts):
1844 """restore the queue state saved by a rev"""
1854 """restore the queue state saved by a rev"""
1845 rev = repo.lookup(rev)
1855 rev = repo.lookup(rev)
1846 q = repo.mq
1856 q = repo.mq
1847 q.restore(repo, rev, delete=opts['delete'],
1857 q.restore(repo, rev, delete=opts['delete'],
1848 qupdate=opts['update'])
1858 qupdate=opts['update'])
1849 q.save_dirty()
1859 q.save_dirty()
1850 return 0
1860 return 0
1851
1861
1852 def save(ui, repo, **opts):
1862 def save(ui, repo, **opts):
1853 """save current queue state"""
1863 """save current queue state"""
1854 q = repo.mq
1864 q = repo.mq
1855 message = cmdutil.logmessage(opts)
1865 message = cmdutil.logmessage(opts)
1856 ret = q.save(repo, msg=message)
1866 ret = q.save(repo, msg=message)
1857 if ret:
1867 if ret:
1858 return ret
1868 return ret
1859 q.save_dirty()
1869 q.save_dirty()
1860 if opts['copy']:
1870 if opts['copy']:
1861 path = q.path
1871 path = q.path
1862 if opts['name']:
1872 if opts['name']:
1863 newpath = os.path.join(q.basepath, opts['name'])
1873 newpath = os.path.join(q.basepath, opts['name'])
1864 if os.path.exists(newpath):
1874 if os.path.exists(newpath):
1865 if not os.path.isdir(newpath):
1875 if not os.path.isdir(newpath):
1866 raise util.Abort(_('destination %s exists and is not '
1876 raise util.Abort(_('destination %s exists and is not '
1867 'a directory') % newpath)
1877 'a directory') % newpath)
1868 if not opts['force']:
1878 if not opts['force']:
1869 raise util.Abort(_('destination %s exists, '
1879 raise util.Abort(_('destination %s exists, '
1870 'use -f to force') % newpath)
1880 'use -f to force') % newpath)
1871 else:
1881 else:
1872 newpath = savename(path)
1882 newpath = savename(path)
1873 ui.warn("copy %s to %s\n" % (path, newpath))
1883 ui.warn("copy %s to %s\n" % (path, newpath))
1874 util.copyfiles(path, newpath)
1884 util.copyfiles(path, newpath)
1875 if opts['empty']:
1885 if opts['empty']:
1876 try:
1886 try:
1877 os.unlink(q.join(q.status_path))
1887 os.unlink(q.join(q.status_path))
1878 except:
1888 except:
1879 pass
1889 pass
1880 return 0
1890 return 0
1881
1891
1882 def strip(ui, repo, rev, **opts):
1892 def strip(ui, repo, rev, **opts):
1883 """strip a revision and all later revs on the same branch"""
1893 """strip a revision and all later revs on the same branch"""
1884 rev = repo.lookup(rev)
1894 rev = repo.lookup(rev)
1885 backup = 'all'
1895 backup = 'all'
1886 if opts['backup']:
1896 if opts['backup']:
1887 backup = 'strip'
1897 backup = 'strip'
1888 elif opts['nobackup']:
1898 elif opts['nobackup']:
1889 backup = 'none'
1899 backup = 'none'
1890 update = repo.dirstate.parents()[0] != revlog.nullid
1900 update = repo.dirstate.parents()[0] != revlog.nullid
1891 repo.mq.strip(repo, rev, backup=backup, update=update)
1901 repo.mq.strip(repo, rev, backup=backup, update=update)
1892 return 0
1902 return 0
1893
1903
1894 def select(ui, repo, *args, **opts):
1904 def select(ui, repo, *args, **opts):
1895 '''set or print guarded patches to push
1905 '''set or print guarded patches to push
1896
1906
1897 Use the qguard command to set or print guards on patch, then use
1907 Use the qguard command to set or print guards on patch, then use
1898 qselect to tell mq which guards to use. A patch will be pushed if it
1908 qselect to tell mq which guards to use. A patch will be pushed if it
1899 has no guards or any positive guards match the currently selected guard,
1909 has no guards or any positive guards match the currently selected guard,
1900 but will not be pushed if any negative guards match the current guard.
1910 but will not be pushed if any negative guards match the current guard.
1901 For example:
1911 For example:
1902
1912
1903 qguard foo.patch -stable (negative guard)
1913 qguard foo.patch -stable (negative guard)
1904 qguard bar.patch +stable (positive guard)
1914 qguard bar.patch +stable (positive guard)
1905 qselect stable
1915 qselect stable
1906
1916
1907 This activates the "stable" guard. mq will skip foo.patch (because
1917 This activates the "stable" guard. mq will skip foo.patch (because
1908 it has a negative match) but push bar.patch (because it
1918 it has a negative match) but push bar.patch (because it
1909 has a positive match).
1919 has a positive match).
1910
1920
1911 With no arguments, prints the currently active guards.
1921 With no arguments, prints the currently active guards.
1912 With one argument, sets the active guard.
1922 With one argument, sets the active guard.
1913
1923
1914 Use -n/--none to deactivate guards (no other arguments needed).
1924 Use -n/--none to deactivate guards (no other arguments needed).
1915 When no guards are active, patches with positive guards are skipped
1925 When no guards are active, patches with positive guards are skipped
1916 and patches with negative guards are pushed.
1926 and patches with negative guards are pushed.
1917
1927
1918 qselect can change the guards on applied patches. It does not pop
1928 qselect can change the guards on applied patches. It does not pop
1919 guarded patches by default. Use --pop to pop back to the last applied
1929 guarded patches by default. Use --pop to pop back to the last applied
1920 patch that is not guarded. Use --reapply (which implies --pop) to push
1930 patch that is not guarded. Use --reapply (which implies --pop) to push
1921 back to the current patch afterwards, but skip guarded patches.
1931 back to the current patch afterwards, but skip guarded patches.
1922
1932
1923 Use -s/--series to print a list of all guards in the series file (no
1933 Use -s/--series to print a list of all guards in the series file (no
1924 other arguments needed). Use -v for more information.'''
1934 other arguments needed). Use -v for more information.'''
1925
1935
1926 q = repo.mq
1936 q = repo.mq
1927 guards = q.active()
1937 guards = q.active()
1928 if args or opts['none']:
1938 if args or opts['none']:
1929 old_unapplied = q.unapplied(repo)
1939 old_unapplied = q.unapplied(repo)
1930 old_guarded = [i for i in xrange(len(q.applied)) if
1940 old_guarded = [i for i in xrange(len(q.applied)) if
1931 not q.pushable(i)[0]]
1941 not q.pushable(i)[0]]
1932 q.set_active(args)
1942 q.set_active(args)
1933 q.save_dirty()
1943 q.save_dirty()
1934 if not args:
1944 if not args:
1935 ui.status(_('guards deactivated\n'))
1945 ui.status(_('guards deactivated\n'))
1936 if not opts['pop'] and not opts['reapply']:
1946 if not opts['pop'] and not opts['reapply']:
1937 unapplied = q.unapplied(repo)
1947 unapplied = q.unapplied(repo)
1938 guarded = [i for i in xrange(len(q.applied))
1948 guarded = [i for i in xrange(len(q.applied))
1939 if not q.pushable(i)[0]]
1949 if not q.pushable(i)[0]]
1940 if len(unapplied) != len(old_unapplied):
1950 if len(unapplied) != len(old_unapplied):
1941 ui.status(_('number of unguarded, unapplied patches has '
1951 ui.status(_('number of unguarded, unapplied patches has '
1942 'changed from %d to %d\n') %
1952 'changed from %d to %d\n') %
1943 (len(old_unapplied), len(unapplied)))
1953 (len(old_unapplied), len(unapplied)))
1944 if len(guarded) != len(old_guarded):
1954 if len(guarded) != len(old_guarded):
1945 ui.status(_('number of guarded, applied patches has changed '
1955 ui.status(_('number of guarded, applied patches has changed '
1946 'from %d to %d\n') %
1956 'from %d to %d\n') %
1947 (len(old_guarded), len(guarded)))
1957 (len(old_guarded), len(guarded)))
1948 elif opts['series']:
1958 elif opts['series']:
1949 guards = {}
1959 guards = {}
1950 noguards = 0
1960 noguards = 0
1951 for gs in q.series_guards:
1961 for gs in q.series_guards:
1952 if not gs:
1962 if not gs:
1953 noguards += 1
1963 noguards += 1
1954 for g in gs:
1964 for g in gs:
1955 guards.setdefault(g, 0)
1965 guards.setdefault(g, 0)
1956 guards[g] += 1
1966 guards[g] += 1
1957 if ui.verbose:
1967 if ui.verbose:
1958 guards['NONE'] = noguards
1968 guards['NONE'] = noguards
1959 guards = guards.items()
1969 guards = guards.items()
1960 guards.sort(lambda a, b: cmp(a[0][1:], b[0][1:]))
1970 guards.sort(lambda a, b: cmp(a[0][1:], b[0][1:]))
1961 if guards:
1971 if guards:
1962 ui.note(_('guards in series file:\n'))
1972 ui.note(_('guards in series file:\n'))
1963 for guard, count in guards:
1973 for guard, count in guards:
1964 ui.note('%2d ' % count)
1974 ui.note('%2d ' % count)
1965 ui.write(guard, '\n')
1975 ui.write(guard, '\n')
1966 else:
1976 else:
1967 ui.note(_('no guards in series file\n'))
1977 ui.note(_('no guards in series file\n'))
1968 else:
1978 else:
1969 if guards:
1979 if guards:
1970 ui.note(_('active guards:\n'))
1980 ui.note(_('active guards:\n'))
1971 for g in guards:
1981 for g in guards:
1972 ui.write(g, '\n')
1982 ui.write(g, '\n')
1973 else:
1983 else:
1974 ui.write(_('no active guards\n'))
1984 ui.write(_('no active guards\n'))
1975 reapply = opts['reapply'] and q.applied and q.appliedname(-1)
1985 reapply = opts['reapply'] and q.applied and q.appliedname(-1)
1976 popped = False
1986 popped = False
1977 if opts['pop'] or opts['reapply']:
1987 if opts['pop'] or opts['reapply']:
1978 for i in xrange(len(q.applied)):
1988 for i in xrange(len(q.applied)):
1979 pushable, reason = q.pushable(i)
1989 pushable, reason = q.pushable(i)
1980 if not pushable:
1990 if not pushable:
1981 ui.status(_('popping guarded patches\n'))
1991 ui.status(_('popping guarded patches\n'))
1982 popped = True
1992 popped = True
1983 if i == 0:
1993 if i == 0:
1984 q.pop(repo, all=True)
1994 q.pop(repo, all=True)
1985 else:
1995 else:
1986 q.pop(repo, i-1)
1996 q.pop(repo, i-1)
1987 break
1997 break
1988 if popped:
1998 if popped:
1989 try:
1999 try:
1990 if reapply:
2000 if reapply:
1991 ui.status(_('reapplying unguarded patches\n'))
2001 ui.status(_('reapplying unguarded patches\n'))
1992 q.push(repo, reapply)
2002 q.push(repo, reapply)
1993 finally:
2003 finally:
1994 q.save_dirty()
2004 q.save_dirty()
1995
2005
1996 def reposetup(ui, repo):
2006 def reposetup(ui, repo):
1997 class mqrepo(repo.__class__):
2007 class mqrepo(repo.__class__):
1998 def abort_if_wdir_patched(self, errmsg, force=False):
2008 def abort_if_wdir_patched(self, errmsg, force=False):
1999 if self.mq.applied and not force:
2009 if self.mq.applied and not force:
2000 parent = revlog.hex(self.dirstate.parents()[0])
2010 parent = revlog.hex(self.dirstate.parents()[0])
2001 if parent in [s.rev for s in self.mq.applied]:
2011 if parent in [s.rev for s in self.mq.applied]:
2002 raise util.Abort(errmsg)
2012 raise util.Abort(errmsg)
2003
2013
2004 def commit(self, *args, **opts):
2014 def commit(self, *args, **opts):
2005 if len(args) >= 6:
2015 if len(args) >= 6:
2006 force = args[5]
2016 force = args[5]
2007 else:
2017 else:
2008 force = opts.get('force')
2018 force = opts.get('force')
2009 self.abort_if_wdir_patched(
2019 self.abort_if_wdir_patched(
2010 _('cannot commit over an applied mq patch'),
2020 _('cannot commit over an applied mq patch'),
2011 force)
2021 force)
2012
2022
2013 return super(mqrepo, self).commit(*args, **opts)
2023 return super(mqrepo, self).commit(*args, **opts)
2014
2024
2015 def push(self, remote, force=False, revs=None):
2025 def push(self, remote, force=False, revs=None):
2016 if self.mq.applied and not force and not revs:
2026 if self.mq.applied and not force and not revs:
2017 raise util.Abort(_('source has mq patches applied'))
2027 raise util.Abort(_('source has mq patches applied'))
2018 return super(mqrepo, self).push(remote, force, revs)
2028 return super(mqrepo, self).push(remote, force, revs)
2019
2029
2020 def tags(self):
2030 def tags(self):
2021 if self.tagscache:
2031 if self.tagscache:
2022 return self.tagscache
2032 return self.tagscache
2023
2033
2024 tagscache = super(mqrepo, self).tags()
2034 tagscache = super(mqrepo, self).tags()
2025
2035
2026 q = self.mq
2036 q = self.mq
2027 if not q.applied:
2037 if not q.applied:
2028 return tagscache
2038 return tagscache
2029
2039
2030 mqtags = [(revlog.bin(patch.rev), patch.name) for patch in q.applied]
2040 mqtags = [(revlog.bin(patch.rev), patch.name) for patch in q.applied]
2031 mqtags.append((mqtags[-1][0], 'qtip'))
2041 mqtags.append((mqtags[-1][0], 'qtip'))
2032 mqtags.append((mqtags[0][0], 'qbase'))
2042 mqtags.append((mqtags[0][0], 'qbase'))
2033 mqtags.append((self.changelog.parents(mqtags[0][0])[0], 'qparent'))
2043 mqtags.append((self.changelog.parents(mqtags[0][0])[0], 'qparent'))
2034 for patch in mqtags:
2044 for patch in mqtags:
2035 if patch[1] in tagscache:
2045 if patch[1] in tagscache:
2036 self.ui.warn('Tag %s overrides mq patch of the same name\n' % patch[1])
2046 self.ui.warn('Tag %s overrides mq patch of the same name\n' % patch[1])
2037 else:
2047 else:
2038 tagscache[patch[1]] = patch[0]
2048 tagscache[patch[1]] = patch[0]
2039
2049
2040 return tagscache
2050 return tagscache
2041
2051
2042 def _branchtags(self):
2052 def _branchtags(self):
2043 q = self.mq
2053 q = self.mq
2044 if not q.applied:
2054 if not q.applied:
2045 return super(mqrepo, self)._branchtags()
2055 return super(mqrepo, self)._branchtags()
2046
2056
2047 self.branchcache = {} # avoid recursion in changectx
2057 self.branchcache = {} # avoid recursion in changectx
2048 cl = self.changelog
2058 cl = self.changelog
2049 partial, last, lrev = self._readbranchcache()
2059 partial, last, lrev = self._readbranchcache()
2050
2060
2051 qbase = cl.rev(revlog.bin(q.applied[0].rev))
2061 qbase = cl.rev(revlog.bin(q.applied[0].rev))
2052 start = lrev + 1
2062 start = lrev + 1
2053 if start < qbase:
2063 if start < qbase:
2054 # update the cache (excluding the patches) and save it
2064 # update the cache (excluding the patches) and save it
2055 self._updatebranchcache(partial, lrev+1, qbase)
2065 self._updatebranchcache(partial, lrev+1, qbase)
2056 self._writebranchcache(partial, cl.node(qbase-1), qbase-1)
2066 self._writebranchcache(partial, cl.node(qbase-1), qbase-1)
2057 start = qbase
2067 start = qbase
2058 # if start = qbase, the cache is as updated as it should be.
2068 # if start = qbase, the cache is as updated as it should be.
2059 # if start > qbase, the cache includes (part of) the patches.
2069 # if start > qbase, the cache includes (part of) the patches.
2060 # we might as well use it, but we won't save it.
2070 # we might as well use it, but we won't save it.
2061
2071
2062 # update the cache up to the tip
2072 # update the cache up to the tip
2063 self._updatebranchcache(partial, start, cl.count())
2073 self._updatebranchcache(partial, start, cl.count())
2064
2074
2065 return partial
2075 return partial
2066
2076
2067 if repo.local():
2077 if repo.local():
2068 repo.__class__ = mqrepo
2078 repo.__class__ = mqrepo
2069 repo.mq = queue(ui, repo.join(""))
2079 repo.mq = queue(ui, repo.join(""))
2070
2080
2071 seriesopts = [('s', 'summary', None, _('print first line of patch header'))]
2081 seriesopts = [('s', 'summary', None, _('print first line of patch header'))]
2072
2082
2073 cmdtable = {
2083 cmdtable = {
2074 "qapplied": (applied, [] + seriesopts, 'hg qapplied [-s] [PATCH]'),
2084 "qapplied": (applied, [] + seriesopts, 'hg qapplied [-s] [PATCH]'),
2075 "qclone": (clone,
2085 "qclone": (clone,
2076 [('', 'pull', None, _('use pull protocol to copy metadata')),
2086 [('', 'pull', None, _('use pull protocol to copy metadata')),
2077 ('U', 'noupdate', None, _('do not update the new working directories')),
2087 ('U', 'noupdate', None, _('do not update the new working directories')),
2078 ('', 'uncompressed', None,
2088 ('', 'uncompressed', None,
2079 _('use uncompressed transfer (fast over LAN)')),
2089 _('use uncompressed transfer (fast over LAN)')),
2080 ('e', 'ssh', '', _('specify ssh command to use')),
2090 ('e', 'ssh', '', _('specify ssh command to use')),
2081 ('p', 'patches', '', _('location of source patch repo')),
2091 ('p', 'patches', '', _('location of source patch repo')),
2082 ('', 'remotecmd', '',
2092 ('', 'remotecmd', '',
2083 _('specify hg command to run on the remote side'))],
2093 _('specify hg command to run on the remote side'))],
2084 'hg qclone [OPTION]... SOURCE [DEST]'),
2094 'hg qclone [OPTION]... SOURCE [DEST]'),
2085 "qcommit|qci":
2095 "qcommit|qci":
2086 (commit,
2096 (commit,
2087 commands.table["^commit|ci"][1],
2097 commands.table["^commit|ci"][1],
2088 'hg qcommit [OPTION]... [FILE]...'),
2098 'hg qcommit [OPTION]... [FILE]...'),
2089 "^qdiff": (diff,
2099 "^qdiff": (diff,
2090 [('g', 'git', None, _('use git extended diff format')),
2100 [('g', 'git', None, _('use git extended diff format')),
2091 ('I', 'include', [], _('include names matching the given patterns')),
2101 ('I', 'include', [], _('include names matching the given patterns')),
2092 ('X', 'exclude', [], _('exclude names matching the given patterns'))],
2102 ('X', 'exclude', [], _('exclude names matching the given patterns'))],
2093 'hg qdiff [-I] [-X] [FILE]...'),
2103 'hg qdiff [-I] [-X] [FILE]...'),
2094 "qdelete|qremove|qrm":
2104 "qdelete|qremove|qrm":
2095 (delete,
2105 (delete,
2096 [('k', 'keep', None, _('keep patch file')),
2106 [('k', 'keep', None, _('keep patch file')),
2097 ('r', 'rev', [], _('stop managing a revision'))],
2107 ('r', 'rev', [], _('stop managing a revision'))],
2098 'hg qdelete [-k] [-r REV]... PATCH...'),
2108 'hg qdelete [-k] [-r REV]... PATCH...'),
2099 'qfold':
2109 'qfold':
2100 (fold,
2110 (fold,
2101 [('e', 'edit', None, _('edit patch header')),
2111 [('e', 'edit', None, _('edit patch header')),
2102 ('k', 'keep', None, _('keep folded patch files'))
2112 ('k', 'keep', None, _('keep folded patch files'))
2103 ] + commands.commitopts,
2113 ] + commands.commitopts,
2104 'hg qfold [-e] [-m <text>] [-l <file] PATCH...'),
2114 'hg qfold [-e] [-m <text>] [-l <file] PATCH...'),
2105 'qgoto': (goto, [('f', 'force', None, _('overwrite any local changes'))],
2115 'qgoto': (goto, [('f', 'force', None, _('overwrite any local changes'))],
2106 'hg qgoto [OPT]... PATCH'),
2116 'hg qgoto [OPT]... PATCH'),
2107 'qguard': (guard, [('l', 'list', None, _('list all patches and guards')),
2117 'qguard': (guard, [('l', 'list', None, _('list all patches and guards')),
2108 ('n', 'none', None, _('drop all guards'))],
2118 ('n', 'none', None, _('drop all guards'))],
2109 'hg qguard [PATCH] [+GUARD]... [-GUARD]...'),
2119 'hg qguard [PATCH] [+GUARD]... [-GUARD]...'),
2110 'qheader': (header, [],
2120 'qheader': (header, [],
2111 _('hg qheader [PATCH]')),
2121 _('hg qheader [PATCH]')),
2112 "^qimport":
2122 "^qimport":
2113 (qimport,
2123 (qimport,
2114 [('e', 'existing', None, 'import file in patch dir'),
2124 [('e', 'existing', None, 'import file in patch dir'),
2115 ('n', 'name', '', 'patch file name'),
2125 ('n', 'name', '', 'patch file name'),
2116 ('f', 'force', None, 'overwrite existing files'),
2126 ('f', 'force', None, 'overwrite existing files'),
2117 ('r', 'rev', [], 'place existing revisions under mq control'),
2127 ('r', 'rev', [], 'place existing revisions under mq control'),
2118 ('g', 'git', None, _('use git extended diff format'))],
2128 ('g', 'git', None, _('use git extended diff format'))],
2119 'hg qimport [-e] [-n NAME] [-f] [-g] [-r REV]... FILE...'),
2129 'hg qimport [-e] [-n NAME] [-f] [-g] [-r REV]... FILE...'),
2120 "^qinit":
2130 "^qinit":
2121 (init,
2131 (init,
2122 [('c', 'create-repo', None, 'create queue repository')],
2132 [('c', 'create-repo', None, 'create queue repository')],
2123 'hg qinit [-c]'),
2133 'hg qinit [-c]'),
2124 "qnew":
2134 "qnew":
2125 (new,
2135 (new,
2126 [('e', 'edit', None, _('edit commit message')),
2136 [('e', 'edit', None, _('edit commit message')),
2127 ('f', 'force', None, _('import uncommitted changes into patch'))
2137 ('f', 'force', None, _('import uncommitted changes into patch')),
2138 ('I', 'include', [], _('include names matching the given patterns')),
2139 ('X', 'exclude', [], _('exclude names matching the given patterns'))
2128 ] + commands.commitopts,
2140 ] + commands.commitopts,
2129 'hg qnew [-e] [-m TEXT] [-l FILE] [-f] PATCH'),
2141 'hg qnew [-e] [-m TEXT] [-l FILE] [-f] PATCH [FILE]...'),
2130 "qnext": (next, [] + seriesopts, 'hg qnext [-s]'),
2142 "qnext": (next, [] + seriesopts, 'hg qnext [-s]'),
2131 "qprev": (prev, [] + seriesopts, 'hg qprev [-s]'),
2143 "qprev": (prev, [] + seriesopts, 'hg qprev [-s]'),
2132 "^qpop":
2144 "^qpop":
2133 (pop,
2145 (pop,
2134 [('a', 'all', None, 'pop all patches'),
2146 [('a', 'all', None, 'pop all patches'),
2135 ('n', 'name', '', 'queue name to pop'),
2147 ('n', 'name', '', 'queue name to pop'),
2136 ('f', 'force', None, 'forget any local changes')],
2148 ('f', 'force', None, 'forget any local changes')],
2137 'hg qpop [-a] [-n NAME] [-f] [PATCH | INDEX]'),
2149 'hg qpop [-a] [-n NAME] [-f] [PATCH | INDEX]'),
2138 "^qpush":
2150 "^qpush":
2139 (push,
2151 (push,
2140 [('f', 'force', None, 'apply if the patch has rejects'),
2152 [('f', 'force', None, 'apply if the patch has rejects'),
2141 ('l', 'list', None, 'list patch name in commit text'),
2153 ('l', 'list', None, 'list patch name in commit text'),
2142 ('a', 'all', None, 'apply all patches'),
2154 ('a', 'all', None, 'apply all patches'),
2143 ('m', 'merge', None, 'merge from another queue'),
2155 ('m', 'merge', None, 'merge from another queue'),
2144 ('n', 'name', '', 'merge queue name')],
2156 ('n', 'name', '', 'merge queue name')],
2145 'hg qpush [-f] [-l] [-a] [-m] [-n NAME] [PATCH | INDEX]'),
2157 'hg qpush [-f] [-l] [-a] [-m] [-n NAME] [PATCH | INDEX]'),
2146 "^qrefresh":
2158 "^qrefresh":
2147 (refresh,
2159 (refresh,
2148 [('e', 'edit', None, _('edit commit message')),
2160 [('e', 'edit', None, _('edit commit message')),
2149 ('g', 'git', None, _('use git extended diff format')),
2161 ('g', 'git', None, _('use git extended diff format')),
2150 ('s', 'short', None, 'refresh only files already in the patch'),
2162 ('s', 'short', None, 'refresh only files already in the patch'),
2151 ('I', 'include', [], _('include names matching the given patterns')),
2163 ('I', 'include', [], _('include names matching the given patterns')),
2152 ('X', 'exclude', [], _('exclude names matching the given patterns'))
2164 ('X', 'exclude', [], _('exclude names matching the given patterns'))
2153 ] + commands.commitopts,
2165 ] + commands.commitopts,
2154 'hg qrefresh [-I] [-X] [-e] [-m TEXT] [-l FILE] [-s] [FILE]...'),
2166 'hg qrefresh [-I] [-X] [-e] [-m TEXT] [-l FILE] [-s] [FILE]...'),
2155 'qrename|qmv':
2167 'qrename|qmv':
2156 (rename, [], 'hg qrename PATCH1 [PATCH2]'),
2168 (rename, [], 'hg qrename PATCH1 [PATCH2]'),
2157 "qrestore":
2169 "qrestore":
2158 (restore,
2170 (restore,
2159 [('d', 'delete', None, 'delete save entry'),
2171 [('d', 'delete', None, 'delete save entry'),
2160 ('u', 'update', None, 'update queue working dir')],
2172 ('u', 'update', None, 'update queue working dir')],
2161 'hg qrestore [-d] [-u] REV'),
2173 'hg qrestore [-d] [-u] REV'),
2162 "qsave":
2174 "qsave":
2163 (save,
2175 (save,
2164 [('c', 'copy', None, 'copy patch directory'),
2176 [('c', 'copy', None, 'copy patch directory'),
2165 ('n', 'name', '', 'copy directory name'),
2177 ('n', 'name', '', 'copy directory name'),
2166 ('e', 'empty', None, 'clear queue status file'),
2178 ('e', 'empty', None, 'clear queue status file'),
2167 ('f', 'force', None, 'force copy')] + commands.commitopts,
2179 ('f', 'force', None, 'force copy')] + commands.commitopts,
2168 'hg qsave [-m TEXT] [-l FILE] [-c] [-n NAME] [-e] [-f]'),
2180 'hg qsave [-m TEXT] [-l FILE] [-c] [-n NAME] [-e] [-f]'),
2169 "qselect": (select,
2181 "qselect": (select,
2170 [('n', 'none', None, _('disable all guards')),
2182 [('n', 'none', None, _('disable all guards')),
2171 ('s', 'series', None, _('list all guards in series file')),
2183 ('s', 'series', None, _('list all guards in series file')),
2172 ('', 'pop', None,
2184 ('', 'pop', None,
2173 _('pop to before first guarded applied patch')),
2185 _('pop to before first guarded applied patch')),
2174 ('', 'reapply', None, _('pop, then reapply patches'))],
2186 ('', 'reapply', None, _('pop, then reapply patches'))],
2175 'hg qselect [OPTION]... [GUARD]...'),
2187 'hg qselect [OPTION]... [GUARD]...'),
2176 "qseries":
2188 "qseries":
2177 (series,
2189 (series,
2178 [('m', 'missing', None, 'print patches not in series')] + seriesopts,
2190 [('m', 'missing', None, 'print patches not in series')] + seriesopts,
2179 'hg qseries [-ms]'),
2191 'hg qseries [-ms]'),
2180 "^strip":
2192 "^strip":
2181 (strip,
2193 (strip,
2182 [('f', 'force', None, 'force multi-head removal'),
2194 [('f', 'force', None, 'force multi-head removal'),
2183 ('b', 'backup', None, 'bundle unrelated changesets'),
2195 ('b', 'backup', None, 'bundle unrelated changesets'),
2184 ('n', 'nobackup', None, 'no backups')],
2196 ('n', 'nobackup', None, 'no backups')],
2185 'hg strip [-f] [-b] [-n] REV'),
2197 'hg strip [-f] [-b] [-n] REV'),
2186 "qtop": (top, [] + seriesopts, 'hg qtop [-s]'),
2198 "qtop": (top, [] + seriesopts, 'hg qtop [-s]'),
2187 "qunapplied": (unapplied, [] + seriesopts, 'hg qunapplied [-s] [PATCH]'),
2199 "qunapplied": (unapplied, [] + seriesopts, 'hg qunapplied [-s] [PATCH]'),
2188 }
2200 }
General Comments 0
You need to be logged in to leave comments. Login now