Mercurial > hg
comparison hgext/mq.py @ 8653:aa011d123f71
mq: initializing patchheader class directly from patch content
The patch header needs only be read in order to instantiate the class,
and as such it makes more sense to do it within the class.
author | Cédric Duval <cedricduval@free.fr> |
---|---|
date | Sat, 30 May 2009 19:18:29 +0200 |
parents | 9e055cfdd620 |
children | f6cc3638f468 |
comparison
equal
deleted
inserted
replaced
8652:64614c7e4bd9 | 8653:aa011d123f71 |
---|---|
55 | 55 |
56 def __str__(self): | 56 def __str__(self): |
57 return self.rev + ':' + self.name | 57 return self.rev + ':' + self.name |
58 | 58 |
59 class patchheader(object): | 59 class patchheader(object): |
60 def __init__(self, message, comments, user, date, haspatch): | 60 def __init__(self, pf): |
61 self.message = message | |
62 self.comments = comments | |
63 self.user = user | |
64 self.date = date | |
65 self.haspatch = haspatch | |
66 | |
67 def setuser(self, user): | |
68 if not self.setheader(['From: ', '# User '], user): | |
69 try: | |
70 patchheaderat = self.comments.index('# HG changeset patch') | |
71 self.comments.insert(patchheaderat + 1,'# User ' + user) | |
72 except ValueError: | |
73 self.comments = ['From: ' + user, ''] + self.comments | |
74 self.user = user | |
75 | |
76 def setdate(self, date): | |
77 if self.setheader(['# Date '], date): | |
78 self.date = date | |
79 | |
80 def setmessage(self, message): | |
81 if self.comments: | |
82 self._delmsg() | |
83 self.message = [message] | |
84 self.comments += self.message | |
85 | |
86 def setheader(self, prefixes, new): | |
87 '''Update all references to a field in the patch header. | |
88 If none found, add it email style.''' | |
89 res = False | |
90 for prefix in prefixes: | |
91 for i in xrange(len(self.comments)): | |
92 if self.comments[i].startswith(prefix): | |
93 self.comments[i] = prefix + new | |
94 res = True | |
95 break | |
96 return res | |
97 | |
98 def __str__(self): | |
99 if not self.comments: | |
100 return '' | |
101 return '\n'.join(self.comments) + '\n\n' | |
102 | |
103 def _delmsg(self): | |
104 '''Remove existing message, keeping the rest of the comments fields. | |
105 If comments contains 'subject: ', message will prepend | |
106 the field and a blank line.''' | |
107 if self.message: | |
108 subj = 'subject: ' + self.message[0].lower() | |
109 for i in xrange(len(self.comments)): | |
110 if subj == self.comments[i].lower(): | |
111 del self.comments[i] | |
112 self.message = self.message[2:] | |
113 break | |
114 ci = 0 | |
115 for mi in self.message: | |
116 while mi != self.comments[ci]: | |
117 ci += 1 | |
118 del self.comments[ci] | |
119 | |
120 class queue: | |
121 def __init__(self, ui, path, patchdir=None): | |
122 self.basepath = path | |
123 self.path = patchdir or os.path.join(path, "patches") | |
124 self.opener = util.opener(self.path) | |
125 self.ui = ui | |
126 self.applied_dirty = 0 | |
127 self.series_dirty = 0 | |
128 self.series_path = "series" | |
129 self.status_path = "status" | |
130 self.guards_path = "guards" | |
131 self.active_guards = None | |
132 self.guards_dirty = False | |
133 self._diffopts = None | |
134 | |
135 @util.propertycache | |
136 def applied(self): | |
137 if os.path.exists(self.join(self.status_path)): | |
138 lines = self.opener(self.status_path).read().splitlines() | |
139 return [statusentry(l) for l in lines] | |
140 return [] | |
141 | |
142 @util.propertycache | |
143 def full_series(self): | |
144 if os.path.exists(self.join(self.series_path)): | |
145 return self.opener(self.series_path).read().splitlines() | |
146 return [] | |
147 | |
148 @util.propertycache | |
149 def series(self): | |
150 self.parse_series() | |
151 return self.series | |
152 | |
153 @util.propertycache | |
154 def series_guards(self): | |
155 self.parse_series() | |
156 return self.series_guards | |
157 | |
158 def invalidate(self): | |
159 for a in 'applied full_series series series_guards'.split(): | |
160 if a in self.__dict__: | |
161 delattr(self, a) | |
162 self.applied_dirty = 0 | |
163 self.series_dirty = 0 | |
164 self.guards_dirty = False | |
165 self.active_guards = None | |
166 | |
167 def diffopts(self): | |
168 if self._diffopts is None: | |
169 self._diffopts = patch.diffopts(self.ui) | |
170 return self._diffopts | |
171 | |
172 def join(self, *p): | |
173 return os.path.join(self.path, *p) | |
174 | |
175 def find_series(self, patch): | |
176 pre = re.compile("(\s*)([^#]+)") | |
177 index = 0 | |
178 for l in self.full_series: | |
179 m = pre.match(l) | |
180 if m: | |
181 s = m.group(2) | |
182 s = s.rstrip() | |
183 if s == patch: | |
184 return index | |
185 index += 1 | |
186 return None | |
187 | |
188 guard_re = re.compile(r'\s?#([-+][^-+# \t\r\n\f][^# \t\r\n\f]*)') | |
189 | |
190 def parse_series(self): | |
191 self.series = [] | |
192 self.series_guards = [] | |
193 for l in self.full_series: | |
194 h = l.find('#') | |
195 if h == -1: | |
196 patch = l | |
197 comment = '' | |
198 elif h == 0: | |
199 continue | |
200 else: | |
201 patch = l[:h] | |
202 comment = l[h:] | |
203 patch = patch.strip() | |
204 if patch: | |
205 if patch in self.series: | |
206 raise util.Abort(_('%s appears more than once in %s') % | |
207 (patch, self.join(self.series_path))) | |
208 self.series.append(patch) | |
209 self.series_guards.append(self.guard_re.findall(comment)) | |
210 | |
211 def check_guard(self, guard): | |
212 if not guard: | |
213 return _('guard cannot be an empty string') | |
214 bad_chars = '# \t\r\n\f' | |
215 first = guard[0] | |
216 if first in '-+': | |
217 return (_('guard %r starts with invalid character: %r') % | |
218 (guard, first)) | |
219 for c in bad_chars: | |
220 if c in guard: | |
221 return _('invalid character in guard %r: %r') % (guard, c) | |
222 | |
223 def set_active(self, guards): | |
224 for guard in guards: | |
225 bad = self.check_guard(guard) | |
226 if bad: | |
227 raise util.Abort(bad) | |
228 guards = sorted(set(guards)) | |
229 self.ui.debug(_('active guards: %s\n') % ' '.join(guards)) | |
230 self.active_guards = guards | |
231 self.guards_dirty = True | |
232 | |
233 def active(self): | |
234 if self.active_guards is None: | |
235 self.active_guards = [] | |
236 try: | |
237 guards = self.opener(self.guards_path).read().split() | |
238 except IOError, err: | |
239 if err.errno != errno.ENOENT: raise | |
240 guards = [] | |
241 for i, guard in enumerate(guards): | |
242 bad = self.check_guard(guard) | |
243 if bad: | |
244 self.ui.warn('%s:%d: %s\n' % | |
245 (self.join(self.guards_path), i + 1, bad)) | |
246 else: | |
247 self.active_guards.append(guard) | |
248 return self.active_guards | |
249 | |
250 def set_guards(self, idx, guards): | |
251 for g in guards: | |
252 if len(g) < 2: | |
253 raise util.Abort(_('guard %r too short') % g) | |
254 if g[0] not in '-+': | |
255 raise util.Abort(_('guard %r starts with invalid char') % g) | |
256 bad = self.check_guard(g[1:]) | |
257 if bad: | |
258 raise util.Abort(bad) | |
259 drop = self.guard_re.sub('', self.full_series[idx]) | |
260 self.full_series[idx] = drop + ''.join([' #' + g for g in guards]) | |
261 self.parse_series() | |
262 self.series_dirty = True | |
263 | |
264 def pushable(self, idx): | |
265 if isinstance(idx, str): | |
266 idx = self.series.index(idx) | |
267 patchguards = self.series_guards[idx] | |
268 if not patchguards: | |
269 return True, None | |
270 guards = self.active() | |
271 exactneg = [g for g in patchguards if g[0] == '-' and g[1:] in guards] | |
272 if exactneg: | |
273 return False, exactneg[0] | |
274 pos = [g for g in patchguards if g[0] == '+'] | |
275 exactpos = [g for g in pos if g[1:] in guards] | |
276 if pos: | |
277 if exactpos: | |
278 return True, exactpos[0] | |
279 return False, pos | |
280 return True, '' | |
281 | |
282 def explain_pushable(self, idx, all_patches=False): | |
283 write = all_patches and self.ui.write or self.ui.warn | |
284 if all_patches or self.ui.verbose: | |
285 if isinstance(idx, str): | |
286 idx = self.series.index(idx) | |
287 pushable, why = self.pushable(idx) | |
288 if all_patches and pushable: | |
289 if why is None: | |
290 write(_('allowing %s - no guards in effect\n') % | |
291 self.series[idx]) | |
292 else: | |
293 if not why: | |
294 write(_('allowing %s - no matching negative guards\n') % | |
295 self.series[idx]) | |
296 else: | |
297 write(_('allowing %s - guarded by %r\n') % | |
298 (self.series[idx], why)) | |
299 if not pushable: | |
300 if why: | |
301 write(_('skipping %s - guarded by %r\n') % | |
302 (self.series[idx], why)) | |
303 else: | |
304 write(_('skipping %s - no matching guards\n') % | |
305 self.series[idx]) | |
306 | |
307 def save_dirty(self): | |
308 def write_list(items, path): | |
309 fp = self.opener(path, 'w') | |
310 for i in items: | |
311 fp.write("%s\n" % i) | |
312 fp.close() | |
313 if self.applied_dirty: write_list(map(str, self.applied), self.status_path) | |
314 if self.series_dirty: write_list(self.full_series, self.series_path) | |
315 if self.guards_dirty: write_list(self.active_guards, self.guards_path) | |
316 | |
317 def readheaders(self, patch): | |
318 def eatdiff(lines): | 61 def eatdiff(lines): |
319 while lines: | 62 while lines: |
320 l = lines[-1] | 63 l = lines[-1] |
321 if (l.startswith("diff -") or | 64 if (l.startswith("diff -") or |
322 l.startswith("Index:") or | 65 l.startswith("Index:") or |
330 if re.match('\s*$', l): | 73 if re.match('\s*$', l): |
331 del lines[-1] | 74 del lines[-1] |
332 else: | 75 else: |
333 break | 76 break |
334 | 77 |
335 pf = self.join(patch) | |
336 message = [] | 78 message = [] |
337 comments = [] | 79 comments = [] |
338 user = None | 80 user = None |
339 date = None | 81 date = None |
340 format = None | 82 format = None |
387 | 129 |
388 # make sure message isn't empty | 130 # make sure message isn't empty |
389 if format and format.startswith("tag") and subject: | 131 if format and format.startswith("tag") and subject: |
390 message.insert(0, "") | 132 message.insert(0, "") |
391 message.insert(0, subject) | 133 message.insert(0, subject) |
392 return patchheader(message, comments, user, date, diffstart > 1) | 134 |
135 self.message = message | |
136 self.comments = comments | |
137 self.user = user | |
138 self.date = date | |
139 self.haspatch = diffstart > 1 | |
140 | |
141 def setuser(self, user): | |
142 if not self.setheader(['From: ', '# User '], user): | |
143 try: | |
144 patchheaderat = self.comments.index('# HG changeset patch') | |
145 self.comments.insert(patchheaderat + 1,'# User ' + user) | |
146 except ValueError: | |
147 self.comments = ['From: ' + user, ''] + self.comments | |
148 self.user = user | |
149 | |
150 def setdate(self, date): | |
151 if self.setheader(['# Date '], date): | |
152 self.date = date | |
153 | |
154 def setmessage(self, message): | |
155 if self.comments: | |
156 self._delmsg() | |
157 self.message = [message] | |
158 self.comments += self.message | |
159 | |
160 def setheader(self, prefixes, new): | |
161 '''Update all references to a field in the patch header. | |
162 If none found, add it email style.''' | |
163 res = False | |
164 for prefix in prefixes: | |
165 for i in xrange(len(self.comments)): | |
166 if self.comments[i].startswith(prefix): | |
167 self.comments[i] = prefix + new | |
168 res = True | |
169 break | |
170 return res | |
171 | |
172 def __str__(self): | |
173 if not self.comments: | |
174 return '' | |
175 return '\n'.join(self.comments) + '\n\n' | |
176 | |
177 def _delmsg(self): | |
178 '''Remove existing message, keeping the rest of the comments fields. | |
179 If comments contains 'subject: ', message will prepend | |
180 the field and a blank line.''' | |
181 if self.message: | |
182 subj = 'subject: ' + self.message[0].lower() | |
183 for i in xrange(len(self.comments)): | |
184 if subj == self.comments[i].lower(): | |
185 del self.comments[i] | |
186 self.message = self.message[2:] | |
187 break | |
188 ci = 0 | |
189 for mi in self.message: | |
190 while mi != self.comments[ci]: | |
191 ci += 1 | |
192 del self.comments[ci] | |
193 | |
194 class queue: | |
195 def __init__(self, ui, path, patchdir=None): | |
196 self.basepath = path | |
197 self.path = patchdir or os.path.join(path, "patches") | |
198 self.opener = util.opener(self.path) | |
199 self.ui = ui | |
200 self.applied_dirty = 0 | |
201 self.series_dirty = 0 | |
202 self.series_path = "series" | |
203 self.status_path = "status" | |
204 self.guards_path = "guards" | |
205 self.active_guards = None | |
206 self.guards_dirty = False | |
207 self._diffopts = None | |
208 | |
209 @util.propertycache | |
210 def applied(self): | |
211 if os.path.exists(self.join(self.status_path)): | |
212 lines = self.opener(self.status_path).read().splitlines() | |
213 return [statusentry(l) for l in lines] | |
214 return [] | |
215 | |
216 @util.propertycache | |
217 def full_series(self): | |
218 if os.path.exists(self.join(self.series_path)): | |
219 return self.opener(self.series_path).read().splitlines() | |
220 return [] | |
221 | |
222 @util.propertycache | |
223 def series(self): | |
224 self.parse_series() | |
225 return self.series | |
226 | |
227 @util.propertycache | |
228 def series_guards(self): | |
229 self.parse_series() | |
230 return self.series_guards | |
231 | |
232 def invalidate(self): | |
233 for a in 'applied full_series series series_guards'.split(): | |
234 if a in self.__dict__: | |
235 delattr(self, a) | |
236 self.applied_dirty = 0 | |
237 self.series_dirty = 0 | |
238 self.guards_dirty = False | |
239 self.active_guards = None | |
240 | |
241 def diffopts(self): | |
242 if self._diffopts is None: | |
243 self._diffopts = patch.diffopts(self.ui) | |
244 return self._diffopts | |
245 | |
246 def join(self, *p): | |
247 return os.path.join(self.path, *p) | |
248 | |
249 def find_series(self, patch): | |
250 pre = re.compile("(\s*)([^#]+)") | |
251 index = 0 | |
252 for l in self.full_series: | |
253 m = pre.match(l) | |
254 if m: | |
255 s = m.group(2) | |
256 s = s.rstrip() | |
257 if s == patch: | |
258 return index | |
259 index += 1 | |
260 return None | |
261 | |
262 guard_re = re.compile(r'\s?#([-+][^-+# \t\r\n\f][^# \t\r\n\f]*)') | |
263 | |
264 def parse_series(self): | |
265 self.series = [] | |
266 self.series_guards = [] | |
267 for l in self.full_series: | |
268 h = l.find('#') | |
269 if h == -1: | |
270 patch = l | |
271 comment = '' | |
272 elif h == 0: | |
273 continue | |
274 else: | |
275 patch = l[:h] | |
276 comment = l[h:] | |
277 patch = patch.strip() | |
278 if patch: | |
279 if patch in self.series: | |
280 raise util.Abort(_('%s appears more than once in %s') % | |
281 (patch, self.join(self.series_path))) | |
282 self.series.append(patch) | |
283 self.series_guards.append(self.guard_re.findall(comment)) | |
284 | |
285 def check_guard(self, guard): | |
286 if not guard: | |
287 return _('guard cannot be an empty string') | |
288 bad_chars = '# \t\r\n\f' | |
289 first = guard[0] | |
290 if first in '-+': | |
291 return (_('guard %r starts with invalid character: %r') % | |
292 (guard, first)) | |
293 for c in bad_chars: | |
294 if c in guard: | |
295 return _('invalid character in guard %r: %r') % (guard, c) | |
296 | |
297 def set_active(self, guards): | |
298 for guard in guards: | |
299 bad = self.check_guard(guard) | |
300 if bad: | |
301 raise util.Abort(bad) | |
302 guards = sorted(set(guards)) | |
303 self.ui.debug(_('active guards: %s\n') % ' '.join(guards)) | |
304 self.active_guards = guards | |
305 self.guards_dirty = True | |
306 | |
307 def active(self): | |
308 if self.active_guards is None: | |
309 self.active_guards = [] | |
310 try: | |
311 guards = self.opener(self.guards_path).read().split() | |
312 except IOError, err: | |
313 if err.errno != errno.ENOENT: raise | |
314 guards = [] | |
315 for i, guard in enumerate(guards): | |
316 bad = self.check_guard(guard) | |
317 if bad: | |
318 self.ui.warn('%s:%d: %s\n' % | |
319 (self.join(self.guards_path), i + 1, bad)) | |
320 else: | |
321 self.active_guards.append(guard) | |
322 return self.active_guards | |
323 | |
324 def set_guards(self, idx, guards): | |
325 for g in guards: | |
326 if len(g) < 2: | |
327 raise util.Abort(_('guard %r too short') % g) | |
328 if g[0] not in '-+': | |
329 raise util.Abort(_('guard %r starts with invalid char') % g) | |
330 bad = self.check_guard(g[1:]) | |
331 if bad: | |
332 raise util.Abort(bad) | |
333 drop = self.guard_re.sub('', self.full_series[idx]) | |
334 self.full_series[idx] = drop + ''.join([' #' + g for g in guards]) | |
335 self.parse_series() | |
336 self.series_dirty = True | |
337 | |
338 def pushable(self, idx): | |
339 if isinstance(idx, str): | |
340 idx = self.series.index(idx) | |
341 patchguards = self.series_guards[idx] | |
342 if not patchguards: | |
343 return True, None | |
344 guards = self.active() | |
345 exactneg = [g for g in patchguards if g[0] == '-' and g[1:] in guards] | |
346 if exactneg: | |
347 return False, exactneg[0] | |
348 pos = [g for g in patchguards if g[0] == '+'] | |
349 exactpos = [g for g in pos if g[1:] in guards] | |
350 if pos: | |
351 if exactpos: | |
352 return True, exactpos[0] | |
353 return False, pos | |
354 return True, '' | |
355 | |
356 def explain_pushable(self, idx, all_patches=False): | |
357 write = all_patches and self.ui.write or self.ui.warn | |
358 if all_patches or self.ui.verbose: | |
359 if isinstance(idx, str): | |
360 idx = self.series.index(idx) | |
361 pushable, why = self.pushable(idx) | |
362 if all_patches and pushable: | |
363 if why is None: | |
364 write(_('allowing %s - no guards in effect\n') % | |
365 self.series[idx]) | |
366 else: | |
367 if not why: | |
368 write(_('allowing %s - no matching negative guards\n') % | |
369 self.series[idx]) | |
370 else: | |
371 write(_('allowing %s - guarded by %r\n') % | |
372 (self.series[idx], why)) | |
373 if not pushable: | |
374 if why: | |
375 write(_('skipping %s - guarded by %r\n') % | |
376 (self.series[idx], why)) | |
377 else: | |
378 write(_('skipping %s - no matching guards\n') % | |
379 self.series[idx]) | |
380 | |
381 def save_dirty(self): | |
382 def write_list(items, path): | |
383 fp = self.opener(path, 'w') | |
384 for i in items: | |
385 fp.write("%s\n" % i) | |
386 fp.close() | |
387 if self.applied_dirty: write_list(map(str, self.applied), self.status_path) | |
388 if self.series_dirty: write_list(self.full_series, self.series_path) | |
389 if self.guards_dirty: write_list(self.active_guards, self.guards_path) | |
393 | 390 |
394 def removeundo(self, repo): | 391 def removeundo(self, repo): |
395 undo = repo.sjoin('undo') | 392 undo = repo.sjoin('undo') |
396 if not os.path.exists(undo): | 393 if not os.path.exists(undo): |
397 return | 394 return |
431 raise util.Abort(_("update returned %d") % ret) | 428 raise util.Abort(_("update returned %d") % ret) |
432 n = repo.commit(None, ctx.description(), ctx.user(), force=1) | 429 n = repo.commit(None, ctx.description(), ctx.user(), force=1) |
433 if n is None: | 430 if n is None: |
434 raise util.Abort(_("repo commit failed")) | 431 raise util.Abort(_("repo commit failed")) |
435 try: | 432 try: |
436 ph = mergeq.readheaders(patch) | 433 ph = patchheader(mergeq.join(patch)) |
437 except: | 434 except: |
438 raise util.Abort(_("unable to read %s") % patch) | 435 raise util.Abort(_("unable to read %s") % patch) |
439 | 436 |
440 patchf = self.opener(patch, "w") | 437 patchf = self.opener(patch, "w") |
441 comments = str(ph) | 438 comments = str(ph) |
558 continue | 555 continue |
559 self.ui.warn(_("applying %s\n") % patchname) | 556 self.ui.warn(_("applying %s\n") % patchname) |
560 pf = os.path.join(patchdir, patchname) | 557 pf = os.path.join(patchdir, patchname) |
561 | 558 |
562 try: | 559 try: |
563 ph = self.readheaders(patchname) | 560 ph = patchheader(self.join(patchname)) |
564 except: | 561 except: |
565 self.ui.warn(_("Unable to read %s\n") % patchname) | 562 self.ui.warn(_("Unable to read %s\n") % patchname) |
566 err = 1 | 563 err = 1 |
567 break | 564 break |
568 | 565 |
1118 top = bin(top) | 1115 top = bin(top) |
1119 if repo.changelog.heads(top) != [top]: | 1116 if repo.changelog.heads(top) != [top]: |
1120 raise util.Abort(_("cannot refresh a revision with children")) | 1117 raise util.Abort(_("cannot refresh a revision with children")) |
1121 cparents = repo.changelog.parents(top) | 1118 cparents = repo.changelog.parents(top) |
1122 patchparent = self.qparents(repo, top) | 1119 patchparent = self.qparents(repo, top) |
1123 ph = self.readheaders(patchfn) | 1120 ph = patchheader(self.join(patchfn)) |
1124 | 1121 |
1125 patchf = self.opener(patchfn, 'r') | 1122 patchf = self.opener(patchfn, 'r') |
1126 | 1123 |
1127 # if the patch was a git patch, refresh it as a git patch | 1124 # if the patch was a git patch, refresh it as a git patch |
1128 for line in patchf: | 1125 for line in patchf: |
1347 | 1344 |
1348 def qseries(self, repo, missing=None, start=0, length=None, status=None, | 1345 def qseries(self, repo, missing=None, start=0, length=None, status=None, |
1349 summary=False): | 1346 summary=False): |
1350 def displayname(patchname): | 1347 def displayname(patchname): |
1351 if summary: | 1348 if summary: |
1352 ph = self.readheaders(patchname) | 1349 ph = patchheader(self.join(patchname)) |
1353 msg = ph.message | 1350 msg = ph.message |
1354 msg = msg and ': ' + msg[0] or ': ' | 1351 msg = msg and ': ' + msg[0] or ': ' |
1355 else: | 1352 else: |
1356 msg = '' | 1353 msg = '' |
1357 return '%s%s' % (patchname, msg) | 1354 return '%s%s' % (patchname, msg) |
1920 ui.write(_("no patches applied\n")) | 1917 ui.write(_("no patches applied\n")) |
1921 return 1 | 1918 return 1 |
1922 if message: | 1919 if message: |
1923 raise util.Abort(_('option "-e" incompatible with "-m" or "-l"')) | 1920 raise util.Abort(_('option "-e" incompatible with "-m" or "-l"')) |
1924 patch = q.applied[-1].name | 1921 patch = q.applied[-1].name |
1925 ph = q.readheaders(patch) | 1922 ph = patchheader(q.join(patch)) |
1926 message = ui.edit('\n'.join(ph.message), ph.user or ui.username()) | 1923 message = ui.edit('\n'.join(ph.message), ph.user or ui.username()) |
1927 setupheaderopts(ui, opts) | 1924 setupheaderopts(ui, opts) |
1928 ret = q.refresh(repo, pats, msg=message, **opts) | 1925 ret = q.refresh(repo, pats, msg=message, **opts) |
1929 q.save_dirty() | 1926 q.save_dirty() |
1930 return ret | 1927 return ret |
1982 raise util.Abort(_('qfold cannot fold already applied patch %s') % p) | 1979 raise util.Abort(_('qfold cannot fold already applied patch %s') % p) |
1983 patches.append(p) | 1980 patches.append(p) |
1984 | 1981 |
1985 for p in patches: | 1982 for p in patches: |
1986 if not message: | 1983 if not message: |
1987 ph = q.readheaders(p) | 1984 ph = patchheader(q.join(p)) |
1988 if ph.message: | 1985 if ph.message: |
1989 messages.append(ph.message) | 1986 messages.append(ph.message) |
1990 pf = q.join(p) | 1987 pf = q.join(p) |
1991 (patchsuccess, files, fuzz) = q.patch(repo, pf) | 1988 (patchsuccess, files, fuzz) = q.patch(repo, pf) |
1992 if not patchsuccess: | 1989 if not patchsuccess: |
1993 raise util.Abort(_('Error folding patch %s') % p) | 1990 raise util.Abort(_('Error folding patch %s') % p) |
1994 patch.updatedir(ui, repo, files) | 1991 patch.updatedir(ui, repo, files) |
1995 | 1992 |
1996 if not message: | 1993 if not message: |
1997 ph = q.readheaders(parent) | 1994 ph = patchheader(q.join(parent)) |
1998 message, user = ph.message, ph.user | 1995 message, user = ph.message, ph.user |
1999 for msg in messages: | 1996 for msg in messages: |
2000 message.append('* * *') | 1997 message.append('* * *') |
2001 message.extend(msg) | 1998 message.extend(msg) |
2002 message = '\n'.join(message) | 1999 message = '\n'.join(message) |
2073 else: | 2070 else: |
2074 if not q.applied: | 2071 if not q.applied: |
2075 ui.write('no patches applied\n') | 2072 ui.write('no patches applied\n') |
2076 return 1 | 2073 return 1 |
2077 patch = q.lookup('qtip') | 2074 patch = q.lookup('qtip') |
2078 ph = repo.mq.readheaders(patch) | 2075 ph = patchheader(repo.mq.join(patch)) |
2079 | 2076 |
2080 ui.write('\n'.join(ph.message) + '\n') | 2077 ui.write('\n'.join(ph.message) + '\n') |
2081 | 2078 |
2082 def lastsavename(path): | 2079 def lastsavename(path): |
2083 (directory, base) = os.path.split(path) | 2080 (directory, base) = os.path.split(path) |