115 testedwith = 'ships-with-hg-core' |
115 testedwith = 'ships-with-hg-core' |
116 |
116 |
117 configtable = {} |
117 configtable = {} |
118 configitem = registrar.configitem(configtable) |
118 configitem = registrar.configitem(configtable) |
119 |
119 |
120 configitem('mq', 'git', |
120 configitem( |
121 default='auto', |
121 'mq', 'git', default='auto', |
122 ) |
122 ) |
123 configitem('mq', 'keepchanges', |
123 configitem( |
124 default=False, |
124 'mq', 'keepchanges', default=False, |
125 ) |
125 ) |
126 configitem('mq', 'plain', |
126 configitem( |
127 default=False, |
127 'mq', 'plain', default=False, |
128 ) |
128 ) |
129 configitem('mq', 'secret', |
129 configitem( |
130 default=False, |
130 'mq', 'secret', default=False, |
131 ) |
131 ) |
132 |
132 |
133 # force load strip extension formerly included in mq and import some utility |
133 # force load strip extension formerly included in mq and import some utility |
134 try: |
134 try: |
135 stripext = extensions.find('strip') |
135 stripext = extensions.find('strip') |
137 # note: load is lazy so we could avoid the try-except, |
137 # note: load is lazy so we could avoid the try-except, |
138 # but I (marmoute) prefer this explicit code. |
138 # but I (marmoute) prefer this explicit code. |
139 class dummyui(object): |
139 class dummyui(object): |
140 def debug(self, msg): |
140 def debug(self, msg): |
141 pass |
141 pass |
|
142 |
142 def log(self, event, msgfmt, *msgargs, **opts): |
143 def log(self, event, msgfmt, *msgargs, **opts): |
143 pass |
144 pass |
|
145 |
144 stripext = extensions.load(dummyui(), 'strip', '') |
146 stripext = extensions.load(dummyui(), 'strip', '') |
145 |
147 |
146 strip = stripext.strip |
148 strip = stripext.strip |
|
149 |
147 |
150 |
148 def checksubstate(repo, baserev=None): |
151 def checksubstate(repo, baserev=None): |
149 '''return list of subrepos at a different revision than substate. |
152 '''return list of subrepos at a different revision than substate. |
150 Abort if any subrepos have uncommitted changes.''' |
153 Abort if any subrepos have uncommitted changes.''' |
151 inclsubs = [] |
154 inclsubs = [] |
158 wctx.sub(s).bailifchanged(True) |
161 wctx.sub(s).bailifchanged(True) |
159 if s not in bctx.substate or bctx.sub(s).dirty(): |
162 if s not in bctx.substate or bctx.sub(s).dirty(): |
160 inclsubs.append(s) |
163 inclsubs.append(s) |
161 return inclsubs |
164 return inclsubs |
162 |
165 |
|
166 |
163 # Patch names looks like unix-file names. |
167 # Patch names looks like unix-file names. |
164 # They must be joinable with queue directory and result in the patch path. |
168 # They must be joinable with queue directory and result in the patch path. |
165 normname = util.normpath |
169 normname = util.normpath |
166 |
170 |
|
171 |
167 class statusentry(object): |
172 class statusentry(object): |
168 def __init__(self, node, name): |
173 def __init__(self, node, name): |
169 self.node, self.name = node, name |
174 self.node, self.name = node, name |
170 |
175 |
171 def __bytes__(self): |
176 def __bytes__(self): |
172 return hex(self.node) + ':' + self.name |
177 return hex(self.node) + ':' + self.name |
173 |
178 |
174 __str__ = encoding.strmethod(__bytes__) |
179 __str__ = encoding.strmethod(__bytes__) |
175 __repr__ = encoding.strmethod(__bytes__) |
180 __repr__ = encoding.strmethod(__bytes__) |
176 |
181 |
|
182 |
177 # The order of the headers in 'hg export' HG patches: |
183 # The order of the headers in 'hg export' HG patches: |
178 HGHEADERS = [ |
184 HGHEADERS = [ |
179 # '# HG changeset patch', |
185 # '# HG changeset patch', |
180 '# User ', |
186 '# User ', |
181 '# Date ', |
187 '# Date ', |
182 '# ', |
188 '# ', |
183 '# Branch ', |
189 '# Branch ', |
184 '# Node ID ', |
190 '# Node ID ', |
185 '# Parent ', # can occur twice for merges - but that is not relevant for mq |
191 '# Parent ', # can occur twice for merges - but that is not relevant for mq |
186 ] |
192 ] |
187 # The order of headers in plain 'mail style' patches: |
193 # The order of headers in plain 'mail style' patches: |
188 PLAINHEADERS = { |
194 PLAINHEADERS = { |
189 'from': 0, |
195 'from': 0, |
190 'date': 1, |
196 'date': 1, |
191 'subject': 2, |
197 'subject': 2, |
192 } |
198 } |
|
199 |
193 |
200 |
194 def inserthgheader(lines, header, value): |
201 def inserthgheader(lines, header, value): |
195 """Assuming lines contains a HG patch header, add a header line with value. |
202 """Assuming lines contains a HG patch header, add a header line with value. |
196 >>> try: inserthgheader([], b'# Date ', b'z') |
203 >>> try: inserthgheader([], b'# Date ', b'z') |
197 ... except ValueError as inst: print("oops") |
204 ... except ValueError as inst: print("oops") |
299 nodeid = None |
311 nodeid = None |
300 diffstart = 0 |
312 diffstart = 0 |
301 |
313 |
302 for line in open(pf, 'rb'): |
314 for line in open(pf, 'rb'): |
303 line = line.rstrip() |
315 line = line.rstrip() |
304 if (line.startswith('diff --git') |
316 if line.startswith('diff --git') or ( |
305 or (diffstart and line.startswith('+++ '))): |
317 diffstart and line.startswith('+++ ') |
|
318 ): |
306 diffstart = 2 |
319 diffstart = 2 |
307 break |
320 break |
308 diffstart = 0 # reset |
321 diffstart = 0 # reset |
309 if line.startswith("--- "): |
322 if line.startswith("--- "): |
310 diffstart = 1 |
323 diffstart = 1 |
311 continue |
324 continue |
312 elif format == "hgpatch": |
325 elif format == "hgpatch": |
313 # parse values when importing the result of an hg export |
326 # parse values when importing the result of an hg export |
314 if line.startswith("# User "): |
327 if line.startswith("# User "): |
315 user = line[7:] |
328 user = line[7:] |
316 elif line.startswith("# Date "): |
329 elif line.startswith("# Date "): |
317 date = line[7:] |
330 date = line[7:] |
318 elif line.startswith("# Parent "): |
331 elif line.startswith("# Parent "): |
319 parent = line[9:].lstrip() # handle double trailing space |
332 parent = line[9:].lstrip() # handle double trailing space |
320 elif line.startswith("# Branch "): |
333 elif line.startswith("# Branch "): |
321 branch = line[9:] |
334 branch = line[9:] |
322 elif line.startswith("# Node ID "): |
335 elif line.startswith("# Node ID "): |
323 nodeid = line[10:] |
336 nodeid = line[10:] |
324 elif not line.startswith("# ") and line: |
337 elif not line.startswith("# ") and line: |
325 message.append(line) |
338 message.append(line) |
326 format = None |
339 format = None |
327 elif line == '# HG changeset patch': |
340 elif line == '# HG changeset patch': |
328 message = [] |
341 message = [] |
329 format = "hgpatch" |
342 format = "hgpatch" |
330 elif (format != "tagdone" and (line.startswith("Subject: ") or |
343 elif format != "tagdone" and ( |
331 line.startswith("subject: "))): |
344 line.startswith("Subject: ") or line.startswith("subject: ") |
|
345 ): |
332 subject = line[9:] |
346 subject = line[9:] |
333 format = "tag" |
347 format = "tag" |
334 elif (format != "tagdone" and (line.startswith("From: ") or |
348 elif format != "tagdone" and ( |
335 line.startswith("from: "))): |
349 line.startswith("From: ") or line.startswith("from: ") |
|
350 ): |
336 user = line[6:] |
351 user = line[6:] |
337 format = "tag" |
352 format = "tag" |
338 elif (format != "tagdone" and (line.startswith("Date: ") or |
353 elif format != "tagdone" and ( |
339 line.startswith("date: "))): |
354 line.startswith("Date: ") or line.startswith("date: ") |
|
355 ): |
340 date = line[6:] |
356 date = line[6:] |
341 format = "tag" |
357 format = "tag" |
342 elif format == "tag" and line == "": |
358 elif format == "tag" and line == "": |
343 # when looking for tags (subject: from: etc) they |
359 # when looking for tags (subject: from: etc) they |
344 # end once you find a blank line in the source |
360 # end once you find a blank line in the source |
546 self.activeguards = None |
571 self.activeguards = None |
547 |
572 |
548 def diffopts(self, opts=None, patchfn=None, plain=False): |
573 def diffopts(self, opts=None, patchfn=None, plain=False): |
549 """Return diff options tweaked for this mq use, possibly upgrading to |
574 """Return diff options tweaked for this mq use, possibly upgrading to |
550 git format, and possibly plain and without lossy options.""" |
575 git format, and possibly plain and without lossy options.""" |
551 diffopts = patchmod.difffeatureopts(self.ui, opts, |
576 diffopts = patchmod.difffeatureopts( |
552 git=True, whitespace=not plain, formatchanging=not plain) |
577 self.ui, |
|
578 opts, |
|
579 git=True, |
|
580 whitespace=not plain, |
|
581 formatchanging=not plain, |
|
582 ) |
553 if self.gitmode == 'auto': |
583 if self.gitmode == 'auto': |
554 diffopts.upgrade = True |
584 diffopts.upgrade = True |
555 elif self.gitmode == 'keep': |
585 elif self.gitmode == 'keep': |
556 pass |
586 pass |
557 elif self.gitmode in ('yes', 'no'): |
587 elif self.gitmode in ('yes', 'no'): |
558 diffopts.git = self.gitmode == 'yes' |
588 diffopts.git = self.gitmode == 'yes' |
559 else: |
589 else: |
560 raise error.Abort(_('mq.git option can be auto/keep/yes/no' |
590 raise error.Abort( |
561 ' got %s') % self.gitmode) |
591 _('mq.git option can be auto/keep/yes/no' ' got %s') |
|
592 % self.gitmode |
|
593 ) |
562 if patchfn: |
594 if patchfn: |
563 diffopts = self.patchopts(diffopts, patchfn) |
595 diffopts = self.patchopts(diffopts, patchfn) |
564 return diffopts |
596 return diffopts |
565 |
597 |
566 def patchopts(self, diffopts, *patches): |
598 def patchopts(self, diffopts, *patches): |
570 diffopts = diffopts.copy() |
602 diffopts = diffopts.copy() |
571 if not diffopts.git and self.gitmode == 'keep': |
603 if not diffopts.git and self.gitmode == 'keep': |
572 for patchfn in patches: |
604 for patchfn in patches: |
573 patchf = self.opener(patchfn, 'r') |
605 patchf = self.opener(patchfn, 'r') |
574 # if the patch was a git patch, refresh it as a git patch |
606 # if the patch was a git patch, refresh it as a git patch |
575 diffopts.git = any(line.startswith('diff --git') |
607 diffopts.git = any( |
576 for line in patchf) |
608 line.startswith('diff --git') for line in patchf |
|
609 ) |
577 patchf.close() |
610 patchf.close() |
578 return diffopts |
611 return diffopts |
579 |
612 |
580 def join(self, *p): |
613 def join(self, *p): |
581 return os.path.join(self.path, *p) |
614 return os.path.join(self.path, *p) |
582 |
615 |
583 def findseries(self, patch): |
616 def findseries(self, patch): |
584 def matchpatch(l): |
617 def matchpatch(l): |
585 l = l.split('#', 1)[0] |
618 l = l.split('#', 1)[0] |
586 return l.strip() == patch |
619 return l.strip() == patch |
|
620 |
587 for index, l in enumerate(self.fullseries): |
621 for index, l in enumerate(self.fullseries): |
588 if matchpatch(l): |
622 if matchpatch(l): |
589 return index |
623 return index |
590 return None |
624 return None |
591 |
625 |
605 patch = l[:h] |
639 patch = l[:h] |
606 comment = l[h:] |
640 comment = l[h:] |
607 patch = patch.strip() |
641 patch = patch.strip() |
608 if patch: |
642 if patch: |
609 if patch in self.series: |
643 if patch in self.series: |
610 raise error.Abort(_('%s appears more than once in %s') % |
644 raise error.Abort( |
611 (patch, self.join(self.seriespath))) |
645 _('%s appears more than once in %s') |
|
646 % (patch, self.join(self.seriespath)) |
|
647 ) |
612 self.series.append(patch) |
648 self.series.append(patch) |
613 self.seriesguards.append(self.guard_re.findall(comment)) |
649 self.seriesguards.append(self.guard_re.findall(comment)) |
614 |
650 |
615 def checkguard(self, guard): |
651 def checkguard(self, guard): |
616 if not guard: |
652 if not guard: |
617 return _('guard cannot be an empty string') |
653 return _('guard cannot be an empty string') |
618 bad_chars = '# \t\r\n\f' |
654 bad_chars = '# \t\r\n\f' |
619 first = guard[0] |
655 first = guard[0] |
620 if first in '-+': |
656 if first in '-+': |
621 return (_('guard %r starts with invalid character: %r') % |
657 return _('guard %r starts with invalid character: %r') % ( |
622 (guard, first)) |
658 guard, |
|
659 first, |
|
660 ) |
623 for c in bad_chars: |
661 for c in bad_chars: |
624 if c in guard: |
662 if c in guard: |
625 return _('invalid character in guard %r: %r') % (guard, c) |
663 return _('invalid character in guard %r: %r') % (guard, c) |
626 |
664 |
627 def setactive(self, guards): |
665 def setactive(self, guards): |
695 if isinstance(idx, bytes): |
735 if isinstance(idx, bytes): |
696 idx = self.series.index(idx) |
736 idx = self.series.index(idx) |
697 pushable, why = self.pushable(idx) |
737 pushable, why = self.pushable(idx) |
698 if all_patches and pushable: |
738 if all_patches and pushable: |
699 if why is None: |
739 if why is None: |
700 write(_('allowing %s - no guards in effect\n') % |
740 write( |
701 self.series[idx]) |
741 _('allowing %s - no guards in effect\n') |
|
742 % self.series[idx] |
|
743 ) |
702 else: |
744 else: |
703 if not why: |
745 if not why: |
704 write(_('allowing %s - no matching negative guards\n') % |
746 write( |
705 self.series[idx]) |
747 _('allowing %s - no matching negative guards\n') |
|
748 % self.series[idx] |
|
749 ) |
706 else: |
750 else: |
707 write(_('allowing %s - guarded by %s\n') % |
751 write( |
708 (self.series[idx], why)) |
752 _('allowing %s - guarded by %s\n') |
|
753 % (self.series[idx], why) |
|
754 ) |
709 if not pushable: |
755 if not pushable: |
710 if why: |
756 if why: |
711 write(_('skipping %s - guarded by %s\n') % |
757 write( |
712 (self.series[idx], why)) |
758 _('skipping %s - guarded by %s\n') |
|
759 % (self.series[idx], why) |
|
760 ) |
713 else: |
761 else: |
714 write(_('skipping %s - no matching guards\n') % |
762 write( |
715 self.series[idx]) |
763 _('skipping %s - no matching guards\n') |
|
764 % self.series[idx] |
|
765 ) |
716 |
766 |
717 def savedirty(self): |
767 def savedirty(self): |
718 def writelist(items, path): |
768 def writelist(items, path): |
719 fp = self.opener(path, 'wb') |
769 fp = self.opener(path, 'wb') |
720 for i in items: |
770 for i in items: |
721 fp.write("%s\n" % i) |
771 fp.write("%s\n" % i) |
722 fp.close() |
772 fp.close() |
|
773 |
723 if self.applieddirty: |
774 if self.applieddirty: |
724 writelist(map(bytes, self.applied), self.statuspath) |
775 writelist(map(bytes, self.applied), self.statuspath) |
725 self.applieddirty = False |
776 self.applieddirty = False |
726 if self.seriesdirty: |
777 if self.seriesdirty: |
727 writelist(self.fullseries, self.seriespath) |
778 writelist(self.fullseries, self.seriespath) |
740 if not os.path.exists(undo): |
791 if not os.path.exists(undo): |
741 return |
792 return |
742 try: |
793 try: |
743 os.unlink(undo) |
794 os.unlink(undo) |
744 except OSError as inst: |
795 except OSError as inst: |
745 self.ui.warn(_('error removing undo: %s\n') % |
796 self.ui.warn( |
746 stringutil.forcebytestr(inst)) |
797 _('error removing undo: %s\n') % stringutil.forcebytestr(inst) |
|
798 ) |
747 |
799 |
748 def backup(self, repo, files, copy=False): |
800 def backup(self, repo, files, copy=False): |
749 # backup local changes in --force case |
801 # backup local changes in --force case |
750 for f in sorted(files): |
802 for f in sorted(files): |
751 absf = repo.wjoin(f) |
803 absf = repo.wjoin(f) |
752 if os.path.lexists(absf): |
804 if os.path.lexists(absf): |
753 absorig = scmutil.backuppath(self.ui, repo, f) |
805 absorig = scmutil.backuppath(self.ui, repo, f) |
754 self.ui.note(_('saving current version of %s as %s\n') % |
806 self.ui.note( |
755 (f, os.path.relpath(absorig))) |
807 _('saving current version of %s as %s\n') |
|
808 % (f, os.path.relpath(absorig)) |
|
809 ) |
756 |
810 |
757 if copy: |
811 if copy: |
758 util.copyfile(absf, absorig) |
812 util.copyfile(absf, absorig) |
759 else: |
813 else: |
760 util.rename(absf, absorig) |
814 util.rename(absf, absorig) |
761 |
815 |
762 def printdiff(self, repo, diffopts, node1, node2=None, files=None, |
816 def printdiff( |
763 fp=None, changes=None, opts=None): |
817 self, |
|
818 repo, |
|
819 diffopts, |
|
820 node1, |
|
821 node2=None, |
|
822 files=None, |
|
823 fp=None, |
|
824 changes=None, |
|
825 opts=None, |
|
826 ): |
764 if opts is None: |
827 if opts is None: |
765 opts = {} |
828 opts = {} |
766 stat = opts.get('stat') |
829 stat = opts.get('stat') |
767 m = scmutil.match(repo[node1], files, opts) |
830 m = scmutil.match(repo[node1], files, opts) |
768 logcmdutil.diffordiffstat(self.ui, repo, diffopts, node1, node2, m, |
831 logcmdutil.diffordiffstat( |
769 changes, stat, fp) |
832 self.ui, repo, diffopts, node1, node2, m, changes, stat, fp |
|
833 ) |
770 |
834 |
771 def mergeone(self, repo, mergeq, head, patch, rev, diffopts): |
835 def mergeone(self, repo, mergeq, head, patch, rev, diffopts): |
772 # first try just applying the patch |
836 # first try just applying the patch |
773 (err, n) = self.apply(repo, [patch], update_status=False, |
837 (err, n) = self.apply( |
774 strict=True, merge=rev) |
838 repo, [patch], update_status=False, strict=True, merge=rev |
|
839 ) |
775 |
840 |
776 if err == 0: |
841 if err == 0: |
777 return (err, n) |
842 return (err, n) |
778 |
843 |
779 if n is None: |
844 if n is None: |
870 def patch(self, repo, patchfile): |
935 def patch(self, repo, patchfile): |
871 '''Apply patchfile to the working directory. |
936 '''Apply patchfile to the working directory. |
872 patchfile: name of patch file''' |
937 patchfile: name of patch file''' |
873 files = set() |
938 files = set() |
874 try: |
939 try: |
875 fuzz = patchmod.patch(self.ui, repo, patchfile, strip=1, |
940 fuzz = patchmod.patch( |
876 files=files, eolmode=None) |
941 self.ui, repo, patchfile, strip=1, files=files, eolmode=None |
|
942 ) |
877 return (True, list(files), fuzz) |
943 return (True, list(files), fuzz) |
878 except Exception as inst: |
944 except Exception as inst: |
879 self.ui.note(stringutil.forcebytestr(inst) + '\n') |
945 self.ui.note(stringutil.forcebytestr(inst) + '\n') |
880 if not self.ui.verbose: |
946 if not self.ui.verbose: |
881 self.ui.warn(_("patch failed, unable to continue (try -v)\n")) |
947 self.ui.warn(_("patch failed, unable to continue (try -v)\n")) |
882 self.ui.traceback() |
948 self.ui.traceback() |
883 return (False, list(files), False) |
949 return (False, list(files), False) |
884 |
950 |
885 def apply(self, repo, series, list=False, update_status=True, |
951 def apply( |
886 strict=False, patchdir=None, merge=None, all_files=None, |
952 self, |
887 tobackup=None, keepchanges=False): |
953 repo, |
|
954 series, |
|
955 list=False, |
|
956 update_status=True, |
|
957 strict=False, |
|
958 patchdir=None, |
|
959 merge=None, |
|
960 all_files=None, |
|
961 tobackup=None, |
|
962 keepchanges=False, |
|
963 ): |
888 wlock = lock = tr = None |
964 wlock = lock = tr = None |
889 try: |
965 try: |
890 wlock = repo.wlock() |
966 wlock = repo.wlock() |
891 lock = repo.lock() |
967 lock = repo.lock() |
892 tr = repo.transaction("qpush") |
968 tr = repo.transaction("qpush") |
893 try: |
969 try: |
894 ret = self._apply(repo, series, list, update_status, |
970 ret = self._apply( |
895 strict, patchdir, merge, all_files=all_files, |
971 repo, |
896 tobackup=tobackup, keepchanges=keepchanges) |
972 series, |
|
973 list, |
|
974 update_status, |
|
975 strict, |
|
976 patchdir, |
|
977 merge, |
|
978 all_files=all_files, |
|
979 tobackup=tobackup, |
|
980 keepchanges=keepchanges, |
|
981 ) |
897 tr.close() |
982 tr.close() |
898 self.savedirty() |
983 self.savedirty() |
899 return ret |
984 return ret |
900 except AbortNoCleanup: |
985 except AbortNoCleanup: |
901 tr.close() |
986 tr.close() |
902 self.savedirty() |
987 self.savedirty() |
903 raise |
988 raise |
904 except: # re-raises |
989 except: # re-raises |
905 try: |
990 try: |
906 tr.abort() |
991 tr.abort() |
907 finally: |
992 finally: |
908 self.invalidate() |
993 self.invalidate() |
909 raise |
994 raise |
910 finally: |
995 finally: |
911 release(tr, lock, wlock) |
996 release(tr, lock, wlock) |
912 self.removeundo(repo) |
997 self.removeundo(repo) |
913 |
998 |
914 def _apply(self, repo, series, list=False, update_status=True, |
999 def _apply( |
915 strict=False, patchdir=None, merge=None, all_files=None, |
1000 self, |
916 tobackup=None, keepchanges=False): |
1001 repo, |
|
1002 series, |
|
1003 list=False, |
|
1004 update_status=True, |
|
1005 strict=False, |
|
1006 patchdir=None, |
|
1007 merge=None, |
|
1008 all_files=None, |
|
1009 tobackup=None, |
|
1010 keepchanges=False, |
|
1011 ): |
917 """returns (error, hash) |
1012 """returns (error, hash) |
918 |
1013 |
919 error = 1 for unable to read, 2 for patch failed, 3 for patch |
1014 error = 1 for unable to read, 2 for patch failed, 3 for patch |
920 fuzz. tobackup is None or a set of files to backup before they |
1015 fuzz. tobackup is None or a set of files to backup before they |
921 are modified by a patch. |
1016 are modified by a patch. |
955 touched = patchmod.changedfiles(self.ui, repo, pf) |
1050 touched = patchmod.changedfiles(self.ui, repo, pf) |
956 touched = set(touched) & tobackup |
1051 touched = set(touched) & tobackup |
957 if touched and keepchanges: |
1052 if touched and keepchanges: |
958 raise AbortNoCleanup( |
1053 raise AbortNoCleanup( |
959 _("conflicting local changes found"), |
1054 _("conflicting local changes found"), |
960 hint=_("did you forget to qrefresh?")) |
1055 hint=_("did you forget to qrefresh?"), |
|
1056 ) |
961 self.backup(repo, touched, copy=True) |
1057 self.backup(repo, touched, copy=True) |
962 tobackup = tobackup - touched |
1058 tobackup = tobackup - touched |
963 (patcherr, files, fuzz) = self.patch(repo, pf) |
1059 (patcherr, files, fuzz) = self.patch(repo, pf) |
964 if all_files is not None: |
1060 if all_files is not None: |
965 all_files.update(files) |
1061 all_files.update(files) |
987 |
1083 |
988 if all_files and '.hgsubstate' in all_files: |
1084 if all_files and '.hgsubstate' in all_files: |
989 wctx = repo[None] |
1085 wctx = repo[None] |
990 pctx = repo['.'] |
1086 pctx = repo['.'] |
991 overwrite = False |
1087 overwrite = False |
992 mergedsubstate = subrepoutil.submerge(repo, pctx, wctx, wctx, |
1088 mergedsubstate = subrepoutil.submerge( |
993 overwrite) |
1089 repo, pctx, wctx, wctx, overwrite |
|
1090 ) |
994 files += mergedsubstate.keys() |
1091 files += mergedsubstate.keys() |
995 |
1092 |
996 match = scmutil.matchfiles(repo, files or []) |
1093 match = scmutil.matchfiles(repo, files or []) |
997 oldtip = repo.changelog.tip() |
1094 oldtip = repo.changelog.tip() |
998 n = newcommit(repo, None, message, ph.user, ph.date, match=match, |
1095 n = newcommit( |
999 force=True) |
1096 repo, None, message, ph.user, ph.date, match=match, force=True |
|
1097 ) |
1000 if repo.changelog.tip() == oldtip: |
1098 if repo.changelog.tip() == oldtip: |
1001 raise error.Abort(_("qpush exactly duplicates child changeset")) |
1099 raise error.Abort(_("qpush exactly duplicates child changeset")) |
1002 if n is None: |
1100 if n is None: |
1003 raise error.Abort(_("repository commit failed")) |
1101 raise error.Abort(_("repository commit failed")) |
1004 |
1102 |
1005 if update_status: |
1103 if update_status: |
1006 self.applied.append(statusentry(n, patchname)) |
1104 self.applied.append(statusentry(n, patchname)) |
1007 |
1105 |
1008 if patcherr: |
1106 if patcherr: |
1009 self.ui.warn(_("patch failed, rejects left in working " |
1107 self.ui.warn( |
1010 "directory\n")) |
1108 _("patch failed, rejects left in working " "directory\n") |
|
1109 ) |
1011 err = 2 |
1110 err = 2 |
1012 break |
1111 break |
1013 |
1112 |
1014 if fuzz and strict: |
1113 if fuzz and strict: |
1015 self.ui.warn(_("fuzz found when applying patch, stopping\n")) |
1114 self.ui.warn(_("fuzz found when applying patch, stopping\n")) |
1143 return None, None |
1243 return None, None |
1144 |
1244 |
1145 def putsubstate2changes(self, substatestate, changes): |
1245 def putsubstate2changes(self, substatestate, changes): |
1146 for files in changes[:3]: |
1246 for files in changes[:3]: |
1147 if '.hgsubstate' in files: |
1247 if '.hgsubstate' in files: |
1148 return # already listed up |
1248 return # already listed up |
1149 # not yet listed up |
1249 # not yet listed up |
1150 if substatestate in 'a?': |
1250 if substatestate in 'a?': |
1151 changes[1].append('.hgsubstate') |
1251 changes[1].append('.hgsubstate') |
1152 elif substatestate in 'r': |
1252 elif substatestate in 'r': |
1153 changes[2].append('.hgsubstate') |
1253 changes[2].append('.hgsubstate') |
1154 else: # modified |
1254 else: # modified |
1155 changes[0].append('.hgsubstate') |
1255 changes[0].append('.hgsubstate') |
1156 |
1256 |
1157 def checklocalchanges(self, repo, force=False, refresh=True): |
1257 def checklocalchanges(self, repo, force=False, refresh=True): |
1158 excsuffix = '' |
1258 excsuffix = '' |
1159 if refresh: |
1259 if refresh: |
1164 |
1264 |
1165 s = repo.status() |
1265 s = repo.status() |
1166 if not force: |
1266 if not force: |
1167 cmdutil.checkunfinished(repo) |
1267 cmdutil.checkunfinished(repo) |
1168 if s.modified or s.added or s.removed or s.deleted: |
1268 if s.modified or s.added or s.removed or s.deleted: |
1169 _("local changes found") # i18n tool detection |
1269 _("local changes found") # i18n tool detection |
1170 raise error.Abort(_("local changes found" + excsuffix)) |
1270 raise error.Abort(_("local changes found" + excsuffix)) |
1171 if checksubstate(repo): |
1271 if checksubstate(repo): |
1172 _("local changed subrepos found") # i18n tool detection |
1272 _("local changed subrepos found") # i18n tool detection |
1173 raise error.Abort(_("local changed subrepos found" + excsuffix)) |
1273 raise error.Abort(_("local changed subrepos found" + excsuffix)) |
1174 else: |
1274 else: |
1175 cmdutil.checkunfinished(repo, skipmerge=True) |
1275 cmdutil.checkunfinished(repo, skipmerge=True) |
1176 return s |
1276 return s |
1177 |
1277 |
1178 _reserved = ('series', 'status', 'guards', '.', '..') |
1278 _reserved = ('series', 'status', 'guards', '.', '..') |
|
1279 |
1179 def checkreservedname(self, name): |
1280 def checkreservedname(self, name): |
1180 if name in self._reserved: |
1281 if name in self._reserved: |
1181 raise error.Abort(_('"%s" cannot be used as the name of a patch') |
1282 raise error.Abort( |
1182 % name) |
1283 _('"%s" cannot be used as the name of a patch') % name |
|
1284 ) |
1183 if name != name.strip(): |
1285 if name != name.strip(): |
1184 # whitespace is stripped by parseseries() |
1286 # whitespace is stripped by parseseries() |
1185 raise error.Abort(_('patch name cannot begin or end with ' |
1287 raise error.Abort( |
1186 'whitespace')) |
1288 _('patch name cannot begin or end with ' 'whitespace') |
|
1289 ) |
1187 for prefix in ('.hg', '.mq'): |
1290 for prefix in ('.hg', '.mq'): |
1188 if name.startswith(prefix): |
1291 if name.startswith(prefix): |
1189 raise error.Abort(_('patch name cannot begin with "%s"') |
1292 raise error.Abort( |
1190 % prefix) |
1293 _('patch name cannot begin with "%s"') % prefix |
|
1294 ) |
1191 for c in ('#', ':', '\r', '\n'): |
1295 for c in ('#', ':', '\r', '\n'): |
1192 if c in name: |
1296 if c in name: |
1193 raise error.Abort(_('%r cannot be used in the name of a patch') |
1297 raise error.Abort( |
1194 % pycompat.bytestr(c)) |
1298 _('%r cannot be used in the name of a patch') |
|
1299 % pycompat.bytestr(c) |
|
1300 ) |
1195 |
1301 |
1196 def checkpatchname(self, name, force=False): |
1302 def checkpatchname(self, name, force=False): |
1197 self.checkreservedname(name) |
1303 self.checkreservedname(name) |
1198 if not force and os.path.exists(self.join(name)): |
1304 if not force and os.path.exists(self.join(name)): |
1199 if os.path.isdir(self.join(name)): |
1305 if os.path.isdir(self.join(name)): |
1200 raise error.Abort(_('"%s" already exists as a directory') |
1306 raise error.Abort( |
1201 % name) |
1307 _('"%s" already exists as a directory') % name |
|
1308 ) |
1202 else: |
1309 else: |
1203 raise error.Abort(_('patch "%s" already exists') % name) |
1310 raise error.Abort(_('patch "%s" already exists') % name) |
1204 |
1311 |
1205 def makepatchname(self, title, fallbackname): |
1312 def makepatchname(self, title, fallbackname): |
1206 """Return a suitable filename for title, adding a suffix to make |
1313 """Return a suitable filename for title, adding a suffix to make |
1207 it unique in the existing list""" |
1314 it unique in the existing list""" |
1208 namebase = re.sub(br'[\s\W_]+', b'_', title.lower()).strip(b'_') |
1315 namebase = re.sub(br'[\s\W_]+', b'_', title.lower()).strip(b'_') |
1209 namebase = namebase[:75] # avoid too long name (issue5117) |
1316 namebase = namebase[:75] # avoid too long name (issue5117) |
1210 if namebase: |
1317 if namebase: |
1211 try: |
1318 try: |
1212 self.checkreservedname(namebase) |
1319 self.checkreservedname(namebase) |
1213 except error.Abort: |
1320 except error.Abort: |
1214 namebase = fallbackname |
1321 namebase = fallbackname |
1250 if inclsubs: |
1357 if inclsubs: |
1251 substatestate = repo.dirstate['.hgsubstate'] |
1358 substatestate = repo.dirstate['.hgsubstate'] |
1252 if opts.get('include') or opts.get('exclude') or pats: |
1359 if opts.get('include') or opts.get('exclude') or pats: |
1253 # detect missing files in pats |
1360 # detect missing files in pats |
1254 def badfn(f, msg): |
1361 def badfn(f, msg): |
1255 if f != '.hgsubstate': # .hgsubstate is auto-created |
1362 if f != '.hgsubstate': # .hgsubstate is auto-created |
1256 raise error.Abort('%s: %s' % (f, msg)) |
1363 raise error.Abort('%s: %s' % (f, msg)) |
|
1364 |
1257 match = scmutil.match(repo[None], pats, opts, badfn=badfn) |
1365 match = scmutil.match(repo[None], pats, opts, badfn=badfn) |
1258 changes = repo.status(match=match) |
1366 changes = repo.status(match=match) |
1259 else: |
1367 else: |
1260 changes = self.checklocalchanges(repo, force=True) |
1368 changes = self.checklocalchanges(repo, force=True) |
1261 commitfiles = list(inclsubs) |
1369 commitfiles = list(inclsubs) |
1269 with repo.wlock(): |
1377 with repo.wlock(): |
1270 try: |
1378 try: |
1271 # if patch file write fails, abort early |
1379 # if patch file write fails, abort early |
1272 p = self.opener(patchfn, "w") |
1380 p = self.opener(patchfn, "w") |
1273 except IOError as e: |
1381 except IOError as e: |
1274 raise error.Abort(_('cannot write patch "%s": %s') |
1382 raise error.Abort( |
1275 % (patchfn, encoding.strtolocal(e.strerror))) |
1383 _('cannot write patch "%s": %s') |
|
1384 % (patchfn, encoding.strtolocal(e.strerror)) |
|
1385 ) |
1276 try: |
1386 try: |
1277 defaultmsg = "[mq]: %s" % patchfn |
1387 defaultmsg = "[mq]: %s" % patchfn |
1278 editor = cmdutil.getcommiteditor(editform=editform) |
1388 editor = cmdutil.getcommiteditor(editform=editform) |
1279 if edit: |
1389 if edit: |
|
1390 |
1280 def finishdesc(desc): |
1391 def finishdesc(desc): |
1281 if desc.rstrip(): |
1392 if desc.rstrip(): |
1282 return desc |
1393 return desc |
1283 else: |
1394 else: |
1284 return defaultmsg |
1395 return defaultmsg |
|
1396 |
1285 # i18n: this message is shown in editor with "HG: " prefix |
1397 # i18n: this message is shown in editor with "HG: " prefix |
1286 extramsg = _('Leave message empty to use default message.') |
1398 extramsg = _('Leave message empty to use default message.') |
1287 editor = cmdutil.getcommiteditor(finishdesc=finishdesc, |
1399 editor = cmdutil.getcommiteditor( |
1288 extramsg=extramsg, |
1400 finishdesc=finishdesc, |
1289 editform=editform) |
1401 extramsg=extramsg, |
|
1402 editform=editform, |
|
1403 ) |
1290 commitmsg = msg |
1404 commitmsg = msg |
1291 else: |
1405 else: |
1292 commitmsg = msg or defaultmsg |
1406 commitmsg = msg or defaultmsg |
1293 |
1407 |
1294 n = newcommit(repo, None, commitmsg, user, date, match=match, |
1408 n = newcommit( |
1295 force=True, editor=editor) |
1409 repo, |
|
1410 None, |
|
1411 commitmsg, |
|
1412 user, |
|
1413 date, |
|
1414 match=match, |
|
1415 force=True, |
|
1416 editor=editor, |
|
1417 ) |
1296 if n is None: |
1418 if n is None: |
1297 raise error.Abort(_("repo commit failed")) |
1419 raise error.Abort(_("repo commit failed")) |
1298 try: |
1420 try: |
1299 self.fullseries[insert:insert] = [patchfn] |
1421 self.fullseries[insert:insert] = [patchfn] |
1300 self.applied.append(statusentry(n, patchfn)) |
1422 self.applied.append(statusentry(n, patchfn)) |
1401 if plus >= 0: |
1528 if plus >= 0: |
1402 res = partialname(patch[:plus]) |
1529 res = partialname(patch[:plus]) |
1403 if res: |
1530 if res: |
1404 i = self.series.index(res) |
1531 i = self.series.index(res) |
1405 try: |
1532 try: |
1406 off = int(patch[plus + 1:] or 1) |
1533 off = int(patch[plus + 1 :] or 1) |
1407 except (ValueError, OverflowError): |
1534 except (ValueError, OverflowError): |
1408 pass |
1535 pass |
1409 else: |
1536 else: |
1410 if i + off < len(self.series): |
1537 if i + off < len(self.series): |
1411 return self.series[i + off] |
1538 return self.series[i + off] |
1412 raise error.Abort(_("patch %s not in series") % patch) |
1539 raise error.Abort(_("patch %s not in series") % patch) |
1413 |
1540 |
1414 def push(self, repo, patch=None, force=False, list=False, mergeq=None, |
1541 def push( |
1415 all=False, move=False, exact=False, nobackup=False, |
1542 self, |
1416 keepchanges=False): |
1543 repo, |
|
1544 patch=None, |
|
1545 force=False, |
|
1546 list=False, |
|
1547 mergeq=None, |
|
1548 all=False, |
|
1549 move=False, |
|
1550 exact=False, |
|
1551 nobackup=False, |
|
1552 keepchanges=False, |
|
1553 ): |
1417 self.checkkeepchanges(keepchanges, force) |
1554 self.checkkeepchanges(keepchanges, force) |
1418 diffopts = self.diffopts() |
1555 diffopts = self.diffopts() |
1419 with repo.wlock(): |
1556 with repo.wlock(): |
1420 heads = [] |
1557 heads = [] |
1421 for hs in repo.branchmap().iterheads(): |
1558 for hs in repo.branchmap().iterheads(): |
1519 |
1660 |
1520 tobackup = set() |
1661 tobackup = set() |
1521 if (not nobackup and force) or keepchanges: |
1662 if (not nobackup and force) or keepchanges: |
1522 status = self.checklocalchanges(repo, force=True) |
1663 status = self.checklocalchanges(repo, force=True) |
1523 if keepchanges: |
1664 if keepchanges: |
1524 tobackup.update(status.modified + status.added + |
1665 tobackup.update( |
1525 status.removed + status.deleted) |
1666 status.modified |
|
1667 + status.added |
|
1668 + status.removed |
|
1669 + status.deleted |
|
1670 ) |
1526 else: |
1671 else: |
1527 tobackup.update(status.modified + status.added) |
1672 tobackup.update(status.modified + status.added) |
1528 |
1673 |
1529 s = self.series[start:end] |
1674 s = self.series[start:end] |
1530 all_files = set() |
1675 all_files = set() |
1531 try: |
1676 try: |
1532 if mergeq: |
1677 if mergeq: |
1533 ret = self.mergepatch(repo, mergeq, s, diffopts) |
1678 ret = self.mergepatch(repo, mergeq, s, diffopts) |
1534 else: |
1679 else: |
1535 ret = self.apply(repo, s, list, all_files=all_files, |
1680 ret = self.apply( |
1536 tobackup=tobackup, keepchanges=keepchanges) |
1681 repo, |
|
1682 s, |
|
1683 list, |
|
1684 all_files=all_files, |
|
1685 tobackup=tobackup, |
|
1686 keepchanges=keepchanges, |
|
1687 ) |
1537 except AbortNoCleanup: |
1688 except AbortNoCleanup: |
1538 raise |
1689 raise |
1539 except: # re-raises |
1690 except: # re-raises |
1540 self.ui.warn(_('cleaning up working directory...\n')) |
1691 self.ui.warn(_('cleaning up working directory...\n')) |
1541 cmdutil.revert(self.ui, repo, repo['.'], |
1692 cmdutil.revert( |
1542 repo.dirstate.parents(), no_backup=True) |
1693 self.ui, |
|
1694 repo, |
|
1695 repo['.'], |
|
1696 repo.dirstate.parents(), |
|
1697 no_backup=True, |
|
1698 ) |
1543 # only remove unknown files that we know we touched or |
1699 # only remove unknown files that we know we touched or |
1544 # created while patching |
1700 # created while patching |
1545 for f in all_files: |
1701 for f in all_files: |
1546 if f not in repo.dirstate: |
1702 if f not in repo.dirstate: |
1547 repo.wvfs.unlinkpath(f, ignoremissing=True) |
1703 repo.wvfs.unlinkpath(f, ignoremissing=True) |
1619 except error.LookupError: |
1785 except error.LookupError: |
1620 node = short(rev) |
1786 node = short(rev) |
1621 raise error.Abort(_('trying to pop unknown node %s') % node) |
1787 raise error.Abort(_('trying to pop unknown node %s') % node) |
1622 |
1788 |
1623 if heads != [self.applied[-1].node]: |
1789 if heads != [self.applied[-1].node]: |
1624 raise error.Abort(_("popping would remove a revision not " |
1790 raise error.Abort( |
1625 "managed by this patch queue")) |
1791 _( |
|
1792 "popping would remove a revision not " |
|
1793 "managed by this patch queue" |
|
1794 ) |
|
1795 ) |
1626 if not repo[self.applied[-1].node].mutable(): |
1796 if not repo[self.applied[-1].node].mutable(): |
1627 raise error.Abort( |
1797 raise error.Abort( |
1628 _("popping would remove a public revision"), |
1798 _("popping would remove a public revision"), |
1629 hint=_("see 'hg help phases' for details")) |
1799 hint=_("see 'hg help phases' for details"), |
|
1800 ) |
1630 |
1801 |
1631 # we know there are no local changes, so we can make a simplified |
1802 # we know there are no local changes, so we can make a simplified |
1632 # form of hg.update. |
1803 # form of hg.update. |
1633 if update: |
1804 if update: |
1634 qp = self.qparents(repo, rev) |
1805 qp = self.qparents(repo, rev) |
1692 self.checktoppatch(repo) |
1863 self.checktoppatch(repo) |
1693 (top, patchfn) = (self.applied[-1].node, self.applied[-1].name) |
1864 (top, patchfn) = (self.applied[-1].node, self.applied[-1].name) |
1694 if repo.changelog.heads(top) != [top]: |
1865 if repo.changelog.heads(top) != [top]: |
1695 raise error.Abort(_("cannot qrefresh a revision with children")) |
1866 raise error.Abort(_("cannot qrefresh a revision with children")) |
1696 if not repo[top].mutable(): |
1867 if not repo[top].mutable(): |
1697 raise error.Abort(_("cannot qrefresh public revision"), |
1868 raise error.Abort( |
1698 hint=_("see 'hg help phases' for details")) |
1869 _("cannot qrefresh public revision"), |
|
1870 hint=_("see 'hg help phases' for details"), |
|
1871 ) |
1699 |
1872 |
1700 cparents = repo.changelog.parents(top) |
1873 cparents = repo.changelog.parents(top) |
1701 patchparent = self.qparents(repo, top) |
1874 patchparent = self.qparents(repo, top) |
1702 |
1875 |
1703 inclsubs = checksubstate(repo, patchparent) |
1876 inclsubs = checksubstate(repo, patchparent) |
1704 if inclsubs: |
1877 if inclsubs: |
1705 substatestate = repo.dirstate['.hgsubstate'] |
1878 substatestate = repo.dirstate['.hgsubstate'] |
1706 |
1879 |
1707 ph = patchheader(self.join(patchfn), self.plainmode) |
1880 ph = patchheader(self.join(patchfn), self.plainmode) |
1708 diffopts = self.diffopts({'git': opts.get('git')}, patchfn, |
1881 diffopts = self.diffopts( |
1709 plain=True) |
1882 {'git': opts.get('git')}, patchfn, plain=True |
|
1883 ) |
1710 if newuser: |
1884 if newuser: |
1711 ph.setuser(newuser) |
1885 ph.setuser(newuser) |
1712 if newdate: |
1886 if newdate: |
1713 ph.setdate(newdate) |
1887 ph.setdate(newdate) |
1714 ph.setparent(hex(patchparent)) |
1888 ph.setparent(hex(patchparent)) |
1878 # the old one. |
2057 # the old one. |
1879 lock = tr = None |
2058 lock = tr = None |
1880 try: |
2059 try: |
1881 lock = repo.lock() |
2060 lock = repo.lock() |
1882 tr = repo.transaction('mq') |
2061 tr = repo.transaction('mq') |
1883 n = newcommit(repo, oldphase, message, user, ph.date, |
2062 n = newcommit( |
1884 match=match, force=True, editor=editor) |
2063 repo, |
|
2064 oldphase, |
|
2065 message, |
|
2066 user, |
|
2067 ph.date, |
|
2068 match=match, |
|
2069 force=True, |
|
2070 editor=editor, |
|
2071 ) |
1885 # only write patch after a successful commit |
2072 # only write patch after a successful commit |
1886 c = [list(x) for x in refreshchanges] |
2073 c = [list(x) for x in refreshchanges] |
1887 if inclsubs: |
2074 if inclsubs: |
1888 self.putsubstate2changes(substatestate, c) |
2075 self.putsubstate2changes(substatestate, c) |
1889 chunks = patchmod.diff(repo, patchparent, |
2076 chunks = patchmod.diff( |
1890 changes=c, opts=diffopts) |
2077 repo, patchparent, changes=c, opts=diffopts |
|
2078 ) |
1891 comments = bytes(ph) |
2079 comments = bytes(ph) |
1892 if comments: |
2080 if comments: |
1893 patchf.write(comments) |
2081 patchf.write(comments) |
1894 for chunk in chunks: |
2082 for chunk in chunks: |
1895 patchf.write(chunk) |
2083 patchf.write(chunk) |
1985 continue |
2184 continue |
1986 displayname(pfx, patch, state) |
2185 displayname(pfx, patch, state) |
1987 else: |
2186 else: |
1988 msng_list = [] |
2187 msng_list = [] |
1989 for root, dirs, files in os.walk(self.path): |
2188 for root, dirs, files in os.walk(self.path): |
1990 d = root[len(self.path) + 1:] |
2189 d = root[len(self.path) + 1 :] |
1991 for f in files: |
2190 for f in files: |
1992 fl = os.path.join(d, f) |
2191 fl = os.path.join(d, f) |
1993 if (fl not in self.series and |
2192 if ( |
1994 fl not in (self.statuspath, self.seriespath, |
2193 fl not in self.series |
1995 self.guardspath) |
2194 and fl |
1996 and not fl.startswith('.')): |
2195 not in ( |
|
2196 self.statuspath, |
|
2197 self.seriespath, |
|
2198 self.guardspath, |
|
2199 ) |
|
2200 and not fl.startswith('.') |
|
2201 ): |
1997 msng_list.append(fl) |
2202 msng_list.append(fl) |
1998 for x in sorted(msng_list): |
2203 for x in sorted(msng_list): |
1999 pfx = self.ui.verbose and ('D ') or '' |
2204 pfx = self.ui.verbose and 'D ' or '' |
2000 displayname(pfx, x, 'missing') |
2205 displayname(pfx, x, 'missing') |
2001 |
2206 |
2002 def issaveline(self, l): |
2207 def issaveline(self, l): |
2003 if l.name == '.hg.patches.save.line': |
2208 if l.name == '.hg.patches.save.line': |
2004 return True |
2209 return True |
2007 ui = self.baseui.copy() |
2212 ui = self.baseui.copy() |
2008 # copy back attributes set by ui.pager() |
2213 # copy back attributes set by ui.pager() |
2009 if self.ui.pageractive and not ui.pageractive: |
2214 if self.ui.pageractive and not ui.pageractive: |
2010 ui.pageractive = self.ui.pageractive |
2215 ui.pageractive = self.ui.pageractive |
2011 # internal config: ui.formatted |
2216 # internal config: ui.formatted |
2012 ui.setconfig('ui', 'formatted', |
2217 ui.setconfig( |
2013 self.ui.config('ui', 'formatted'), 'mqpager') |
2218 'ui', 'formatted', self.ui.config('ui', 'formatted'), 'mqpager' |
2014 ui.setconfig('ui', 'interactive', |
2219 ) |
2015 self.ui.config('ui', 'interactive'), 'mqpager') |
2220 ui.setconfig( |
|
2221 'ui', |
|
2222 'interactive', |
|
2223 self.ui.config('ui', 'interactive'), |
|
2224 'mqpager', |
|
2225 ) |
2016 if create or os.path.isdir(self.join(".hg")): |
2226 if create or os.path.isdir(self.join(".hg")): |
2017 return hg.repository(ui, path=self.path, create=create) |
2227 return hg.repository(ui, path=self.path, create=create) |
2018 |
2228 |
2019 def restore(self, repo, rev, delete=None, qupdate=None): |
2229 def restore(self, repo, rev, delete=None, qupdate=None): |
2020 desc = repo[rev].description().strip() |
2230 desc = repo[rev].description().strip() |
2110 """If all_patches is False, return the index of the next pushable patch |
2322 """If all_patches is False, return the index of the next pushable patch |
2111 in the series, or the series length. If all_patches is True, return the |
2323 in the series, or the series length. If all_patches is True, return the |
2112 index of the first patch past the last applied one. |
2324 index of the first patch past the last applied one. |
2113 """ |
2325 """ |
2114 end = 0 |
2326 end = 0 |
|
2327 |
2115 def nextpatch(start): |
2328 def nextpatch(start): |
2116 if all_patches or start >= len(self.series): |
2329 if all_patches or start >= len(self.series): |
2117 return start |
2330 return start |
2118 for i in pycompat.xrange(start, len(self.series)): |
2331 for i in pycompat.xrange(start, len(self.series)): |
2119 p, reason = self.pushable(i) |
2332 p, reason = self.pushable(i) |
2120 if p: |
2333 if p: |
2121 return i |
2334 return i |
2122 self.explainpushable(i) |
2335 self.explainpushable(i) |
2123 return len(self.series) |
2336 return len(self.series) |
|
2337 |
2124 if self.applied: |
2338 if self.applied: |
2125 p = self.applied[-1].name |
2339 p = self.applied[-1].name |
2126 try: |
2340 try: |
2127 end = self.series.index(p) |
2341 end = self.series.index(p) |
2128 except ValueError: |
2342 except ValueError: |
2136 p = pname |
2350 p = pname |
2137 else: |
2351 else: |
2138 p = ("%d" % self.series.index(pname)) + " " + pname |
2352 p = ("%d" % self.series.index(pname)) + " " + pname |
2139 return p |
2353 return p |
2140 |
2354 |
2141 def qimport(self, repo, files, patchname=None, rev=None, existing=None, |
2355 def qimport( |
2142 force=None, git=False): |
2356 self, |
|
2357 repo, |
|
2358 files, |
|
2359 patchname=None, |
|
2360 rev=None, |
|
2361 existing=None, |
|
2362 force=None, |
|
2363 git=False, |
|
2364 ): |
2143 def checkseries(patchname): |
2365 def checkseries(patchname): |
2144 if patchname in self.series: |
2366 if patchname in self.series: |
2145 raise error.Abort(_('patch %s is already in the series file') |
2367 raise error.Abort( |
2146 % patchname) |
2368 _('patch %s is already in the series file') % patchname |
|
2369 ) |
2147 |
2370 |
2148 if rev: |
2371 if rev: |
2149 if files: |
2372 if files: |
2150 raise error.Abort(_('option "-r" not valid when importing ' |
2373 raise error.Abort( |
2151 'files')) |
2374 _('option "-r" not valid when importing ' 'files') |
|
2375 ) |
2152 rev = scmutil.revrange(repo, rev) |
2376 rev = scmutil.revrange(repo, rev) |
2153 rev.sort(reverse=True) |
2377 rev.sort(reverse=True) |
2154 elif not files: |
2378 elif not files: |
2155 raise error.Abort(_('no files or revisions specified')) |
2379 raise error.Abort(_('no files or revisions specified')) |
2156 if (len(files) > 1 or len(rev) > 1) and patchname: |
2380 if (len(files) > 1 or len(rev) > 1) and patchname: |
2157 raise error.Abort(_('option "-n" not valid when importing multiple ' |
2381 raise error.Abort( |
2158 'patches')) |
2382 _('option "-n" not valid when importing multiple ' 'patches') |
|
2383 ) |
2159 imported = [] |
2384 imported = [] |
2160 if rev: |
2385 if rev: |
2161 # If mq patches are applied, we can only import revisions |
2386 # If mq patches are applied, we can only import revisions |
2162 # that form a linear path to qbase. |
2387 # that form a linear path to qbase. |
2163 # Otherwise, they should form a linear path to a head. |
2388 # Otherwise, they should form a linear path to a head. |
2164 heads = repo.changelog.heads(repo.changelog.node(rev.first())) |
2389 heads = repo.changelog.heads(repo.changelog.node(rev.first())) |
2165 if len(heads) > 1: |
2390 if len(heads) > 1: |
2166 raise error.Abort(_('revision %d is the root of more than one ' |
2391 raise error.Abort( |
2167 'branch') % rev.last()) |
2392 _('revision %d is the root of more than one ' 'branch') |
|
2393 % rev.last() |
|
2394 ) |
2168 if self.applied: |
2395 if self.applied: |
2169 base = repo.changelog.node(rev.first()) |
2396 base = repo.changelog.node(rev.first()) |
2170 if base in [n.node for n in self.applied]: |
2397 if base in [n.node for n in self.applied]: |
2171 raise error.Abort(_('revision %d is already managed') |
2398 raise error.Abort( |
2172 % rev.first()) |
2399 _('revision %d is already managed') % rev.first() |
|
2400 ) |
2173 if heads != [self.applied[-1].node]: |
2401 if heads != [self.applied[-1].node]: |
2174 raise error.Abort(_('revision %d is not the parent of ' |
2402 raise error.Abort( |
2175 'the queue') % rev.first()) |
2403 _('revision %d is not the parent of ' 'the queue') |
|
2404 % rev.first() |
|
2405 ) |
2176 base = repo.changelog.rev(self.applied[0].node) |
2406 base = repo.changelog.rev(self.applied[0].node) |
2177 lastparent = repo.changelog.parentrevs(base)[0] |
2407 lastparent = repo.changelog.parentrevs(base)[0] |
2178 else: |
2408 else: |
2179 if heads != [repo.changelog.node(rev.first())]: |
2409 if heads != [repo.changelog.node(rev.first())]: |
2180 raise error.Abort(_('revision %d has unmanaged children') |
2410 raise error.Abort( |
2181 % rev.first()) |
2411 _('revision %d has unmanaged children') % rev.first() |
|
2412 ) |
2182 lastparent = None |
2413 lastparent = None |
2183 |
2414 |
2184 diffopts = self.diffopts({'git': git}) |
2415 diffopts = self.diffopts({'git': git}) |
2185 with repo.transaction('qimport') as tr: |
2416 with repo.transaction('qimport') as tr: |
2186 for r in rev: |
2417 for r in rev: |
2187 if not repo[r].mutable(): |
2418 if not repo[r].mutable(): |
2188 raise error.Abort(_('revision %d is not mutable') % r, |
2419 raise error.Abort( |
2189 hint=_("see 'hg help phases' " |
2420 _('revision %d is not mutable') % r, |
2190 'for details')) |
2421 hint=_("see 'hg help phases' " 'for details'), |
|
2422 ) |
2191 p1, p2 = repo.changelog.parentrevs(r) |
2423 p1, p2 = repo.changelog.parentrevs(r) |
2192 n = repo.changelog.node(r) |
2424 n = repo.changelog.node(r) |
2193 if p2 != nullrev: |
2425 if p2 != nullrev: |
2194 raise error.Abort(_('cannot import merge revision %d') |
2426 raise error.Abort( |
2195 % r) |
2427 _('cannot import merge revision %d') % r |
|
2428 ) |
2196 if lastparent and lastparent != r: |
2429 if lastparent and lastparent != r: |
2197 raise error.Abort(_('revision %d is not the parent of ' |
2430 raise error.Abort( |
2198 '%d') |
2431 _('revision %d is not the parent of ' '%d') |
2199 % (r, lastparent)) |
2432 % (r, lastparent) |
|
2433 ) |
2200 lastparent = p1 |
2434 lastparent = p1 |
2201 |
2435 |
2202 if not patchname: |
2436 if not patchname: |
2203 patchname = self.makepatchname( |
2437 patchname = self.makepatchname( |
2204 repo[r].description().split('\n', 1)[0], |
2438 repo[r].description().split('\n', 1)[0], |
2205 '%d.diff' % r) |
2439 '%d.diff' % r, |
|
2440 ) |
2206 checkseries(patchname) |
2441 checkseries(patchname) |
2207 self.checkpatchname(patchname, force) |
2442 self.checkpatchname(patchname, force) |
2208 self.fullseries.insert(0, patchname) |
2443 self.fullseries.insert(0, patchname) |
2209 |
2444 |
2210 with self.opener(patchname, "w") as fp: |
2445 with self.opener(patchname, "w") as fp: |
2224 self.seriesdirty = True |
2459 self.seriesdirty = True |
2225 |
2460 |
2226 for i, filename in enumerate(files): |
2461 for i, filename in enumerate(files): |
2227 if existing: |
2462 if existing: |
2228 if filename == '-': |
2463 if filename == '-': |
2229 raise error.Abort(_('-e is incompatible with import from -') |
2464 raise error.Abort( |
2230 ) |
2465 _('-e is incompatible with import from -') |
|
2466 ) |
2231 filename = normname(filename) |
2467 filename = normname(filename) |
2232 self.checkreservedname(filename) |
2468 self.checkreservedname(filename) |
2233 if util.url(filename).islocal(): |
2469 if util.url(filename).islocal(): |
2234 originpath = self.join(filename) |
2470 originpath = self.join(filename) |
2235 if not os.path.isfile(originpath): |
2471 if not os.path.isfile(originpath): |
2236 raise error.Abort( |
2472 raise error.Abort( |
2237 _("patch %s does not exist") % filename) |
2473 _("patch %s does not exist") % filename |
|
2474 ) |
2238 |
2475 |
2239 if patchname: |
2476 if patchname: |
2240 self.checkpatchname(patchname, force) |
2477 self.checkpatchname(patchname, force) |
2241 |
2478 |
2242 self.ui.write(_('renaming %s to %s\n') |
2479 self.ui.write( |
2243 % (filename, patchname)) |
2480 _('renaming %s to %s\n') % (filename, patchname) |
|
2481 ) |
2244 util.rename(originpath, self.join(patchname)) |
2482 util.rename(originpath, self.join(patchname)) |
2245 else: |
2483 else: |
2246 patchname = filename |
2484 patchname = filename |
2247 |
2485 |
2248 else: |
2486 else: |
2276 patchname = None |
2514 patchname = None |
2277 |
2515 |
2278 self.removeundo(repo) |
2516 self.removeundo(repo) |
2279 return imported |
2517 return imported |
2280 |
2518 |
|
2519 |
2281 def fixkeepchangesopts(ui, opts): |
2520 def fixkeepchangesopts(ui, opts): |
2282 if (not ui.configbool('mq', 'keepchanges') or opts.get('force') |
2521 if ( |
2283 or opts.get('exact')): |
2522 not ui.configbool('mq', 'keepchanges') |
|
2523 or opts.get('force') |
|
2524 or opts.get('exact') |
|
2525 ): |
2284 return opts |
2526 return opts |
2285 opts = dict(opts) |
2527 opts = dict(opts) |
2286 opts['keep_changes'] = True |
2528 opts['keep_changes'] = True |
2287 return opts |
2529 return opts |
2288 |
2530 |
2289 @command("qdelete|qremove|qrm", |
2531 |
2290 [('k', 'keep', None, _('keep patch file')), |
2532 @command( |
2291 ('r', 'rev', [], |
2533 "qdelete|qremove|qrm", |
2292 _('stop managing a revision (DEPRECATED)'), _('REV'))], |
2534 [ |
2293 _('hg qdelete [-k] [PATCH]...'), |
2535 ('k', 'keep', None, _('keep patch file')), |
2294 helpcategory=command.CATEGORY_CHANGE_ORGANIZATION) |
2536 ('r', 'rev', [], _('stop managing a revision (DEPRECATED)'), _('REV')), |
|
2537 ], |
|
2538 _('hg qdelete [-k] [PATCH]...'), |
|
2539 helpcategory=command.CATEGORY_CHANGE_ORGANIZATION, |
|
2540 ) |
2295 def delete(ui, repo, *patches, **opts): |
2541 def delete(ui, repo, *patches, **opts): |
2296 """remove patches from queue |
2542 """remove patches from queue |
2297 |
2543 |
2298 The patches must not be applied, and at least one patch is required. Exact |
2544 The patches must not be applied, and at least one patch is required. Exact |
2299 patch identifiers must be given. With -k/--keep, the patch files are |
2545 patch identifiers must be given. With -k/--keep, the patch files are |
2304 q = repo.mq |
2550 q = repo.mq |
2305 q.delete(repo, patches, pycompat.byteskwargs(opts)) |
2551 q.delete(repo, patches, pycompat.byteskwargs(opts)) |
2306 q.savedirty() |
2552 q.savedirty() |
2307 return 0 |
2553 return 0 |
2308 |
2554 |
2309 @command("qapplied", |
2555 |
2310 [('1', 'last', None, _('show only the preceding applied patch')) |
2556 @command( |
2311 ] + seriesopts, |
2557 "qapplied", |
2312 _('hg qapplied [-1] [-s] [PATCH]'), |
2558 [('1', 'last', None, _('show only the preceding applied patch'))] |
2313 helpcategory=command.CATEGORY_CHANGE_ORGANIZATION) |
2559 + seriesopts, |
|
2560 _('hg qapplied [-1] [-s] [PATCH]'), |
|
2561 helpcategory=command.CATEGORY_CHANGE_ORGANIZATION, |
|
2562 ) |
2314 def applied(ui, repo, patch=None, **opts): |
2563 def applied(ui, repo, patch=None, **opts): |
2315 """print the patches already applied |
2564 """print the patches already applied |
2316 |
2565 |
2317 Returns 0 on success.""" |
2566 Returns 0 on success.""" |
2318 |
2567 |
2336 start = end - 2 |
2585 start = end - 2 |
2337 end = 1 |
2586 end = 1 |
2338 else: |
2587 else: |
2339 start = 0 |
2588 start = 0 |
2340 |
2589 |
2341 q.qseries(repo, length=end, start=start, status='A', |
2590 q.qseries( |
2342 summary=opts.get('summary')) |
2591 repo, length=end, start=start, status='A', summary=opts.get('summary') |
2343 |
2592 ) |
2344 |
2593 |
2345 @command("qunapplied", |
2594 |
2346 [('1', 'first', None, _('show only the first patch'))] + seriesopts, |
2595 @command( |
2347 _('hg qunapplied [-1] [-s] [PATCH]'), |
2596 "qunapplied", |
2348 helpcategory=command.CATEGORY_CHANGE_ORGANIZATION) |
2597 [('1', 'first', None, _('show only the first patch'))] + seriesopts, |
|
2598 _('hg qunapplied [-1] [-s] [PATCH]'), |
|
2599 helpcategory=command.CATEGORY_CHANGE_ORGANIZATION, |
|
2600 ) |
2349 def unapplied(ui, repo, patch=None, **opts): |
2601 def unapplied(ui, repo, patch=None, **opts): |
2350 """print the patches not yet applied |
2602 """print the patches not yet applied |
2351 |
2603 |
2352 Returns 0 on success.""" |
2604 Returns 0 on success.""" |
2353 |
2605 |
2366 |
2618 |
2367 if opts.get('first'): |
2619 if opts.get('first'): |
2368 length = 1 |
2620 length = 1 |
2369 else: |
2621 else: |
2370 length = None |
2622 length = None |
2371 q.qseries(repo, start=start, length=length, status='U', |
2623 q.qseries( |
2372 summary=opts.get('summary')) |
2624 repo, |
2373 |
2625 start=start, |
2374 @command("qimport", |
2626 length=length, |
2375 [('e', 'existing', None, _('import file in patch directory')), |
2627 status='U', |
2376 ('n', 'name', '', |
2628 summary=opts.get('summary'), |
2377 _('name of patch file'), _('NAME')), |
2629 ) |
2378 ('f', 'force', None, _('overwrite existing files')), |
2630 |
2379 ('r', 'rev', [], |
2631 |
2380 _('place existing revisions under mq control'), _('REV')), |
2632 @command( |
2381 ('g', 'git', None, _('use git extended diff format')), |
2633 "qimport", |
2382 ('P', 'push', None, _('qpush after importing'))], |
2634 [ |
2383 _('hg qimport [-e] [-n NAME] [-f] [-g] [-P] [-r REV]... [FILE]...'), |
2635 ('e', 'existing', None, _('import file in patch directory')), |
2384 helpcategory=command.CATEGORY_IMPORT_EXPORT) |
2636 ('n', 'name', '', _('name of patch file'), _('NAME')), |
|
2637 ('f', 'force', None, _('overwrite existing files')), |
|
2638 ( |
|
2639 'r', |
|
2640 'rev', |
|
2641 [], |
|
2642 _('place existing revisions under mq control'), |
|
2643 _('REV'), |
|
2644 ), |
|
2645 ('g', 'git', None, _('use git extended diff format')), |
|
2646 ('P', 'push', None, _('qpush after importing')), |
|
2647 ], |
|
2648 _('hg qimport [-e] [-n NAME] [-f] [-g] [-P] [-r REV]... [FILE]...'), |
|
2649 helpcategory=command.CATEGORY_IMPORT_EXPORT, |
|
2650 ) |
2385 def qimport(ui, repo, *filename, **opts): |
2651 def qimport(ui, repo, *filename, **opts): |
2386 """import a patch or existing changeset |
2652 """import a patch or existing changeset |
2387 |
2653 |
2388 The patch is inserted into the series after the last applied |
2654 The patch is inserted into the series after the last applied |
2389 patch. If no patches have been applied, qimport prepends the patch |
2655 patch. If no patches have been applied, qimport prepends the patch |
2415 hg qimport -e existing-patch -n new-name |
2681 hg qimport -e existing-patch -n new-name |
2416 |
2682 |
2417 Returns 0 if import succeeded. |
2683 Returns 0 if import succeeded. |
2418 """ |
2684 """ |
2419 opts = pycompat.byteskwargs(opts) |
2685 opts = pycompat.byteskwargs(opts) |
2420 with repo.lock(): # cause this may move phase |
2686 with repo.lock(): # cause this may move phase |
2421 q = repo.mq |
2687 q = repo.mq |
2422 try: |
2688 try: |
2423 imported = q.qimport( |
2689 imported = q.qimport( |
2424 repo, filename, patchname=opts.get('name'), |
2690 repo, |
2425 existing=opts.get('existing'), force=opts.get('force'), |
2691 filename, |
2426 rev=opts.get('rev'), git=opts.get('git')) |
2692 patchname=opts.get('name'), |
|
2693 existing=opts.get('existing'), |
|
2694 force=opts.get('force'), |
|
2695 rev=opts.get('rev'), |
|
2696 git=opts.get('git'), |
|
2697 ) |
2427 finally: |
2698 finally: |
2428 q.savedirty() |
2699 q.savedirty() |
2429 |
2700 |
2430 if imported and opts.get('push') and not opts.get('rev'): |
2701 if imported and opts.get('push') and not opts.get('rev'): |
2431 return q.push(repo, imported[-1]) |
2702 return q.push(repo, imported[-1]) |
2432 return 0 |
2703 return 0 |
|
2704 |
2433 |
2705 |
2434 def qinit(ui, repo, create): |
2706 def qinit(ui, repo, create): |
2435 """initialize a new queue repository |
2707 """initialize a new queue repository |
2436 |
2708 |
2437 This command also creates a series file for ordering patches, and |
2709 This command also creates a series file for ordering patches, and |
2455 r.wvfs('series', 'w').close() |
2727 r.wvfs('series', 'w').close() |
2456 r[None].add(['.hgignore', 'series']) |
2728 r[None].add(['.hgignore', 'series']) |
2457 commands.add(ui, r) |
2729 commands.add(ui, r) |
2458 return 0 |
2730 return 0 |
2459 |
2731 |
2460 @command("qinit", |
2732 |
2461 [('c', 'create-repo', None, _('create queue repository'))], |
2733 @command( |
2462 _('hg qinit [-c]'), |
2734 "qinit", |
2463 helpcategory=command.CATEGORY_REPO_CREATION, |
2735 [('c', 'create-repo', None, _('create queue repository'))], |
2464 helpbasic=True) |
2736 _('hg qinit [-c]'), |
|
2737 helpcategory=command.CATEGORY_REPO_CREATION, |
|
2738 helpbasic=True, |
|
2739 ) |
2465 def init(ui, repo, **opts): |
2740 def init(ui, repo, **opts): |
2466 """init a new queue repository (DEPRECATED) |
2741 """init a new queue repository (DEPRECATED) |
2467 |
2742 |
2468 The queue repository is unversioned by default. If |
2743 The queue repository is unversioned by default. If |
2469 -c/--create-repo is specified, qinit will create a separate nested |
2744 -c/--create-repo is specified, qinit will create a separate nested |
2473 |
2748 |
2474 This command is deprecated. Without -c, it's implied by other relevant |
2749 This command is deprecated. Without -c, it's implied by other relevant |
2475 commands. With -c, use :hg:`init --mq` instead.""" |
2750 commands. With -c, use :hg:`init --mq` instead.""" |
2476 return qinit(ui, repo, create=opts.get(r'create_repo')) |
2751 return qinit(ui, repo, create=opts.get(r'create_repo')) |
2477 |
2752 |
2478 @command("qclone", |
2753 |
2479 [('', 'pull', None, _('use pull protocol to copy metadata')), |
2754 @command( |
2480 ('U', 'noupdate', None, |
2755 "qclone", |
2481 _('do not update the new working directories')), |
2756 [ |
2482 ('', 'uncompressed', None, |
2757 ('', 'pull', None, _('use pull protocol to copy metadata')), |
2483 _('use uncompressed transfer (fast over LAN)')), |
2758 ('U', 'noupdate', None, _('do not update the new working directories')), |
2484 ('p', 'patches', '', |
2759 ( |
2485 _('location of source patch repository'), _('REPO')), |
2760 '', |
2486 ] + cmdutil.remoteopts, |
2761 'uncompressed', |
2487 _('hg qclone [OPTION]... SOURCE [DEST]'), |
2762 None, |
2488 helpcategory=command.CATEGORY_REPO_CREATION, |
2763 _('use uncompressed transfer (fast over LAN)'), |
2489 norepo=True) |
2764 ), |
|
2765 ( |
|
2766 'p', |
|
2767 'patches', |
|
2768 '', |
|
2769 _('location of source patch repository'), |
|
2770 _('REPO'), |
|
2771 ), |
|
2772 ] |
|
2773 + cmdutil.remoteopts, |
|
2774 _('hg qclone [OPTION]... SOURCE [DEST]'), |
|
2775 helpcategory=command.CATEGORY_REPO_CREATION, |
|
2776 norepo=True, |
|
2777 ) |
2490 def clone(ui, source, dest=None, **opts): |
2778 def clone(ui, source, dest=None, **opts): |
2491 '''clone main and patch repository at same time |
2779 '''clone main and patch repository at same time |
2492 |
2780 |
2493 If source is local, destination will have no patches applied. If |
2781 If source is local, destination will have no patches applied. If |
2494 source is remote, this command can not check if patches are |
2782 source is remote, this command can not check if patches are |
2541 qbase = sr.lookup('qbase') |
2831 qbase = sr.lookup('qbase') |
2542 except error.RepoError: |
2832 except error.RepoError: |
2543 pass |
2833 pass |
2544 |
2834 |
2545 ui.note(_('cloning main repository\n')) |
2835 ui.note(_('cloning main repository\n')) |
2546 sr, dr = hg.clone(ui, opts, sr.url(), dest, |
2836 sr, dr = hg.clone( |
2547 pull=opts.get('pull'), |
2837 ui, |
2548 revs=destrev, |
2838 opts, |
2549 update=False, |
2839 sr.url(), |
2550 stream=opts.get('uncompressed')) |
2840 dest, |
|
2841 pull=opts.get('pull'), |
|
2842 revs=destrev, |
|
2843 update=False, |
|
2844 stream=opts.get('uncompressed'), |
|
2845 ) |
2551 |
2846 |
2552 ui.note(_('cloning patch repository\n')) |
2847 ui.note(_('cloning patch repository\n')) |
2553 hg.clone(ui, opts, opts.get('patches') or patchdir(sr), patchdir(dr), |
2848 hg.clone( |
2554 pull=opts.get('pull'), update=not opts.get('noupdate'), |
2849 ui, |
2555 stream=opts.get('uncompressed')) |
2850 opts, |
|
2851 opts.get('patches') or patchdir(sr), |
|
2852 patchdir(dr), |
|
2853 pull=opts.get('pull'), |
|
2854 update=not opts.get('noupdate'), |
|
2855 stream=opts.get('uncompressed'), |
|
2856 ) |
2556 |
2857 |
2557 if dr.local(): |
2858 if dr.local(): |
2558 repo = dr.local() |
2859 repo = dr.local() |
2559 if qbase: |
2860 if qbase: |
2560 ui.note(_('stripping applied patches from destination ' |
2861 ui.note( |
2561 'repository\n')) |
2862 _('stripping applied patches from destination ' 'repository\n') |
|
2863 ) |
2562 strip(ui, repo, [qbase], update=False, backup=None) |
2864 strip(ui, repo, [qbase], update=False, backup=None) |
2563 if not opts.get('noupdate'): |
2865 if not opts.get('noupdate'): |
2564 ui.note(_('updating destination repository\n')) |
2866 ui.note(_('updating destination repository\n')) |
2565 hg.update(repo, repo.changelog.tip()) |
2867 hg.update(repo, repo.changelog.tip()) |
2566 |
2868 |
2567 @command("qcommit|qci", |
2869 |
2568 commands.table["commit|ci"][1], |
2870 @command( |
2569 _('hg qcommit [OPTION]... [FILE]...'), |
2871 "qcommit|qci", |
2570 helpcategory=command.CATEGORY_COMMITTING, |
2872 commands.table["commit|ci"][1], |
2571 inferrepo=True) |
2873 _('hg qcommit [OPTION]... [FILE]...'), |
|
2874 helpcategory=command.CATEGORY_COMMITTING, |
|
2875 inferrepo=True, |
|
2876 ) |
2572 def commit(ui, repo, *pats, **opts): |
2877 def commit(ui, repo, *pats, **opts): |
2573 """commit changes in the queue repository (DEPRECATED) |
2878 """commit changes in the queue repository (DEPRECATED) |
2574 |
2879 |
2575 This command is deprecated; use :hg:`commit --mq` instead.""" |
2880 This command is deprecated; use :hg:`commit --mq` instead.""" |
2576 q = repo.mq |
2881 q = repo.mq |
2577 r = q.qrepo() |
2882 r = q.qrepo() |
2578 if not r: |
2883 if not r: |
2579 raise error.Abort('no queue repository') |
2884 raise error.Abort('no queue repository') |
2580 commands.commit(r.ui, r, *pats, **opts) |
2885 commands.commit(r.ui, r, *pats, **opts) |
2581 |
2886 |
2582 @command("qseries", |
2887 |
2583 [('m', 'missing', None, _('print patches not in series')), |
2888 @command( |
2584 ] + seriesopts, |
2889 "qseries", |
2585 _('hg qseries [-ms]'), |
2890 [('m', 'missing', None, _('print patches not in series')),] + seriesopts, |
2586 helpcategory=command.CATEGORY_CHANGE_ORGANIZATION) |
2891 _('hg qseries [-ms]'), |
|
2892 helpcategory=command.CATEGORY_CHANGE_ORGANIZATION, |
|
2893 ) |
2587 def series(ui, repo, **opts): |
2894 def series(ui, repo, **opts): |
2588 """print the entire series file |
2895 """print the entire series file |
2589 |
2896 |
2590 Returns 0 on success.""" |
2897 Returns 0 on success.""" |
2591 repo.mq.qseries(repo, missing=opts.get(r'missing'), |
2898 repo.mq.qseries( |
2592 summary=opts.get(r'summary')) |
2899 repo, missing=opts.get(r'missing'), summary=opts.get(r'summary') |
|
2900 ) |
2593 return 0 |
2901 return 0 |
2594 |
2902 |
2595 @command("qtop", seriesopts, _('hg qtop [-s]'), |
2903 |
2596 helpcategory=command.CATEGORY_CHANGE_ORGANIZATION) |
2904 @command( |
|
2905 "qtop", |
|
2906 seriesopts, |
|
2907 _('hg qtop [-s]'), |
|
2908 helpcategory=command.CATEGORY_CHANGE_ORGANIZATION, |
|
2909 ) |
2597 def top(ui, repo, **opts): |
2910 def top(ui, repo, **opts): |
2598 """print the name of the current patch |
2911 """print the name of the current patch |
2599 |
2912 |
2600 Returns 0 on success.""" |
2913 Returns 0 on success.""" |
2601 q = repo.mq |
2914 q = repo.mq |
2637 return 1 |
2965 return 1 |
2638 if not l: |
2966 if not l: |
2639 ui.write(_("no patches applied\n")) |
2967 ui.write(_("no patches applied\n")) |
2640 return 1 |
2968 return 1 |
2641 idx = q.series.index(q.applied[-2].name) |
2969 idx = q.series.index(q.applied[-2].name) |
2642 q.qseries(repo, start=idx, length=1, status='A', |
2970 q.qseries( |
2643 summary=opts.get(r'summary')) |
2971 repo, start=idx, length=1, status='A', summary=opts.get(r'summary') |
|
2972 ) |
|
2973 |
2644 |
2974 |
2645 def setupheaderopts(ui, opts): |
2975 def setupheaderopts(ui, opts): |
2646 if not opts.get('user') and opts.get('currentuser'): |
2976 if not opts.get('user') and opts.get('currentuser'): |
2647 opts['user'] = ui.username() |
2977 opts['user'] = ui.username() |
2648 if not opts.get('date') and opts.get('currentdate'): |
2978 if not opts.get('date') and opts.get('currentdate'): |
2649 opts['date'] = "%d %d" % dateutil.makedate() |
2979 opts['date'] = "%d %d" % dateutil.makedate() |
2650 |
2980 |
2651 @command("qnew", |
2981 |
2652 [('e', 'edit', None, _('invoke editor on commit messages')), |
2982 @command( |
2653 ('f', 'force', None, _('import uncommitted changes (DEPRECATED)')), |
2983 "qnew", |
2654 ('g', 'git', None, _('use git extended diff format')), |
2984 [ |
2655 ('U', 'currentuser', None, _('add "From: <current user>" to patch')), |
2985 ('e', 'edit', None, _('invoke editor on commit messages')), |
2656 ('u', 'user', '', |
2986 ('f', 'force', None, _('import uncommitted changes (DEPRECATED)')), |
2657 _('add "From: <USER>" to patch'), _('USER')), |
2987 ('g', 'git', None, _('use git extended diff format')), |
2658 ('D', 'currentdate', None, _('add "Date: <current date>" to patch')), |
2988 ('U', 'currentuser', None, _('add "From: <current user>" to patch')), |
2659 ('d', 'date', '', |
2989 ('u', 'user', '', _('add "From: <USER>" to patch'), _('USER')), |
2660 _('add "Date: <DATE>" to patch'), _('DATE')) |
2990 ('D', 'currentdate', None, _('add "Date: <current date>" to patch')), |
2661 ] + cmdutil.walkopts + cmdutil.commitopts, |
2991 ('d', 'date', '', _('add "Date: <DATE>" to patch'), _('DATE')), |
2662 _('hg qnew [-e] [-m TEXT] [-l FILE] PATCH [FILE]...'), |
2992 ] |
2663 helpcategory=command.CATEGORY_COMMITTING, helpbasic=True, |
2993 + cmdutil.walkopts |
2664 inferrepo=True) |
2994 + cmdutil.commitopts, |
|
2995 _('hg qnew [-e] [-m TEXT] [-l FILE] PATCH [FILE]...'), |
|
2996 helpcategory=command.CATEGORY_COMMITTING, |
|
2997 helpbasic=True, |
|
2998 inferrepo=True, |
|
2999 ) |
2665 def new(ui, repo, patch, *args, **opts): |
3000 def new(ui, repo, patch, *args, **opts): |
2666 """create a new patch |
3001 """create a new patch |
2667 |
3002 |
2668 qnew creates a new patch on top of the currently-applied patch (if |
3003 qnew creates a new patch on top of the currently-applied patch (if |
2669 any). The patch will be initialized with any outstanding changes |
3004 any). The patch will be initialized with any outstanding changes |
2694 setupheaderopts(ui, opts) |
3029 setupheaderopts(ui, opts) |
2695 q.new(repo, patch, *args, **pycompat.strkwargs(opts)) |
3030 q.new(repo, patch, *args, **pycompat.strkwargs(opts)) |
2696 q.savedirty() |
3031 q.savedirty() |
2697 return 0 |
3032 return 0 |
2698 |
3033 |
2699 @command("qrefresh", |
3034 |
2700 [('e', 'edit', None, _('invoke editor on commit messages')), |
3035 @command( |
2701 ('g', 'git', None, _('use git extended diff format')), |
3036 "qrefresh", |
2702 ('s', 'short', None, |
3037 [ |
2703 _('refresh only files already in the patch and specified files')), |
3038 ('e', 'edit', None, _('invoke editor on commit messages')), |
2704 ('U', 'currentuser', None, |
3039 ('g', 'git', None, _('use git extended diff format')), |
2705 _('add/update author field in patch with current user')), |
3040 ( |
2706 ('u', 'user', '', |
3041 's', |
2707 _('add/update author field in patch with given user'), _('USER')), |
3042 'short', |
2708 ('D', 'currentdate', None, |
3043 None, |
2709 _('add/update date field in patch with current date')), |
3044 _('refresh only files already in the patch and specified files'), |
2710 ('d', 'date', '', |
3045 ), |
2711 _('add/update date field in patch with given date'), _('DATE')) |
3046 ( |
2712 ] + cmdutil.walkopts + cmdutil.commitopts, |
3047 'U', |
2713 _('hg qrefresh [-I] [-X] [-e] [-m TEXT] [-l FILE] [-s] [FILE]...'), |
3048 'currentuser', |
2714 helpcategory=command.CATEGORY_COMMITTING, helpbasic=True, |
3049 None, |
2715 inferrepo=True) |
3050 _('add/update author field in patch with current user'), |
|
3051 ), |
|
3052 ( |
|
3053 'u', |
|
3054 'user', |
|
3055 '', |
|
3056 _('add/update author field in patch with given user'), |
|
3057 _('USER'), |
|
3058 ), |
|
3059 ( |
|
3060 'D', |
|
3061 'currentdate', |
|
3062 None, |
|
3063 _('add/update date field in patch with current date'), |
|
3064 ), |
|
3065 ( |
|
3066 'd', |
|
3067 'date', |
|
3068 '', |
|
3069 _('add/update date field in patch with given date'), |
|
3070 _('DATE'), |
|
3071 ), |
|
3072 ] |
|
3073 + cmdutil.walkopts |
|
3074 + cmdutil.commitopts, |
|
3075 _('hg qrefresh [-I] [-X] [-e] [-m TEXT] [-l FILE] [-s] [FILE]...'), |
|
3076 helpcategory=command.CATEGORY_COMMITTING, |
|
3077 helpbasic=True, |
|
3078 inferrepo=True, |
|
3079 ) |
2716 def refresh(ui, repo, *pats, **opts): |
3080 def refresh(ui, repo, *pats, **opts): |
2717 """update the current patch |
3081 """update the current patch |
2718 |
3082 |
2719 If any file patterns are provided, the refreshed patch will |
3083 If any file patterns are provided, the refreshed patch will |
2720 contain only the modifications that match those patterns; the |
3084 contain only the modifications that match those patterns; the |
2741 with repo.wlock(): |
3105 with repo.wlock(): |
2742 ret = q.refresh(repo, pats, msg=message, **pycompat.strkwargs(opts)) |
3106 ret = q.refresh(repo, pats, msg=message, **pycompat.strkwargs(opts)) |
2743 q.savedirty() |
3107 q.savedirty() |
2744 return ret |
3108 return ret |
2745 |
3109 |
2746 @command("qdiff", |
3110 |
2747 cmdutil.diffopts + cmdutil.diffopts2 + cmdutil.walkopts, |
3111 @command( |
2748 _('hg qdiff [OPTION]... [FILE]...'), |
3112 "qdiff", |
2749 helpcategory=command.CATEGORY_FILE_CONTENTS, helpbasic=True, |
3113 cmdutil.diffopts + cmdutil.diffopts2 + cmdutil.walkopts, |
2750 inferrepo=True) |
3114 _('hg qdiff [OPTION]... [FILE]...'), |
|
3115 helpcategory=command.CATEGORY_FILE_CONTENTS, |
|
3116 helpbasic=True, |
|
3117 inferrepo=True, |
|
3118 ) |
2751 def diff(ui, repo, *pats, **opts): |
3119 def diff(ui, repo, *pats, **opts): |
2752 """diff of the current patch and subsequent modifications |
3120 """diff of the current patch and subsequent modifications |
2753 |
3121 |
2754 Shows a diff which includes the current patch as well as any |
3122 Shows a diff which includes the current patch as well as any |
2755 changes which have been made in the working directory since the |
3123 changes which have been made in the working directory since the |
2765 """ |
3133 """ |
2766 ui.pager('qdiff') |
3134 ui.pager('qdiff') |
2767 repo.mq.diff(repo, pats, pycompat.byteskwargs(opts)) |
3135 repo.mq.diff(repo, pats, pycompat.byteskwargs(opts)) |
2768 return 0 |
3136 return 0 |
2769 |
3137 |
2770 @command('qfold', |
3138 |
2771 [('e', 'edit', None, _('invoke editor on commit messages')), |
3139 @command( |
2772 ('k', 'keep', None, _('keep folded patch files')), |
3140 'qfold', |
2773 ] + cmdutil.commitopts, |
3141 [ |
2774 _('hg qfold [-e] [-k] [-m TEXT] [-l FILE] PATCH...'), |
3142 ('e', 'edit', None, _('invoke editor on commit messages')), |
2775 helpcategory=command.CATEGORY_CHANGE_MANAGEMENT) |
3143 ('k', 'keep', None, _('keep folded patch files')), |
|
3144 ] |
|
3145 + cmdutil.commitopts, |
|
3146 _('hg qfold [-e] [-k] [-m TEXT] [-l FILE] PATCH...'), |
|
3147 helpcategory=command.CATEGORY_CHANGE_MANAGEMENT, |
|
3148 ) |
2776 def fold(ui, repo, *files, **opts): |
3149 def fold(ui, repo, *files, **opts): |
2777 """fold the named patches into the current patch |
3150 """fold the named patches into the current patch |
2778 |
3151 |
2779 Patches must not yet be applied. Each patch will be successively |
3152 Patches must not yet be applied. Each patch will be successively |
2780 applied to the current patch in the order given. If all the |
3153 applied to the current patch in the order given. If all the |
2829 message.extend(msg) |
3203 message.extend(msg) |
2830 message = '\n'.join(message) |
3204 message = '\n'.join(message) |
2831 |
3205 |
2832 diffopts = q.patchopts(q.diffopts(), *patches) |
3206 diffopts = q.patchopts(q.diffopts(), *patches) |
2833 with repo.wlock(): |
3207 with repo.wlock(): |
2834 q.refresh(repo, msg=message, git=diffopts.git, edit=opts.get('edit'), |
3208 q.refresh( |
2835 editform='mq.qfold') |
3209 repo, |
|
3210 msg=message, |
|
3211 git=diffopts.git, |
|
3212 edit=opts.get('edit'), |
|
3213 editform='mq.qfold', |
|
3214 ) |
2836 q.delete(repo, patches, opts) |
3215 q.delete(repo, patches, opts) |
2837 q.savedirty() |
3216 q.savedirty() |
2838 |
3217 |
2839 @command("qgoto", |
3218 |
2840 [('', 'keep-changes', None, |
3219 @command( |
2841 _('tolerate non-conflicting local changes')), |
3220 "qgoto", |
2842 ('f', 'force', None, _('overwrite any local changes')), |
3221 [ |
2843 ('', 'no-backup', None, _('do not save backup copies of files'))], |
3222 ('', 'keep-changes', None, _('tolerate non-conflicting local changes')), |
2844 _('hg qgoto [OPTION]... PATCH'), |
3223 ('f', 'force', None, _('overwrite any local changes')), |
2845 helpcategory=command.CATEGORY_CHANGE_ORGANIZATION) |
3224 ('', 'no-backup', None, _('do not save backup copies of files')), |
|
3225 ], |
|
3226 _('hg qgoto [OPTION]... PATCH'), |
|
3227 helpcategory=command.CATEGORY_CHANGE_ORGANIZATION, |
|
3228 ) |
2846 def goto(ui, repo, patch, **opts): |
3229 def goto(ui, repo, patch, **opts): |
2847 '''push or pop patches until named patch is at top of stack |
3230 '''push or pop patches until named patch is at top of stack |
2848 |
3231 |
2849 Returns 0 on success.''' |
3232 Returns 0 on success.''' |
2850 opts = pycompat.byteskwargs(opts) |
3233 opts = pycompat.byteskwargs(opts) |
2852 q = repo.mq |
3235 q = repo.mq |
2853 patch = q.lookup(patch) |
3236 patch = q.lookup(patch) |
2854 nobackup = opts.get('no_backup') |
3237 nobackup = opts.get('no_backup') |
2855 keepchanges = opts.get('keep_changes') |
3238 keepchanges = opts.get('keep_changes') |
2856 if q.isapplied(patch): |
3239 if q.isapplied(patch): |
2857 ret = q.pop(repo, patch, force=opts.get('force'), nobackup=nobackup, |
3240 ret = q.pop( |
2858 keepchanges=keepchanges) |
3241 repo, |
|
3242 patch, |
|
3243 force=opts.get('force'), |
|
3244 nobackup=nobackup, |
|
3245 keepchanges=keepchanges, |
|
3246 ) |
2859 else: |
3247 else: |
2860 ret = q.push(repo, patch, force=opts.get('force'), nobackup=nobackup, |
3248 ret = q.push( |
2861 keepchanges=keepchanges) |
3249 repo, |
|
3250 patch, |
|
3251 force=opts.get('force'), |
|
3252 nobackup=nobackup, |
|
3253 keepchanges=keepchanges, |
|
3254 ) |
2862 q.savedirty() |
3255 q.savedirty() |
2863 return ret |
3256 return ret |
2864 |
3257 |
2865 @command("qguard", |
3258 |
2866 [('l', 'list', None, _('list all patches and guards')), |
3259 @command( |
2867 ('n', 'none', None, _('drop all guards'))], |
3260 "qguard", |
2868 _('hg qguard [-l] [-n] [PATCH] [-- [+GUARD]... [-GUARD]...]'), |
3261 [ |
2869 helpcategory=command.CATEGORY_CHANGE_ORGANIZATION) |
3262 ('l', 'list', None, _('list all patches and guards')), |
|
3263 ('n', 'none', None, _('drop all guards')), |
|
3264 ], |
|
3265 _('hg qguard [-l] [-n] [PATCH] [-- [+GUARD]... [-GUARD]...]'), |
|
3266 helpcategory=command.CATEGORY_CHANGE_ORGANIZATION, |
|
3267 ) |
2870 def guard(ui, repo, *args, **opts): |
3268 def guard(ui, repo, *args, **opts): |
2871 '''set or print guards for a patch |
3269 '''set or print guards for a patch |
2872 |
3270 |
2873 Guards control whether a patch can be pushed. A patch with no |
3271 Guards control whether a patch can be pushed. A patch with no |
2874 guards is always pushed. A patch with a positive guard ("+foo") is |
3272 guards is always pushed. A patch with a positive guard ("+foo") is |
2972 maxname = f |
3379 maxname = f |
2973 if maxname: |
3380 if maxname: |
2974 return (os.path.join(directory, maxname), maxindex) |
3381 return (os.path.join(directory, maxname), maxindex) |
2975 return (None, None) |
3382 return (None, None) |
2976 |
3383 |
|
3384 |
2977 def savename(path): |
3385 def savename(path): |
2978 (last, index) = lastsavename(path) |
3386 (last, index) = lastsavename(path) |
2979 if last is None: |
3387 if last is None: |
2980 index = 0 |
3388 index = 0 |
2981 newpath = path + ".%d" % (index + 1) |
3389 newpath = path + ".%d" % (index + 1) |
2982 return newpath |
3390 return newpath |
2983 |
3391 |
2984 @command("qpush", |
3392 |
2985 [('', 'keep-changes', None, |
3393 @command( |
2986 _('tolerate non-conflicting local changes')), |
3394 "qpush", |
2987 ('f', 'force', None, _('apply on top of local changes')), |
3395 [ |
2988 ('e', 'exact', None, |
3396 ('', 'keep-changes', None, _('tolerate non-conflicting local changes')), |
2989 _('apply the target patch to its recorded parent')), |
3397 ('f', 'force', None, _('apply on top of local changes')), |
2990 ('l', 'list', None, _('list patch name in commit text')), |
3398 ( |
2991 ('a', 'all', None, _('apply all patches')), |
3399 'e', |
2992 ('m', 'merge', None, _('merge from another queue (DEPRECATED)')), |
3400 'exact', |
2993 ('n', 'name', '', |
3401 None, |
2994 _('merge queue name (DEPRECATED)'), _('NAME')), |
3402 _('apply the target patch to its recorded parent'), |
2995 ('', 'move', None, |
3403 ), |
2996 _('reorder patch series and apply only the patch')), |
3404 ('l', 'list', None, _('list patch name in commit text')), |
2997 ('', 'no-backup', None, _('do not save backup copies of files'))], |
3405 ('a', 'all', None, _('apply all patches')), |
2998 _('hg qpush [-f] [-l] [-a] [--move] [PATCH | INDEX]'), |
3406 ('m', 'merge', None, _('merge from another queue (DEPRECATED)')), |
2999 helpcategory=command.CATEGORY_CHANGE_ORGANIZATION, |
3407 ('n', 'name', '', _('merge queue name (DEPRECATED)'), _('NAME')), |
3000 helpbasic=True) |
3408 ('', 'move', None, _('reorder patch series and apply only the patch')), |
|
3409 ('', 'no-backup', None, _('do not save backup copies of files')), |
|
3410 ], |
|
3411 _('hg qpush [-f] [-l] [-a] [--move] [PATCH | INDEX]'), |
|
3412 helpcategory=command.CATEGORY_CHANGE_ORGANIZATION, |
|
3413 helpbasic=True, |
|
3414 ) |
3001 def push(ui, repo, patch=None, **opts): |
3415 def push(ui, repo, patch=None, **opts): |
3002 """push the next patch onto the stack |
3416 """push the next patch onto the stack |
3003 |
3417 |
3004 By default, abort if the working directory contains uncommitted |
3418 By default, abort if the working directory contains uncommitted |
3005 changes. With --keep-changes, abort only if the uncommitted files |
3419 changes. With --keep-changes, abort only if the uncommitted files |
3021 if not newpath: |
3435 if not newpath: |
3022 ui.warn(_("no saved queues found, please use -n\n")) |
3436 ui.warn(_("no saved queues found, please use -n\n")) |
3023 return 1 |
3437 return 1 |
3024 mergeq = queue(ui, repo.baseui, repo.path, newpath) |
3438 mergeq = queue(ui, repo.baseui, repo.path, newpath) |
3025 ui.warn(_("merging with queue at: %s\n") % mergeq.path) |
3439 ui.warn(_("merging with queue at: %s\n") % mergeq.path) |
3026 ret = q.push(repo, patch, force=opts.get('force'), list=opts.get('list'), |
3440 ret = q.push( |
3027 mergeq=mergeq, all=opts.get('all'), move=opts.get('move'), |
3441 repo, |
3028 exact=opts.get('exact'), nobackup=opts.get('no_backup'), |
3442 patch, |
3029 keepchanges=opts.get('keep_changes')) |
3443 force=opts.get('force'), |
|
3444 list=opts.get('list'), |
|
3445 mergeq=mergeq, |
|
3446 all=opts.get('all'), |
|
3447 move=opts.get('move'), |
|
3448 exact=opts.get('exact'), |
|
3449 nobackup=opts.get('no_backup'), |
|
3450 keepchanges=opts.get('keep_changes'), |
|
3451 ) |
3030 return ret |
3452 return ret |
3031 |
3453 |
3032 @command("qpop", |
3454 |
3033 [('a', 'all', None, _('pop all patches')), |
3455 @command( |
3034 ('n', 'name', '', |
3456 "qpop", |
3035 _('queue name to pop (DEPRECATED)'), _('NAME')), |
3457 [ |
3036 ('', 'keep-changes', None, |
3458 ('a', 'all', None, _('pop all patches')), |
3037 _('tolerate non-conflicting local changes')), |
3459 ('n', 'name', '', _('queue name to pop (DEPRECATED)'), _('NAME')), |
3038 ('f', 'force', None, _('forget any local changes to patched files')), |
3460 ('', 'keep-changes', None, _('tolerate non-conflicting local changes')), |
3039 ('', 'no-backup', None, _('do not save backup copies of files'))], |
3461 ('f', 'force', None, _('forget any local changes to patched files')), |
3040 _('hg qpop [-a] [-f] [PATCH | INDEX]'), |
3462 ('', 'no-backup', None, _('do not save backup copies of files')), |
3041 helpcategory=command.CATEGORY_CHANGE_ORGANIZATION, |
3463 ], |
3042 helpbasic=True) |
3464 _('hg qpop [-a] [-f] [PATCH | INDEX]'), |
|
3465 helpcategory=command.CATEGORY_CHANGE_ORGANIZATION, |
|
3466 helpbasic=True, |
|
3467 ) |
3043 def pop(ui, repo, patch=None, **opts): |
3468 def pop(ui, repo, patch=None, **opts): |
3044 """pop the current patch off the stack |
3469 """pop the current patch off the stack |
3045 |
3470 |
3046 Without argument, pops off the top of the patch stack. If given a |
3471 Without argument, pops off the top of the patch stack. If given a |
3047 patch name, keeps popping off patches until the named patch is at |
3472 patch name, keeps popping off patches until the named patch is at |
3061 q = queue(ui, repo.baseui, repo.path, repo.vfs.join(opts.get('name'))) |
3486 q = queue(ui, repo.baseui, repo.path, repo.vfs.join(opts.get('name'))) |
3062 ui.warn(_('using patch queue: %s\n') % q.path) |
3487 ui.warn(_('using patch queue: %s\n') % q.path) |
3063 localupdate = False |
3488 localupdate = False |
3064 else: |
3489 else: |
3065 q = repo.mq |
3490 q = repo.mq |
3066 ret = q.pop(repo, patch, force=opts.get('force'), update=localupdate, |
3491 ret = q.pop( |
3067 all=opts.get('all'), nobackup=opts.get('no_backup'), |
3492 repo, |
3068 keepchanges=opts.get('keep_changes')) |
3493 patch, |
|
3494 force=opts.get('force'), |
|
3495 update=localupdate, |
|
3496 all=opts.get('all'), |
|
3497 nobackup=opts.get('no_backup'), |
|
3498 keepchanges=opts.get('keep_changes'), |
|
3499 ) |
3069 q.savedirty() |
3500 q.savedirty() |
3070 return ret |
3501 return ret |
3071 |
3502 |
3072 @command("qrename|qmv", [], _('hg qrename PATCH1 [PATCH2]'), |
3503 |
3073 helpcategory=command.CATEGORY_CHANGE_ORGANIZATION) |
3504 @command( |
|
3505 "qrename|qmv", |
|
3506 [], |
|
3507 _('hg qrename PATCH1 [PATCH2]'), |
|
3508 helpcategory=command.CATEGORY_CHANGE_ORGANIZATION, |
|
3509 ) |
3074 def rename(ui, repo, patch, name=None, **opts): |
3510 def rename(ui, repo, patch, name=None, **opts): |
3075 """rename a patch |
3511 """rename a patch |
3076 |
3512 |
3077 With one argument, renames the current patch to PATCH1. |
3513 With one argument, renames the current patch to PATCH1. |
3078 With two arguments, renames PATCH1 to PATCH2. |
3514 With two arguments, renames PATCH1 to PATCH2. |
3123 wctx.copy(patch, name) |
3559 wctx.copy(patch, name) |
3124 wctx.forget([patch]) |
3560 wctx.forget([patch]) |
3125 |
3561 |
3126 q.savedirty() |
3562 q.savedirty() |
3127 |
3563 |
3128 @command("qrestore", |
3564 |
3129 [('d', 'delete', None, _('delete save entry')), |
3565 @command( |
3130 ('u', 'update', None, _('update queue working directory'))], |
3566 "qrestore", |
3131 _('hg qrestore [-d] [-u] REV'), |
3567 [ |
3132 helpcategory=command.CATEGORY_CHANGE_ORGANIZATION) |
3568 ('d', 'delete', None, _('delete save entry')), |
|
3569 ('u', 'update', None, _('update queue working directory')), |
|
3570 ], |
|
3571 _('hg qrestore [-d] [-u] REV'), |
|
3572 helpcategory=command.CATEGORY_CHANGE_ORGANIZATION, |
|
3573 ) |
3133 def restore(ui, repo, rev, **opts): |
3574 def restore(ui, repo, rev, **opts): |
3134 """restore the queue state saved by a revision (DEPRECATED) |
3575 """restore the queue state saved by a revision (DEPRECATED) |
3135 |
3576 |
3136 This command is deprecated, use :hg:`rebase` instead.""" |
3577 This command is deprecated, use :hg:`rebase` instead.""" |
3137 rev = repo.lookup(rev) |
3578 rev = repo.lookup(rev) |
3138 q = repo.mq |
3579 q = repo.mq |
3139 q.restore(repo, rev, delete=opts.get(r'delete'), |
3580 q.restore( |
3140 qupdate=opts.get(r'update')) |
3581 repo, rev, delete=opts.get(r'delete'), qupdate=opts.get(r'update') |
|
3582 ) |
3141 q.savedirty() |
3583 q.savedirty() |
3142 return 0 |
3584 return 0 |
3143 |
3585 |
3144 @command("qsave", |
3586 |
3145 [('c', 'copy', None, _('copy patch directory')), |
3587 @command( |
3146 ('n', 'name', '', |
3588 "qsave", |
3147 _('copy directory name'), _('NAME')), |
3589 [ |
3148 ('e', 'empty', None, _('clear queue status file')), |
3590 ('c', 'copy', None, _('copy patch directory')), |
3149 ('f', 'force', None, _('force copy'))] + cmdutil.commitopts, |
3591 ('n', 'name', '', _('copy directory name'), _('NAME')), |
3150 _('hg qsave [-m TEXT] [-l FILE] [-c] [-n NAME] [-e] [-f]'), |
3592 ('e', 'empty', None, _('clear queue status file')), |
3151 helpcategory=command.CATEGORY_CHANGE_ORGANIZATION) |
3593 ('f', 'force', None, _('force copy')), |
|
3594 ] |
|
3595 + cmdutil.commitopts, |
|
3596 _('hg qsave [-m TEXT] [-l FILE] [-c] [-n NAME] [-e] [-f]'), |
|
3597 helpcategory=command.CATEGORY_CHANGE_ORGANIZATION, |
|
3598 ) |
3152 def save(ui, repo, **opts): |
3599 def save(ui, repo, **opts): |
3153 """save current queue state (DEPRECATED) |
3600 """save current queue state (DEPRECATED) |
3154 |
3601 |
3155 This command is deprecated, use :hg:`rebase` instead.""" |
3602 This command is deprecated, use :hg:`rebase` instead.""" |
3156 q = repo.mq |
3603 q = repo.mq |
3157 opts = pycompat.byteskwargs(opts) |
3604 opts = pycompat.byteskwargs(opts) |
3158 message = cmdutil.logmessage(ui, opts) |
3605 message = cmdutil.logmessage(ui, opts) |
3159 ret = q.save(repo, msg=message) |
3606 ret = q.save(repo, msg=message) |
3160 if ret: |
3607 if ret: |
3161 return ret |
3608 return ret |
3162 q.savedirty() # save to .hg/patches before copying |
3609 q.savedirty() # save to .hg/patches before copying |
3163 if opts.get('copy'): |
3610 if opts.get('copy'): |
3164 path = q.path |
3611 path = q.path |
3165 if opts.get('name'): |
3612 if opts.get('name'): |
3166 newpath = os.path.join(q.basepath, opts.get('name')) |
3613 newpath = os.path.join(q.basepath, opts.get('name')) |
3167 if os.path.exists(newpath): |
3614 if os.path.exists(newpath): |
3168 if not os.path.isdir(newpath): |
3615 if not os.path.isdir(newpath): |
3169 raise error.Abort(_('destination %s exists and is not ' |
3616 raise error.Abort( |
3170 'a directory') % newpath) |
3617 _('destination %s exists and is not ' 'a directory') |
|
3618 % newpath |
|
3619 ) |
3171 if not opts.get('force'): |
3620 if not opts.get('force'): |
3172 raise error.Abort(_('destination %s exists, ' |
3621 raise error.Abort( |
3173 'use -f to force') % newpath) |
3622 _('destination %s exists, ' 'use -f to force') % newpath |
|
3623 ) |
3174 else: |
3624 else: |
3175 newpath = savename(path) |
3625 newpath = savename(path) |
3176 ui.warn(_("copy %s to %s\n") % (path, newpath)) |
3626 ui.warn(_("copy %s to %s\n") % (path, newpath)) |
3177 util.copyfiles(path, newpath) |
3627 util.copyfiles(path, newpath) |
3178 if opts.get('empty'): |
3628 if opts.get('empty'): |
3180 q.applieddirty = True |
3630 q.applieddirty = True |
3181 q.savedirty() |
3631 q.savedirty() |
3182 return 0 |
3632 return 0 |
3183 |
3633 |
3184 |
3634 |
3185 @command("qselect", |
3635 @command( |
3186 [('n', 'none', None, _('disable all guards')), |
3636 "qselect", |
3187 ('s', 'series', None, _('list all guards in series file')), |
3637 [ |
3188 ('', 'pop', None, _('pop to before first guarded applied patch')), |
3638 ('n', 'none', None, _('disable all guards')), |
3189 ('', 'reapply', None, _('pop, then reapply patches'))], |
3639 ('s', 'series', None, _('list all guards in series file')), |
3190 _('hg qselect [OPTION]... [GUARD]...'), |
3640 ('', 'pop', None, _('pop to before first guarded applied patch')), |
3191 helpcategory=command.CATEGORY_CHANGE_ORGANIZATION) |
3641 ('', 'reapply', None, _('pop, then reapply patches')), |
|
3642 ], |
|
3643 _('hg qselect [OPTION]... [GUARD]...'), |
|
3644 helpcategory=command.CATEGORY_CHANGE_ORGANIZATION, |
|
3645 ) |
3192 def select(ui, repo, *args, **opts): |
3646 def select(ui, repo, *args, **opts): |
3193 '''set or print guarded patches to push |
3647 '''set or print guarded patches to push |
3194 |
3648 |
3195 Use the :hg:`qguard` command to set or print guards on patch, then use |
3649 Use the :hg:`qguard` command to set or print guards on patch, then use |
3196 qselect to tell mq which guards to use. A patch will be pushed if |
3650 qselect to tell mq which guards to use. A patch will be pushed if |
3228 opts = pycompat.byteskwargs(opts) |
3682 opts = pycompat.byteskwargs(opts) |
3229 guards = q.active() |
3683 guards = q.active() |
3230 pushable = lambda i: q.pushable(q.applied[i].name)[0] |
3684 pushable = lambda i: q.pushable(q.applied[i].name)[0] |
3231 if args or opts.get('none'): |
3685 if args or opts.get('none'): |
3232 old_unapplied = q.unapplied(repo) |
3686 old_unapplied = q.unapplied(repo) |
3233 old_guarded = [i for i in pycompat.xrange(len(q.applied)) |
3687 old_guarded = [ |
3234 if not pushable(i)] |
3688 i for i in pycompat.xrange(len(q.applied)) if not pushable(i) |
|
3689 ] |
3235 q.setactive(args) |
3690 q.setactive(args) |
3236 q.savedirty() |
3691 q.savedirty() |
3237 if not args: |
3692 if not args: |
3238 ui.status(_('guards deactivated\n')) |
3693 ui.status(_('guards deactivated\n')) |
3239 if not opts.get('pop') and not opts.get('reapply'): |
3694 if not opts.get('pop') and not opts.get('reapply'): |
3240 unapplied = q.unapplied(repo) |
3695 unapplied = q.unapplied(repo) |
3241 guarded = [i for i in pycompat.xrange(len(q.applied)) |
3696 guarded = [ |
3242 if not pushable(i)] |
3697 i for i in pycompat.xrange(len(q.applied)) if not pushable(i) |
|
3698 ] |
3243 if len(unapplied) != len(old_unapplied): |
3699 if len(unapplied) != len(old_unapplied): |
3244 ui.status(_('number of unguarded, unapplied patches has ' |
3700 ui.status( |
3245 'changed from %d to %d\n') % |
3701 _( |
3246 (len(old_unapplied), len(unapplied))) |
3702 'number of unguarded, unapplied patches has ' |
|
3703 'changed from %d to %d\n' |
|
3704 ) |
|
3705 % (len(old_unapplied), len(unapplied)) |
|
3706 ) |
3247 if len(guarded) != len(old_guarded): |
3707 if len(guarded) != len(old_guarded): |
3248 ui.status(_('number of guarded, applied patches has changed ' |
3708 ui.status( |
3249 'from %d to %d\n') % |
3709 _( |
3250 (len(old_guarded), len(guarded))) |
3710 'number of guarded, applied patches has changed ' |
|
3711 'from %d to %d\n' |
|
3712 ) |
|
3713 % (len(old_guarded), len(guarded)) |
|
3714 ) |
3251 elif opts.get('series'): |
3715 elif opts.get('series'): |
3252 guards = {} |
3716 guards = {} |
3253 noguards = 0 |
3717 noguards = 0 |
3254 for gs in q.seriesguards: |
3718 for gs in q.seriesguards: |
3255 if not gs: |
3719 if not gs: |
3293 ui.status(_('reapplying unguarded patches\n')) |
3757 ui.status(_('reapplying unguarded patches\n')) |
3294 q.push(repo, reapply) |
3758 q.push(repo, reapply) |
3295 finally: |
3759 finally: |
3296 q.savedirty() |
3760 q.savedirty() |
3297 |
3761 |
3298 @command("qfinish", |
3762 |
3299 [('a', 'applied', None, _('finish all applied changesets'))], |
3763 @command( |
3300 _('hg qfinish [-a] [REV]...'), |
3764 "qfinish", |
3301 helpcategory=command.CATEGORY_CHANGE_ORGANIZATION) |
3765 [('a', 'applied', None, _('finish all applied changesets'))], |
|
3766 _('hg qfinish [-a] [REV]...'), |
|
3767 helpcategory=command.CATEGORY_CHANGE_ORGANIZATION, |
|
3768 ) |
3302 def finish(ui, repo, *revrange, **opts): |
3769 def finish(ui, repo, *revrange, **opts): |
3303 """move applied patches into repository history |
3770 """move applied patches into repository history |
3304 |
3771 |
3305 Finishes the specified revisions (corresponding to applied |
3772 Finishes the specified revisions (corresponding to applied |
3306 patches) by moving them out of mq control into regular repository |
3773 patches) by moving them out of mq control into regular repository |
3336 with repo.lock(): |
3803 with repo.lock(): |
3337 q.finish(repo, revs) |
3804 q.finish(repo, revs) |
3338 q.savedirty() |
3805 q.savedirty() |
3339 return 0 |
3806 return 0 |
3340 |
3807 |
3341 @command("qqueue", |
3808 |
3342 [('l', 'list', False, _('list all available queues')), |
3809 @command( |
3343 ('', 'active', False, _('print name of active queue')), |
3810 "qqueue", |
3344 ('c', 'create', False, _('create new queue')), |
3811 [ |
3345 ('', 'rename', False, _('rename active queue')), |
3812 ('l', 'list', False, _('list all available queues')), |
3346 ('', 'delete', False, _('delete reference to queue')), |
3813 ('', 'active', False, _('print name of active queue')), |
3347 ('', 'purge', False, _('delete queue, and remove patch dir')), |
3814 ('c', 'create', False, _('create new queue')), |
3348 ], |
3815 ('', 'rename', False, _('rename active queue')), |
3349 _('[OPTION] [QUEUE]'), |
3816 ('', 'delete', False, _('delete reference to queue')), |
3350 helpcategory=command.CATEGORY_CHANGE_ORGANIZATION) |
3817 ('', 'purge', False, _('delete queue, and remove patch dir')), |
|
3818 ], |
|
3819 _('[OPTION] [QUEUE]'), |
|
3820 helpcategory=command.CATEGORY_CHANGE_ORGANIZATION, |
|
3821 ) |
3351 def qqueue(ui, repo, name=None, **opts): |
3822 def qqueue(ui, repo, name=None, **opts): |
3352 '''manage multiple patch queues |
3823 '''manage multiple patch queues |
3353 |
3824 |
3354 Supports switching between different patch queues, as well as creating |
3825 Supports switching between different patch queues, as well as creating |
3355 new patch queues and deleting existing ones. |
3826 new patch queues and deleting existing ones. |
3478 _addqueue(name) |
3954 _addqueue(name) |
3479 _setactive(name) |
3955 _setactive(name) |
3480 elif opts.get('rename'): |
3956 elif opts.get('rename'): |
3481 current = _getcurrent() |
3957 current = _getcurrent() |
3482 if name == current: |
3958 if name == current: |
3483 raise error.Abort(_('can\'t rename "%s" to its current name') |
3959 raise error.Abort( |
3484 % name) |
3960 _('can\'t rename "%s" to its current name') % name |
|
3961 ) |
3485 if name in existing: |
3962 if name in existing: |
3486 raise error.Abort(_('queue "%s" already exists') % name) |
3963 raise error.Abort(_('queue "%s" already exists') % name) |
3487 |
3964 |
3488 olddir = _queuedir(current) |
3965 olddir = _queuedir(current) |
3489 newdir = _queuedir(name) |
3966 newdir = _queuedir(name) |
3490 |
3967 |
3491 if os.path.exists(newdir): |
3968 if os.path.exists(newdir): |
3492 raise error.Abort(_('non-queue directory "%s" already exists') % |
3969 raise error.Abort( |
3493 newdir) |
3970 _('non-queue directory "%s" already exists') % newdir |
|
3971 ) |
3494 |
3972 |
3495 fh = repo.vfs('patches.queues.new', 'w') |
3973 fh = repo.vfs('patches.queues.new', 'w') |
3496 for queue in existing: |
3974 for queue in existing: |
3497 if queue == current: |
3975 if queue == current: |
3498 fh.write('%s\n' % (name,)) |
3976 fh.write('%s\n' % (name,)) |
3544 parents = self.dirstate.parents() |
4024 parents = self.dirstate.parents() |
3545 patches = [s.node for s in self.mq.applied] |
4025 patches = [s.node for s in self.mq.applied] |
3546 if any(p in patches for p in parents): |
4026 if any(p in patches for p in parents): |
3547 raise error.Abort(errmsg) |
4027 raise error.Abort(errmsg) |
3548 |
4028 |
3549 def commit(self, text="", user=None, date=None, match=None, |
4029 def commit( |
3550 force=False, editor=False, extra=None): |
4030 self, |
|
4031 text="", |
|
4032 user=None, |
|
4033 date=None, |
|
4034 match=None, |
|
4035 force=False, |
|
4036 editor=False, |
|
4037 extra=None, |
|
4038 ): |
3551 if extra is None: |
4039 if extra is None: |
3552 extra = {} |
4040 extra = {} |
3553 self.abortifwdirpatched( |
4041 self.abortifwdirpatched( |
3554 _('cannot commit over an applied mq patch'), |
4042 _('cannot commit over an applied mq patch'), force |
3555 force) |
4043 ) |
3556 |
4044 |
3557 return super(mqrepo, self).commit(text, user, date, match, force, |
4045 return super(mqrepo, self).commit( |
3558 editor, extra) |
4046 text, user, date, match, force, editor, extra |
|
4047 ) |
3559 |
4048 |
3560 def checkpush(self, pushop): |
4049 def checkpush(self, pushop): |
3561 if self.mq.applied and self.mq.checkapplied and not pushop.force: |
4050 if self.mq.applied and self.mq.checkapplied and not pushop.force: |
3562 outapplied = [e.node for e in self.mq.applied] |
4051 outapplied = [e.node for e in self.mq.applied] |
3563 if pushop.revs: |
4052 if pushop.revs: |
3605 mqtags.append((mqtags[0][0], 'qbase')) |
4096 mqtags.append((mqtags[0][0], 'qbase')) |
3606 mqtags.append((self.changelog.parents(mqtags[0][0])[0], 'qparent')) |
4097 mqtags.append((self.changelog.parents(mqtags[0][0])[0], 'qparent')) |
3607 tags = result[0] |
4098 tags = result[0] |
3608 for patch in mqtags: |
4099 for patch in mqtags: |
3609 if patch[1] in tags: |
4100 if patch[1] in tags: |
3610 self.ui.warn(_('tag %s overrides mq patch of the same ' |
4101 self.ui.warn( |
3611 'name\n') % patch[1]) |
4102 _('tag %s overrides mq patch of the same ' 'name\n') |
|
4103 % patch[1] |
|
4104 ) |
3612 else: |
4105 else: |
3613 tags[patch[1]] = patch[0] |
4106 tags[patch[1]] = patch[0] |
3614 |
4107 |
3615 return result |
4108 return result |
3616 |
4109 |
3617 if repo.local(): |
4110 if repo.local(): |
3618 repo.__class__ = mqrepo |
4111 repo.__class__ = mqrepo |
3619 |
4112 |
3620 repo._phasedefaults.append(mqphasedefaults) |
4113 repo._phasedefaults.append(mqphasedefaults) |
3621 |
4114 |
|
4115 |
3622 def mqimport(orig, ui, repo, *args, **kwargs): |
4116 def mqimport(orig, ui, repo, *args, **kwargs): |
3623 if (util.safehasattr(repo, 'abortifwdirpatched') |
4117 if util.safehasattr(repo, 'abortifwdirpatched') and not kwargs.get( |
3624 and not kwargs.get(r'no_commit', False)): |
4118 r'no_commit', False |
3625 repo.abortifwdirpatched(_('cannot import over an applied patch'), |
4119 ): |
3626 kwargs.get(r'force')) |
4120 repo.abortifwdirpatched( |
|
4121 _('cannot import over an applied patch'), kwargs.get(r'force') |
|
4122 ) |
3627 return orig(ui, repo, *args, **kwargs) |
4123 return orig(ui, repo, *args, **kwargs) |
|
4124 |
3628 |
4125 |
3629 def mqinit(orig, ui, *args, **kwargs): |
4126 def mqinit(orig, ui, *args, **kwargs): |
3630 mq = kwargs.pop(r'mq', None) |
4127 mq = kwargs.pop(r'mq', None) |
3631 |
4128 |
3632 if not mq: |
4129 if not mq: |
3633 return orig(ui, *args, **kwargs) |
4130 return orig(ui, *args, **kwargs) |
3634 |
4131 |
3635 if args: |
4132 if args: |
3636 repopath = args[0] |
4133 repopath = args[0] |
3637 if not hg.islocal(repopath): |
4134 if not hg.islocal(repopath): |
3638 raise error.Abort(_('only a local queue repository ' |
4135 raise error.Abort( |
3639 'may be initialized')) |
4136 _('only a local queue repository ' 'may be initialized') |
|
4137 ) |
3640 else: |
4138 else: |
3641 repopath = cmdutil.findrepo(encoding.getcwd()) |
4139 repopath = cmdutil.findrepo(encoding.getcwd()) |
3642 if not repopath: |
4140 if not repopath: |
3643 raise error.Abort(_('there is no Mercurial repository here ' |
4141 raise error.Abort( |
3644 '(.hg not found)')) |
4142 _('there is no Mercurial repository here ' '(.hg not found)') |
|
4143 ) |
3645 repo = hg.repository(ui, repopath) |
4144 repo = hg.repository(ui, repopath) |
3646 return qinit(ui, repo, True) |
4145 return qinit(ui, repo, True) |
|
4146 |
3647 |
4147 |
3648 def mqcommand(orig, ui, repo, *args, **kwargs): |
4148 def mqcommand(orig, ui, repo, *args, **kwargs): |
3649 """Add --mq option to operate on patch repository instead of main""" |
4149 """Add --mq option to operate on patch repository instead of main""" |
3650 |
4150 |
3651 # some commands do not like getting unknown options |
4151 # some commands do not like getting unknown options |
3673 ui.write(_("mq: %s\n") % ', '.join(m)) |
4174 ui.write(_("mq: %s\n") % ', '.join(m)) |
3674 else: |
4175 else: |
3675 # i18n: column positioning for "hg summary" |
4176 # i18n: column positioning for "hg summary" |
3676 ui.note(_("mq: (empty queue)\n")) |
4177 ui.note(_("mq: (empty queue)\n")) |
3677 |
4178 |
|
4179 |
3678 revsetpredicate = registrar.revsetpredicate() |
4180 revsetpredicate = registrar.revsetpredicate() |
|
4181 |
3679 |
4182 |
3680 @revsetpredicate('mq()') |
4183 @revsetpredicate('mq()') |
3681 def revsetmq(repo, subset, x): |
4184 def revsetmq(repo, subset, x): |
3682 """Changesets managed by MQ. |
4185 """Changesets managed by MQ. |
3683 """ |
4186 """ |
3684 revsetlang.getargs(x, 0, 0, _("mq takes no arguments")) |
4187 revsetlang.getargs(x, 0, 0, _("mq takes no arguments")) |
3685 applied = {repo[r.node].rev() for r in repo.mq.applied} |
4188 applied = {repo[r.node].rev() for r in repo.mq.applied} |
3686 return smartset.baseset([r for r in subset if r in applied]) |
4189 return smartset.baseset([r for r in subset if r in applied]) |
3687 |
4190 |
|
4191 |
3688 # tell hggettext to extract docstrings from these functions: |
4192 # tell hggettext to extract docstrings from these functions: |
3689 i18nfunctions = [revsetmq] |
4193 i18nfunctions = [revsetmq] |
|
4194 |
3690 |
4195 |
3691 def extsetup(ui): |
4196 def extsetup(ui): |
3692 # Ensure mq wrappers are called first, regardless of extension load order by |
4197 # Ensure mq wrappers are called first, regardless of extension load order by |
3693 # NOT wrapping in uisetup() and instead deferring to init stage two here. |
4198 # NOT wrapping in uisetup() and instead deferring to init stage two here. |
3694 mqopt = [('', 'mq', None, _("operate on patch repository"))] |
4199 mqopt = [('', 'mq', None, _("operate on patch repository"))] |
3712 |
4217 |
3713 for extname, extmodule in extensions.extensions(): |
4218 for extname, extmodule in extensions.extensions(): |
3714 if extmodule.__file__ != __file__: |
4219 if extmodule.__file__ != __file__: |
3715 dotable(getattr(extmodule, 'cmdtable', {})) |
4220 dotable(getattr(extmodule, 'cmdtable', {})) |
3716 |
4221 |
3717 colortable = {'qguard.negative': 'red', |
4222 |
3718 'qguard.positive': 'yellow', |
4223 colortable = { |
3719 'qguard.unguarded': 'green', |
4224 'qguard.negative': 'red', |
3720 'qseries.applied': 'blue bold underline', |
4225 'qguard.positive': 'yellow', |
3721 'qseries.guarded': 'black bold', |
4226 'qguard.unguarded': 'green', |
3722 'qseries.missing': 'red bold', |
4227 'qseries.applied': 'blue bold underline', |
3723 'qseries.unapplied': 'black bold'} |
4228 'qseries.guarded': 'black bold', |
|
4229 'qseries.missing': 'red bold', |
|
4230 'qseries.unapplied': 'black bold', |
|
4231 } |