Mercurial > hg > mercurial-crew-with-dirclash
comparison hgext/mq.py @ 2803:987c31e2a08c
Merge with crew
author | Matt Mackall <mpm@selenic.com> |
---|---|
date | Mon, 07 Aug 2006 16:47:06 -0500 |
parents | b550cd82f92a a3c6e7888abf |
children | 4b20daa25f15 |
comparison
equal
deleted
inserted
replaced
2802:fdc232d8a193 | 2803:987c31e2a08c |
---|---|
36 from mercurial import ui, hg, revlog, commands, util | 36 from mercurial import ui, hg, revlog, commands, util |
37 | 37 |
38 versionstr = "0.45" | 38 versionstr = "0.45" |
39 | 39 |
40 commands.norepo += " qclone qversion" | 40 commands.norepo += " qclone qversion" |
41 | |
42 class StatusEntry: | |
43 def __init__(self, rev, name=None): | |
44 if not name: | |
45 self.rev, self.name = rev.split(':') | |
46 else: | |
47 self.rev, self.name = rev, name | |
48 | |
49 def __str__(self): | |
50 return self.rev + ':' + self.name | |
41 | 51 |
42 class queue: | 52 class queue: |
43 def __init__(self, ui, path, patchdir=None): | 53 def __init__(self, ui, path, patchdir=None): |
44 self.basepath = path | 54 self.basepath = path |
45 if patchdir: | 55 if patchdir: |
58 if os.path.exists(os.path.join(self.path, self.series_path)): | 68 if os.path.exists(os.path.join(self.path, self.series_path)): |
59 self.full_series = self.opener(self.series_path).read().splitlines() | 69 self.full_series = self.opener(self.series_path).read().splitlines() |
60 self.parse_series() | 70 self.parse_series() |
61 | 71 |
62 if os.path.exists(os.path.join(self.path, self.status_path)): | 72 if os.path.exists(os.path.join(self.path, self.status_path)): |
63 self.applied = self.opener(self.status_path).read().splitlines() | 73 self.applied = [StatusEntry(l) |
74 for l in self.opener(self.status_path).read().splitlines()] | |
64 | 75 |
65 def find_series(self, patch): | 76 def find_series(self, patch): |
66 pre = re.compile("(\s*)([^#]+)") | 77 pre = re.compile("(\s*)([^#]+)") |
67 index = 0 | 78 index = 0 |
68 for l in self.full_series: | 79 for l in self.full_series: |
86 def write_list(items, path): | 97 def write_list(items, path): |
87 fp = self.opener(path, 'w') | 98 fp = self.opener(path, 'w') |
88 for i in items: | 99 for i in items: |
89 print >> fp, i | 100 print >> fp, i |
90 fp.close() | 101 fp.close() |
91 if self.applied_dirty: write_list(self.applied, self.status_path) | 102 if self.applied_dirty: write_list(map(str, self.applied), self.status_path) |
92 if self.series_dirty: write_list(self.full_series, self.series_path) | 103 if self.series_dirty: write_list(self.full_series, self.series_path) |
93 | 104 |
94 def readheaders(self, patch): | 105 def readheaders(self, patch): |
95 def eatdiff(lines): | 106 def eatdiff(lines): |
96 while lines: | 107 while lines: |
207 (p1, p2) = repo.dirstate.parents() | 218 (p1, p2) = repo.dirstate.parents() |
208 if p2 == revlog.nullid: | 219 if p2 == revlog.nullid: |
209 return p1 | 220 return p1 |
210 if len(self.applied) == 0: | 221 if len(self.applied) == 0: |
211 return None | 222 return None |
212 (top, patch) = self.applied[-1].split(':') | 223 return revlog.bin(self.applied[-1].rev) |
213 top = revlog.bin(top) | |
214 return top | |
215 pp = repo.changelog.parents(rev) | 224 pp = repo.changelog.parents(rev) |
216 if pp[1] != revlog.nullid: | 225 if pp[1] != revlog.nullid: |
217 arevs = [ x.split(':')[0] for x in self.applied ] | 226 arevs = [ x.rev for x in self.applied ] |
218 p0 = revlog.hex(pp[0]) | 227 p0 = revlog.hex(pp[0]) |
219 p1 = revlog.hex(pp[1]) | 228 p1 = revlog.hex(pp[1]) |
220 if p0 in arevs: | 229 if p0 in arevs: |
221 return pp[0] | 230 return pp[0] |
222 if p1 in arevs: | 231 if p1 in arevs: |
232 # the first patch in the queue is never a merge patch | 241 # the first patch in the queue is never a merge patch |
233 # | 242 # |
234 pname = ".hg.patches.merge.marker" | 243 pname = ".hg.patches.merge.marker" |
235 n = repo.commit(None, '[mq]: merge marker', user=None, force=1, | 244 n = repo.commit(None, '[mq]: merge marker', user=None, force=1, |
236 wlock=wlock) | 245 wlock=wlock) |
237 self.applied.append(revlog.hex(n) + ":" + pname) | 246 self.applied.append(StatusEntry(revlog.hex(n), pname)) |
238 self.applied_dirty = 1 | 247 self.applied_dirty = 1 |
239 | 248 |
240 head = self.qparents(repo) | 249 head = self.qparents(repo) |
241 | 250 |
242 for patch in series: | 251 for patch in series: |
250 self.ui.warn("patch %s is not applied\n" % patch) | 259 self.ui.warn("patch %s is not applied\n" % patch) |
251 return (1, None) | 260 return (1, None) |
252 rev = revlog.bin(info[1]) | 261 rev = revlog.bin(info[1]) |
253 (err, head) = self.mergeone(repo, mergeq, head, patch, rev, wlock) | 262 (err, head) = self.mergeone(repo, mergeq, head, patch, rev, wlock) |
254 if head: | 263 if head: |
255 self.applied.append(revlog.hex(head) + ":" + patch) | 264 self.applied.append(StatusEntry(revlog.hex(head), patch)) |
256 self.applied_dirty = 1 | 265 self.applied_dirty = 1 |
257 if err: | 266 if err: |
258 return (err, head) | 267 return (err, head) |
259 return (0, head) | 268 return (0, head) |
260 | 269 |
261 def patch(self, repo, patchfile): | 270 def patch(self, repo, patchfile): |
262 '''Apply patchfile to the working directory. | 271 '''Apply patchfile to the working directory. |
263 patchfile: file name of patch''' | 272 patchfile: file name of patch''' |
264 try: | 273 try: |
265 pp = util.find_in_path('gpatch', os.environ.get('PATH', ''), 'patch') | 274 pp = util.find_in_path('gpatch', os.environ.get('PATH', ''), 'patch') |
266 f = os.popen("%s -d '%s' -p1 --no-backup-if-mismatch < '%s'" % | 275 f = os.popen("%s -d %s -p1 --no-backup-if-mismatch < %s" % |
267 (pp, repo.root, patchfile)) | 276 (pp, util.shellquote(repo.root), util.shellquote(patchfile))) |
268 except: | 277 except: |
269 self.ui.warn("patch failed, unable to continue (try -v)\n") | 278 self.ui.warn("patch failed, unable to continue (try -v)\n") |
270 return (None, [], False) | 279 return (None, [], False) |
271 files = [] | 280 files = [] |
272 fuzz = False | 281 fuzz = False |
273 for l in f: | 282 for l in f: |
274 l = l.rstrip('\r\n'); | 283 l = l.rstrip('\r\n'); |
275 if self.ui.verbose: | 284 if self.ui.verbose: |
276 self.ui.warn(l + "\n") | 285 self.ui.warn(l + "\n") |
277 if l[:14] == 'patching file ': | 286 if l[:14] == 'patching file ': |
278 pf = os.path.normpath(l[14:]) | 287 pf = os.path.normpath(util.parse_patch_output(l)) |
279 # when patch finds a space in the file name, it puts | |
280 # single quotes around the filename. strip them off | |
281 if pf[0] == "'" and pf[-1] == "'": | |
282 pf = pf[1:-1] | |
283 if pf not in files: | 288 if pf not in files: |
284 files.append(pf) | 289 files.append(pf) |
285 printed_file = False | 290 printed_file = False |
286 file_str = l | 291 file_str = l |
287 elif l.find('with fuzz') >= 0: | 292 elif l.find('with fuzz') >= 0: |
349 | 354 |
350 if n == None: | 355 if n == None: |
351 raise util.Abort(_("repo commit failed")) | 356 raise util.Abort(_("repo commit failed")) |
352 | 357 |
353 if update_status: | 358 if update_status: |
354 self.applied.append(revlog.hex(n) + ":" + patch) | 359 self.applied.append(StatusEntry(revlog.hex(n), patch)) |
355 | 360 |
356 if patcherr: | 361 if patcherr: |
357 if not patchfound: | 362 if not patchfound: |
358 self.ui.warn("patch %s is empty\n" % patch) | 363 self.ui.warn("patch %s is empty\n" % patch) |
359 err = 0 | 364 err = 0 |
387 self.parse_series() | 392 self.parse_series() |
388 self.series_dirty = 1 | 393 self.series_dirty = 1 |
389 | 394 |
390 def check_toppatch(self, repo): | 395 def check_toppatch(self, repo): |
391 if len(self.applied) > 0: | 396 if len(self.applied) > 0: |
392 (top, patch) = self.applied[-1].split(':') | 397 top = revlog.bin(self.applied[-1].rev) |
393 top = revlog.bin(top) | |
394 pp = repo.dirstate.parents() | 398 pp = repo.dirstate.parents() |
395 if top not in pp: | 399 if top not in pp: |
396 raise util.Abort(_("queue top not at same revision as working directory")) | 400 raise util.Abort(_("queue top not at same revision as working directory")) |
397 return top | 401 return top |
398 return None | 402 return None |
419 n = repo.commit(commitfiles, | 423 n = repo.commit(commitfiles, |
420 "New patch: %s" % patch, force=True, wlock=wlock) | 424 "New patch: %s" % patch, force=True, wlock=wlock) |
421 if n == None: | 425 if n == None: |
422 raise util.Abort(_("repo commit failed")) | 426 raise util.Abort(_("repo commit failed")) |
423 self.full_series[insert:insert] = [patch] | 427 self.full_series[insert:insert] = [patch] |
424 self.applied.append(revlog.hex(n) + ":" + patch) | 428 self.applied.append(StatusEntry(revlog.hex(n), patch)) |
425 self.parse_series() | 429 self.parse_series() |
426 self.series_dirty = 1 | 430 self.series_dirty = 1 |
427 self.applied_dirty = 1 | 431 self.applied_dirty = 1 |
428 p = self.opener(patch, "w") | 432 p = self.opener(patch, "w") |
429 if msg: | 433 if msg: |
499 filerev = 0 | 503 filerev = 0 |
500 seen[f] = filerev | 504 seen[f] = filerev |
501 # we go in two steps here so the strip loop happens in a | 505 # we go in two steps here so the strip loop happens in a |
502 # sensible order. When stripping many files, this helps keep | 506 # sensible order. When stripping many files, this helps keep |
503 # our disk access patterns under control. | 507 # our disk access patterns under control. |
504 list = seen.keys() | 508 seen_list = seen.keys() |
505 list.sort() | 509 seen_list.sort() |
506 for f in list: | 510 for f in seen_list: |
507 ff = repo.file(f) | 511 ff = repo.file(f) |
508 filerev = seen[f] | 512 filerev = seen[f] |
509 if filerev != 0: | 513 if filerev != 0: |
510 if filerev in ff.nodemap: | 514 if filerev in ff.nodemap: |
511 filerev = ff.rev(filerev) | 515 filerev = ff.rev(filerev) |
533 # that we actually want to keep. changegroup will be used | 537 # that we actually want to keep. changegroup will be used |
534 # to preserve them and add them back after the truncate | 538 # to preserve them and add them back after the truncate |
535 saveheads = [] | 539 saveheads = [] |
536 savebases = {} | 540 savebases = {} |
537 | 541 |
538 tip = chlog.tip() | |
539 heads = limitheads(chlog, rev) | 542 heads = limitheads(chlog, rev) |
540 seen = {} | 543 seen = {} |
541 | 544 |
542 # search through all the heads, finding those where the revision | 545 # search through all the heads, finding those where the revision |
543 # we want to strip away is an ancestor. Also look for merges | 546 # we want to strip away is an ancestor. Also look for merges |
564 for x in r: | 567 for x in r: |
565 if chlog.rev(x) > revnum: | 568 if chlog.rev(x) > revnum: |
566 savebases[x] = 1 | 569 savebases[x] = 1 |
567 | 570 |
568 # create a changegroup for all the branches we need to keep | 571 # create a changegroup for all the branches we need to keep |
569 if backup is "all": | 572 if backup == "all": |
570 backupch = repo.changegroupsubset([rev], chlog.heads(), 'strip') | 573 backupch = repo.changegroupsubset([rev], chlog.heads(), 'strip') |
571 bundle(backupch) | 574 bundle(backupch) |
572 if saveheads: | 575 if saveheads: |
573 backupch = repo.changegroupsubset(savebases.keys(), saveheads, 'strip') | 576 backupch = repo.changegroupsubset(savebases.keys(), saveheads, 'strip') |
574 chgrpfile = bundle(backupch) | 577 chgrpfile = bundle(backupch) |
579 repo.manifest.strip(repo.manifest.rev(change[0]), revnum) | 582 repo.manifest.strip(repo.manifest.rev(change[0]), revnum) |
580 chlog.strip(revnum, revnum) | 583 chlog.strip(revnum, revnum) |
581 if saveheads: | 584 if saveheads: |
582 self.ui.status("adding branch\n") | 585 self.ui.status("adding branch\n") |
583 commands.unbundle(self.ui, repo, chgrpfile, update=False) | 586 commands.unbundle(self.ui, repo, chgrpfile, update=False) |
584 if backup is not "strip": | 587 if backup != "strip": |
585 os.unlink(chgrpfile) | 588 os.unlink(chgrpfile) |
586 | 589 |
587 def isapplied(self, patch): | 590 def isapplied(self, patch): |
588 """returns (index, rev, patch)""" | 591 """returns (index, rev, patch)""" |
589 for i in xrange(len(self.applied)): | 592 for i in xrange(len(self.applied)): |
590 p = self.applied[i] | 593 a = self.applied[i] |
591 a = p.split(':') | 594 if a.name == patch: |
592 if a[1] == patch: | 595 return (i, a.rev, a.name) |
593 return (i, a[0], a[1]) | |
594 return None | 596 return None |
595 | 597 |
596 # if the exact patch name does not exist, we try a few | 598 # if the exact patch name does not exist, we try a few |
597 # variations. If strict is passed, we try only #1 | 599 # variations. If strict is passed, we try only #1 |
598 # | 600 # |
691 s = self.series[start:end] | 693 s = self.series[start:end] |
692 if mergeq: | 694 if mergeq: |
693 ret = self.mergepatch(repo, mergeq, s, wlock) | 695 ret = self.mergepatch(repo, mergeq, s, wlock) |
694 else: | 696 else: |
695 ret = self.apply(repo, s, list, wlock=wlock) | 697 ret = self.apply(repo, s, list, wlock=wlock) |
696 top = self.applied[-1].split(':')[1] | 698 top = self.applied[-1].name |
697 if ret[0]: | 699 if ret[0]: |
698 self.ui.write("Errors during apply, please fix and refresh %s\n" % | 700 self.ui.write("Errors during apply, please fix and refresh %s\n" % |
699 top) | 701 top) |
700 else: | 702 else: |
701 self.ui.write("Now at: %s\n" % top) | 703 self.ui.write("Now at: %s\n" % top) |
728 self.ui.warn(_("no patches applied\n")) | 730 self.ui.warn(_("no patches applied\n")) |
729 sys.exit(1) | 731 sys.exit(1) |
730 | 732 |
731 if not update: | 733 if not update: |
732 parents = repo.dirstate.parents() | 734 parents = repo.dirstate.parents() |
733 rr = [ revlog.bin(x.split(':')[0]) for x in self.applied ] | 735 rr = [ revlog.bin(x.rev) for x in self.applied ] |
734 for p in parents: | 736 for p in parents: |
735 if p in rr: | 737 if p in rr: |
736 self.ui.warn("qpop: forcing dirstate update\n") | 738 self.ui.warn("qpop: forcing dirstate update\n") |
737 update = True | 739 update = True |
738 | 740 |
749 else: | 751 else: |
750 popi = info[0] + 1 | 752 popi = info[0] + 1 |
751 if popi >= end: | 753 if popi >= end: |
752 self.ui.warn("qpop: %s is already at the top\n" % patch) | 754 self.ui.warn("qpop: %s is already at the top\n" % patch) |
753 return | 755 return |
754 info = [ popi ] + self.applied[popi].split(':') | 756 info = [ popi ] + [self.applied[popi].rev, self.applied[popi].name] |
755 | 757 |
756 start = info[0] | 758 start = info[0] |
757 rev = revlog.bin(info[1]) | 759 rev = revlog.bin(info[1]) |
758 | 760 |
759 # we know there are no local changes, so we can make a simplified | 761 # we know there are no local changes, so we can make a simplified |
782 repo.dirstate.forget(a) | 784 repo.dirstate.forget(a) |
783 repo.dirstate.setparents(qp, revlog.nullid) | 785 repo.dirstate.setparents(qp, revlog.nullid) |
784 self.strip(repo, rev, update=False, backup='strip', wlock=wlock) | 786 self.strip(repo, rev, update=False, backup='strip', wlock=wlock) |
785 del self.applied[start:end] | 787 del self.applied[start:end] |
786 if len(self.applied): | 788 if len(self.applied): |
787 self.ui.write("Now at: %s\n" % self.applied[-1].split(':')[1]) | 789 self.ui.write("Now at: %s\n" % self.applied[-1].name) |
788 else: | 790 else: |
789 self.ui.write("Patch queue now empty\n") | 791 self.ui.write("Patch queue now empty\n") |
790 | 792 |
791 def diff(self, repo, files): | 793 def diff(self, repo, files): |
792 top = self.check_toppatch(repo) | 794 top = self.check_toppatch(repo) |
800 if len(self.applied) == 0: | 802 if len(self.applied) == 0: |
801 self.ui.write("No patches applied\n") | 803 self.ui.write("No patches applied\n") |
802 return | 804 return |
803 wlock = repo.wlock() | 805 wlock = repo.wlock() |
804 self.check_toppatch(repo) | 806 self.check_toppatch(repo) |
805 qp = self.qparents(repo) | 807 (top, patch) = (self.applied[-1].rev, self.applied[-1].name) |
806 (top, patch) = self.applied[-1].split(':') | |
807 top = revlog.bin(top) | 808 top = revlog.bin(top) |
808 cparents = repo.changelog.parents(top) | 809 cparents = repo.changelog.parents(top) |
809 patchparent = self.qparents(repo, top) | 810 patchparent = self.qparents(repo, top) |
810 message, comments, user, date, patchfound = self.readheaders(patch) | 811 message, comments, user, date, patchfound = self.readheaders(patch) |
811 | 812 |
897 else: | 898 else: |
898 message = msg | 899 message = msg |
899 | 900 |
900 self.strip(repo, top, update=False, backup='strip', wlock=wlock) | 901 self.strip(repo, top, update=False, backup='strip', wlock=wlock) |
901 n = repo.commit(filelist, message, changes[1], force=1, wlock=wlock) | 902 n = repo.commit(filelist, message, changes[1], force=1, wlock=wlock) |
902 self.applied[-1] = revlog.hex(n) + ':' + patch | 903 self.applied[-1] = StatusEntry(revlog.hex(n), patch) |
903 self.applied_dirty = 1 | 904 self.applied_dirty = 1 |
904 else: | 905 else: |
905 commands.dodiff(patchf, self.ui, repo, patchparent, None) | 906 commands.dodiff(patchf, self.ui, repo, patchparent, None) |
906 patchf.close() | 907 patchf.close() |
907 self.pop(repo, force=True, wlock=wlock) | 908 self.pop(repo, force=True, wlock=wlock) |
919 raise util.Abort(_("patch %s is not in series file") % patch) | 920 raise util.Abort(_("patch %s is not in series file") % patch) |
920 if not patch: | 921 if not patch: |
921 start = self.series_end() | 922 start = self.series_end() |
922 else: | 923 else: |
923 start = self.series.index(patch) + 1 | 924 start = self.series.index(patch) + 1 |
924 for p in self.series[start:]: | 925 return [(i, self.series[i]) for i in xrange(start, len(self.series))] |
925 if self.ui.verbose: | |
926 self.ui.write("%d " % self.series.index(p)) | |
927 self.ui.write("%s\n" % p) | |
928 | 926 |
929 def qseries(self, repo, missing=None, summary=False): | 927 def qseries(self, repo, missing=None, summary=False): |
930 start = self.series_end() | 928 start = self.series_end() |
931 if not missing: | 929 if not missing: |
932 for i in range(len(self.series)): | 930 for i in range(len(self.series)): |
942 msg = msg and ': ' + msg[0] or ': ' | 940 msg = msg and ': ' + msg[0] or ': ' |
943 else: | 941 else: |
944 msg = '' | 942 msg = '' |
945 self.ui.write('%s%s\n' % (patch, msg)) | 943 self.ui.write('%s%s\n' % (patch, msg)) |
946 else: | 944 else: |
947 list = [] | 945 msng_list = [] |
948 for root, dirs, files in os.walk(self.path): | 946 for root, dirs, files in os.walk(self.path): |
949 d = root[len(self.path) + 1:] | 947 d = root[len(self.path) + 1:] |
950 for f in files: | 948 for f in files: |
951 fl = os.path.join(d, f) | 949 fl = os.path.join(d, f) |
952 if (fl not in self.series and | 950 if (fl not in self.series and |
953 fl not in (self.status_path, self.series_path) | 951 fl not in (self.status_path, self.series_path) |
954 and not fl.startswith('.')): | 952 and not fl.startswith('.')): |
955 list.append(fl) | 953 msng_list.append(fl) |
956 list.sort() | 954 msng_list.sort() |
957 if list: | 955 for x in msng_list: |
958 for x in list: | 956 if self.ui.verbose: |
959 if self.ui.verbose: | 957 self.ui.write("D ") |
960 self.ui.write("D ") | 958 self.ui.write("%s\n" % x) |
961 self.ui.write("%s\n" % x) | |
962 | 959 |
963 def issaveline(self, l): | 960 def issaveline(self, l): |
964 name = l.split(':')[1] | 961 name = l.split(':')[1] |
965 if name == '.hg.patches.save.line': | 962 if name == '.hg.patches.save.line': |
966 return True | 963 return True |
985 l = lines[i].rstrip() | 982 l = lines[i].rstrip() |
986 l = l[10:].split(' ') | 983 l = l[10:].split(' ') |
987 qpp = [ hg.bin(x) for x in l ] | 984 qpp = [ hg.bin(x) for x in l ] |
988 elif datastart != None: | 985 elif datastart != None: |
989 l = lines[i].rstrip() | 986 l = lines[i].rstrip() |
990 index = l.index(':') | 987 se = StatusEntry(l) |
991 id = l[:index] | 988 file_ = se.name |
992 file = l[index + 1:] | 989 if se.rev: |
993 if id: | 990 applied.append(se) |
994 applied.append(l) | 991 series.append(file_) |
995 series.append(file) | |
996 if datastart == None: | 992 if datastart == None: |
997 self.ui.warn("No saved patch data found\n") | 993 self.ui.warn("No saved patch data found\n") |
998 return 1 | 994 return 1 |
999 self.ui.warn("restoring status: %s\n" % lines[0]) | 995 self.ui.warn("restoring status: %s\n" % lines[0]) |
1000 self.full_series = series | 996 self.full_series = series |
1041 r = self.qrepo() | 1037 r = self.qrepo() |
1042 if r: | 1038 if r: |
1043 pp = r.dirstate.parents() | 1039 pp = r.dirstate.parents() |
1044 msg += "\nDirstate: %s %s" % (hg.hex(pp[0]), hg.hex(pp[1])) | 1040 msg += "\nDirstate: %s %s" % (hg.hex(pp[0]), hg.hex(pp[1])) |
1045 msg += "\n\nPatch Data:\n" | 1041 msg += "\n\nPatch Data:\n" |
1046 text = msg + "\n".join(self.applied) + '\n' + (ar and "\n".join(ar) | 1042 text = msg + "\n".join(str(self.applied)) + '\n' + (ar and "\n".join(ar) |
1047 + '\n' or "") | 1043 + '\n' or "") |
1048 n = repo.commit(None, text, user=None, force=1) | 1044 n = repo.commit(None, text, user=None, force=1) |
1049 if not n: | 1045 if not n: |
1050 self.ui.warn("repo commit failed\n") | 1046 self.ui.warn("repo commit failed\n") |
1051 return 1 | 1047 return 1 |
1052 self.applied.append(revlog.hex(n) + ":" + '.hg.patches.save.line') | 1048 self.applied.append(StatusEntry(revlog.hex(n),'.hg.patches.save.line')) |
1053 self.applied_dirty = 1 | 1049 self.applied_dirty = 1 |
1054 | 1050 |
1055 def full_series_end(self): | 1051 def full_series_end(self): |
1056 if len(self.applied) > 0: | 1052 if len(self.applied) > 0: |
1057 (top, p) = self.applied[-1].split(':') | 1053 p = self.applied[-1].name |
1058 end = self.find_series(p) | 1054 end = self.find_series(p) |
1059 if end == None: | 1055 if end == None: |
1060 return len(self.full_series) | 1056 return len(self.full_series) |
1061 return end + 1 | 1057 return end + 1 |
1062 return 0 | 1058 return 0 |
1063 | 1059 |
1064 def series_end(self): | 1060 def series_end(self): |
1065 end = 0 | 1061 end = 0 |
1066 if len(self.applied) > 0: | 1062 if len(self.applied) > 0: |
1067 (top, p) = self.applied[-1].split(':') | 1063 p = self.applied[-1].name |
1068 try: | 1064 try: |
1069 end = self.series.index(p) | 1065 end = self.series.index(p) |
1070 except ValueError: | 1066 except ValueError: |
1071 return 0 | 1067 return 0 |
1072 return end + 1 | 1068 return end + 1 |
1082 for x in xrange(end): | 1078 for x in xrange(end): |
1083 p = self.appliedname(x) | 1079 p = self.appliedname(x) |
1084 self.ui.write("%s\n" % p) | 1080 self.ui.write("%s\n" % p) |
1085 | 1081 |
1086 def appliedname(self, index): | 1082 def appliedname(self, index): |
1087 p = self.applied[index] | 1083 pname = self.applied[index].name |
1088 pname = p.split(':')[1] | |
1089 if not self.ui.verbose: | 1084 if not self.ui.verbose: |
1090 p = pname | 1085 p = pname |
1091 else: | 1086 else: |
1092 p = str(self.series.index(pname)) + " " + p | 1087 p = str(self.series.index(pname)) + " " + p |
1093 return p | 1088 return p |
1171 repo.mq.qapplied(repo, patch) | 1166 repo.mq.qapplied(repo, patch) |
1172 return 0 | 1167 return 0 |
1173 | 1168 |
1174 def unapplied(ui, repo, patch=None, **opts): | 1169 def unapplied(ui, repo, patch=None, **opts): |
1175 """print the patches not yet applied""" | 1170 """print the patches not yet applied""" |
1176 repo.mq.unapplied(repo, patch) | 1171 for i, p in repo.mq.unapplied(repo, patch): |
1177 return 0 | 1172 if ui.verbose: |
1173 ui.write("%d " % i) | |
1174 ui.write("%s\n" % p) | |
1178 | 1175 |
1179 def qimport(ui, repo, *filename, **opts): | 1176 def qimport(ui, repo, *filename, **opts): |
1180 """import a patch""" | 1177 """import a patch""" |
1181 q = repo.mq | 1178 q = repo.mq |
1182 q.qimport(repo, filename, patch=opts['name'], | 1179 q.qimport(repo, filename, patch=opts['name'], |
1221 sr = hg.repository(ui, ui.expandpath(source)) | 1218 sr = hg.repository(ui, ui.expandpath(source)) |
1222 qbase, destrev = None, None | 1219 qbase, destrev = None, None |
1223 if sr.local(): | 1220 if sr.local(): |
1224 reposetup(ui, sr) | 1221 reposetup(ui, sr) |
1225 if sr.mq.applied: | 1222 if sr.mq.applied: |
1226 qbase = revlog.bin(sr.mq.applied[0].split(':')[0]) | 1223 qbase = revlog.bin(sr.mq.applied[0].rev) |
1227 if not hg.islocal(dest): | 1224 if not hg.islocal(dest): |
1228 destrev = sr.parents(qbase)[0] | 1225 destrev = sr.parents(qbase)[0] |
1229 ui.note(_('cloning main repo\n')) | 1226 ui.note(_('cloning main repo\n')) |
1230 sr, dr = hg.clone(ui, sr, dest, | 1227 sr, dr = hg.clone(ui, sr, dest, |
1231 pull=opts['pull'], | 1228 pull=opts['pull'], |
1284 | 1281 |
1285 -m or -l set the patch header as well as the commit message. | 1282 -m or -l set the patch header as well as the commit message. |
1286 If neither is specified, the patch header is empty and the | 1283 If neither is specified, the patch header is empty and the |
1287 commit message is 'New patch: PATCH'""" | 1284 commit message is 'New patch: PATCH'""" |
1288 q = repo.mq | 1285 q = repo.mq |
1289 message=commands.logmessage(**opts) | 1286 message = commands.logmessage(**opts) |
1290 q.new(repo, patch, msg=message, force=opts['force']) | 1287 q.new(repo, patch, msg=message, force=opts['force']) |
1291 q.save_dirty() | 1288 q.save_dirty() |
1292 return 0 | 1289 return 0 |
1293 | 1290 |
1294 def refresh(ui, repo, **opts): | 1291 def refresh(ui, repo, **opts): |
1295 """update the current patch""" | 1292 """update the current patch""" |
1296 q = repo.mq | 1293 q = repo.mq |
1297 message=commands.logmessage(**opts) | 1294 message = commands.logmessage(**opts) |
1298 if opts['edit']: | 1295 if opts['edit']: |
1299 if message: | 1296 if message: |
1300 raise util.Abort(_('option "-e" incompatible with "-m" or "-l"')) | 1297 raise util.Abort(_('option "-e" incompatible with "-m" or "-l"')) |
1301 patch = q.applied[-1].split(':')[1] | 1298 patch = q.applied[-1].name |
1302 (message, comment, user, date, hasdiff) = q.readheaders(patch) | 1299 (message, comment, user, date, hasdiff) = q.readheaders(patch) |
1303 message = ui.edit('\n'.join(message), user or ui.username()) | 1300 message = ui.edit('\n'.join(message), user or ui.username()) |
1304 q.refresh(repo, msg=message, short=opts['short']) | 1301 q.refresh(repo, msg=message, short=opts['short']) |
1305 q.save_dirty() | 1302 q.save_dirty() |
1306 return 0 | 1303 return 0 |
1329 if not files: | 1326 if not files: |
1330 raise util.Abort(_('qfold requires at least one patch name')) | 1327 raise util.Abort(_('qfold requires at least one patch name')) |
1331 if not q.check_toppatch(repo): | 1328 if not q.check_toppatch(repo): |
1332 raise util.Abort(_('No patches applied\n')) | 1329 raise util.Abort(_('No patches applied\n')) |
1333 | 1330 |
1334 message=commands.logmessage(**opts) | 1331 message = commands.logmessage(**opts) |
1335 if opts['edit']: | 1332 if opts['edit']: |
1336 if message: | 1333 if message: |
1337 raise util.Abort(_('option "-e" incompatible with "-m" or "-l"')) | 1334 raise util.Abort(_('option "-e" incompatible with "-m" or "-l"')) |
1338 | 1335 |
1339 parent = q.lookup('qtip') | 1336 parent = q.lookup('qtip') |
1340 patches = [] | 1337 patches = [] |
1341 messages = [] | 1338 messages = [] |
1342 for f in files: | 1339 for f in files: |
1343 patch = q.lookup(f) | 1340 patch = q.lookup(f) |
1344 if patch in patches or patch == parent: | 1341 if patch in patches or patch == parent: |
1345 self.ui.warn(_('Skipping already folded patch %s') % patch) | 1342 ui.warn(_('Skipping already folded patch %s') % patch) |
1346 if q.isapplied(patch): | 1343 if q.isapplied(patch): |
1347 raise util.Abort(_('qfold cannot fold already applied patch %s') % patch) | 1344 raise util.Abort(_('qfold cannot fold already applied patch %s') % patch) |
1348 patches.append(patch) | 1345 patches.append(patch) |
1349 | 1346 |
1350 for patch in patches: | 1347 for patch in patches: |
1386 message = repo.mq.readheaders(patch)[0] | 1383 message = repo.mq.readheaders(patch)[0] |
1387 | 1384 |
1388 ui.write('\n'.join(message) + '\n') | 1385 ui.write('\n'.join(message) + '\n') |
1389 | 1386 |
1390 def lastsavename(path): | 1387 def lastsavename(path): |
1391 (dir, base) = os.path.split(path) | 1388 (directory, base) = os.path.split(path) |
1392 names = os.listdir(dir) | 1389 names = os.listdir(directory) |
1393 namere = re.compile("%s.([0-9]+)" % base) | 1390 namere = re.compile("%s.([0-9]+)" % base) |
1394 max = None | 1391 maxindex = None |
1395 maxname = None | 1392 maxname = None |
1396 for f in names: | 1393 for f in names: |
1397 m = namere.match(f) | 1394 m = namere.match(f) |
1398 if m: | 1395 if m: |
1399 index = int(m.group(1)) | 1396 index = int(m.group(1)) |
1400 if max == None or index > max: | 1397 if maxindex == None or index > maxindex: |
1401 max = index | 1398 maxindex = index |
1402 maxname = f | 1399 maxname = f |
1403 if maxname: | 1400 if maxname: |
1404 return (os.path.join(dir, maxname), max) | 1401 return (os.path.join(directory, maxname), maxindex) |
1405 return (None, None) | 1402 return (None, None) |
1406 | 1403 |
1407 def savename(path): | 1404 def savename(path): |
1408 (last, index) = lastsavename(path) | 1405 (last, index) = lastsavename(path) |
1409 if last is None: | 1406 if last is None: |
1480 q.parse_series() | 1477 q.parse_series() |
1481 q.series_dirty = 1 | 1478 q.series_dirty = 1 |
1482 | 1479 |
1483 info = q.isapplied(patch) | 1480 info = q.isapplied(patch) |
1484 if info: | 1481 if info: |
1485 q.applied[info[0]] = info[1] + ':' + name | 1482 q.applied[info[0]] = StatusEntry(info[1], name) |
1486 q.applied_dirty = 1 | 1483 q.applied_dirty = 1 |
1487 | 1484 |
1488 util.rename(os.path.join(q.path, patch), absdest) | 1485 util.rename(os.path.join(q.path, patch), absdest) |
1489 r = q.qrepo() | 1486 r = q.qrepo() |
1490 if r: | 1487 if r: |
1506 return 0 | 1503 return 0 |
1507 | 1504 |
1508 def save(ui, repo, **opts): | 1505 def save(ui, repo, **opts): |
1509 """save current queue state""" | 1506 """save current queue state""" |
1510 q = repo.mq | 1507 q = repo.mq |
1511 message=commands.logmessage(**opts) | 1508 message = commands.logmessage(**opts) |
1512 ret = q.save(repo, msg=message) | 1509 ret = q.save(repo, msg=message) |
1513 if ret: | 1510 if ret: |
1514 return ret | 1511 return ret |
1515 q.save_dirty() | 1512 q.save_dirty() |
1516 if opts['copy']: | 1513 if opts['copy']: |
1561 | 1558 |
1562 q = self.mq | 1559 q = self.mq |
1563 if not q.applied: | 1560 if not q.applied: |
1564 return tagscache | 1561 return tagscache |
1565 | 1562 |
1566 mqtags = [patch.split(':') for patch in q.applied] | 1563 mqtags = [(patch.rev, patch.name) for patch in q.applied] |
1567 mqtags.append((mqtags[-1][0], 'qtip')) | 1564 mqtags.append((mqtags[-1][0], 'qtip')) |
1568 mqtags.append((mqtags[0][0], 'qbase')) | 1565 mqtags.append((mqtags[0][0], 'qbase')) |
1569 for patch in mqtags: | 1566 for patch in mqtags: |
1570 if patch[1] in tagscache: | 1567 if patch[1] in tagscache: |
1571 self.ui.warn('Tag %s overrides mq patch of the same name\n' % patch[1]) | 1568 self.ui.warn('Tag %s overrides mq patch of the same name\n' % patch[1]) |