33 from mercurial.demandload import * |
33 from mercurial.demandload import * |
34 demandload(globals(), "os sys re struct traceback errno bz2") |
34 demandload(globals(), "os sys re struct traceback errno bz2") |
35 from mercurial.i18n import gettext as _ |
35 from mercurial.i18n import gettext as _ |
36 from mercurial import ui, hg, revlog, commands, util |
36 from mercurial import ui, hg, revlog, commands, util |
37 |
37 |
38 versionstr = "0.45" |
|
39 |
|
40 commands.norepo += " qclone qversion" |
38 commands.norepo += " qclone qversion" |
41 |
39 |
42 class StatusEntry: |
40 class statusentry: |
43 def __init__(self, rev, name=None): |
41 def __init__(self, rev, name=None): |
44 if not name: |
42 if not name: |
45 self.rev, self.name = rev.split(':') |
43 fields = rev.split(':') |
|
44 if len(fields) == 2: |
|
45 self.rev, self.name = fields |
|
46 else: |
|
47 self.rev, self.name = None, None |
46 else: |
48 else: |
47 self.rev, self.name = rev, name |
49 self.rev, self.name = rev, name |
48 |
50 |
49 def __str__(self): |
51 def __str__(self): |
50 return self.rev + ':' + self.name |
52 return self.rev + ':' + self.name |
51 |
53 |
52 class queue: |
54 class queue: |
53 def __init__(self, ui, path, patchdir=None): |
55 def __init__(self, ui, path, patchdir=None): |
54 self.basepath = path |
56 self.basepath = path |
55 if patchdir: |
57 self.path = patchdir or os.path.join(path, "patches") |
56 self.path = patchdir |
|
57 else: |
|
58 self.path = os.path.join(path, "patches") |
|
59 self.opener = util.opener(self.path) |
58 self.opener = util.opener(self.path) |
60 self.ui = ui |
59 self.ui = ui |
61 self.applied = [] |
60 self.applied = [] |
62 self.full_series = [] |
61 self.full_series = [] |
63 self.applied_dirty = 0 |
62 self.applied_dirty = 0 |
64 self.series_dirty = 0 |
63 self.series_dirty = 0 |
65 self.series_path = "series" |
64 self.series_path = "series" |
66 self.status_path = "status" |
65 self.status_path = "status" |
67 |
66 self.guards_path = "guards" |
68 if os.path.exists(os.path.join(self.path, self.series_path)): |
67 self.active_guards = None |
|
68 self.guards_dirty = False |
|
69 |
|
70 if os.path.exists(self.join(self.series_path)): |
69 self.full_series = self.opener(self.series_path).read().splitlines() |
71 self.full_series = self.opener(self.series_path).read().splitlines() |
70 self.parse_series() |
72 self.parse_series() |
71 |
73 |
72 if os.path.exists(os.path.join(self.path, self.status_path)): |
74 if os.path.exists(self.join(self.status_path)): |
73 self.applied = [StatusEntry(l) |
75 lines = self.opener(self.status_path).read().splitlines() |
74 for l in self.opener(self.status_path).read().splitlines()] |
76 self.applied = [statusentry(l) for l in lines] |
|
77 |
|
78 def join(self, *p): |
|
79 return os.path.join(self.path, *p) |
75 |
80 |
76 def find_series(self, patch): |
81 def find_series(self, patch): |
77 pre = re.compile("(\s*)([^#]+)") |
82 pre = re.compile("(\s*)([^#]+)") |
78 index = 0 |
83 index = 0 |
79 for l in self.full_series: |
84 for l in self.full_series: |
84 if s == patch: |
89 if s == patch: |
85 return index |
90 return index |
86 index += 1 |
91 index += 1 |
87 return None |
92 return None |
88 |
93 |
|
94 guard_re = re.compile(r'\s?#([-+][^-+# \t\r\n\f][^# \t\r\n\f]*)') |
|
95 |
89 def parse_series(self): |
96 def parse_series(self): |
90 self.series = [] |
97 self.series = [] |
|
98 self.series_guards = [] |
91 for l in self.full_series: |
99 for l in self.full_series: |
92 s = l.split('#', 1)[0].strip() |
100 h = l.find('#') |
93 if s: |
101 if h == -1: |
94 self.series.append(s) |
102 patch = l |
|
103 comment = '' |
|
104 elif h == 0: |
|
105 continue |
|
106 else: |
|
107 patch = l[:h] |
|
108 comment = l[h:] |
|
109 patch = patch.strip() |
|
110 if patch: |
|
111 self.series.append(patch) |
|
112 self.series_guards.append(self.guard_re.findall(comment)) |
|
113 |
|
114 def check_guard(self, guard): |
|
115 bad_chars = '# \t\r\n\f' |
|
116 first = guard[0] |
|
117 for c in '-+': |
|
118 if first == c: |
|
119 return (_('guard %r starts with invalid character: %r') % |
|
120 (guard, c)) |
|
121 for c in bad_chars: |
|
122 if c in guard: |
|
123 return _('invalid character in guard %r: %r') % (guard, c) |
|
124 |
|
125 def set_active(self, guards): |
|
126 for guard in guards: |
|
127 bad = self.check_guard(guard) |
|
128 if bad: |
|
129 raise util.Abort(bad) |
|
130 guards = dict.fromkeys(guards).keys() |
|
131 guards.sort() |
|
132 self.ui.debug('active guards: %s\n' % ' '.join(guards)) |
|
133 self.active_guards = guards |
|
134 self.guards_dirty = True |
|
135 |
|
136 def active(self): |
|
137 if self.active_guards is None: |
|
138 self.active_guards = [] |
|
139 try: |
|
140 guards = self.opener(self.guards_path).read().split() |
|
141 except IOError, err: |
|
142 if err.errno != errno.ENOENT: raise |
|
143 guards = [] |
|
144 for i, guard in enumerate(guards): |
|
145 bad = self.check_guard(guard) |
|
146 if bad: |
|
147 self.ui.warn('%s:%d: %s\n' % |
|
148 (self.join(self.guards_path), i + 1, bad)) |
|
149 else: |
|
150 self.active_guards.append(guard) |
|
151 return self.active_guards |
|
152 |
|
153 def set_guards(self, idx, guards): |
|
154 for g in guards: |
|
155 if len(g) < 2: |
|
156 raise util.Abort(_('guard %r too short') % g) |
|
157 if g[0] not in '-+': |
|
158 raise util.Abort(_('guard %r starts with invalid char') % g) |
|
159 bad = self.check_guard(g[1:]) |
|
160 if bad: |
|
161 raise util.Abort(bad) |
|
162 drop = self.guard_re.sub('', self.full_series[idx]) |
|
163 self.full_series[idx] = drop + ''.join([' #' + g for g in guards]) |
|
164 self.parse_series() |
|
165 self.series_dirty = True |
|
166 |
|
167 def pushable(self, idx): |
|
168 if isinstance(idx, str): |
|
169 idx = self.series.index(idx) |
|
170 patchguards = self.series_guards[idx] |
|
171 if not patchguards: |
|
172 return True, None |
|
173 default = False |
|
174 guards = self.active() |
|
175 exactneg = [g for g in patchguards if g[0] == '-' and g[1:] in guards] |
|
176 if exactneg: |
|
177 return False, exactneg[0] |
|
178 pos = [g for g in patchguards if g[0] == '+'] |
|
179 nonpos = [g for g in pos if g[1:] not in guards] |
|
180 if pos: |
|
181 if not nonpos: |
|
182 return True, '' |
|
183 return False, nonpos |
|
184 return True, '' |
|
185 |
|
186 def explain_pushable(self, idx, all_patches=False): |
|
187 write = all_patches and self.ui.write or self.ui.warn |
|
188 if all_patches or self.ui.verbose: |
|
189 if isinstance(idx, str): |
|
190 idx = self.series.index(idx) |
|
191 pushable, why = self.pushable(idx) |
|
192 if all_patches and pushable: |
|
193 if why is None: |
|
194 write(_('allowing %s - no guards in effect\n') % |
|
195 self.series[idx]) |
|
196 else: |
|
197 if not why: |
|
198 write(_('allowing %s - no matching negative guards\n') % |
|
199 self.series[idx]) |
|
200 else: |
|
201 write(_('allowing %s - guarded by %r\n') % |
|
202 (self.series[idx], why)) |
|
203 if not pushable: |
|
204 if why: |
|
205 write(_('skipping %s - guarded by %r\n') % |
|
206 (self.series[idx], ' '.join(why))) |
|
207 else: |
|
208 write(_('skipping %s - no matching guards\n') % |
|
209 self.series[idx]) |
95 |
210 |
96 def save_dirty(self): |
211 def save_dirty(self): |
97 def write_list(items, path): |
212 def write_list(items, path): |
98 fp = self.opener(path, 'w') |
213 fp = self.opener(path, 'w') |
99 for i in items: |
214 for i in items: |
100 print >> fp, i |
215 print >> fp, i |
101 fp.close() |
216 fp.close() |
102 if self.applied_dirty: write_list(map(str, self.applied), self.status_path) |
217 if self.applied_dirty: write_list(map(str, self.applied), self.status_path) |
103 if self.series_dirty: write_list(self.full_series, self.series_path) |
218 if self.series_dirty: write_list(self.full_series, self.series_path) |
|
219 if self.guards_dirty: write_list(self.active_guards, self.guards_path) |
104 |
220 |
105 def readheaders(self, patch): |
221 def readheaders(self, patch): |
106 def eatdiff(lines): |
222 def eatdiff(lines): |
107 while lines: |
223 while lines: |
108 l = lines[-1] |
224 l = lines[-1] |
241 # the first patch in the queue is never a merge patch |
357 # the first patch in the queue is never a merge patch |
242 # |
358 # |
243 pname = ".hg.patches.merge.marker" |
359 pname = ".hg.patches.merge.marker" |
244 n = repo.commit(None, '[mq]: merge marker', user=None, force=1, |
360 n = repo.commit(None, '[mq]: merge marker', user=None, force=1, |
245 wlock=wlock) |
361 wlock=wlock) |
246 self.applied.append(StatusEntry(revlog.hex(n), pname)) |
362 self.applied.append(statusentry(revlog.hex(n), pname)) |
247 self.applied_dirty = 1 |
363 self.applied_dirty = 1 |
248 |
364 |
249 head = self.qparents(repo) |
365 head = self.qparents(repo) |
250 |
366 |
251 for patch in series: |
367 for patch in series: |
252 patch = mergeq.lookup(patch, strict=True) |
368 patch = mergeq.lookup(patch, strict=True) |
253 if not patch: |
369 if not patch: |
254 self.ui.warn("patch %s does not exist\n" % patch) |
370 self.ui.warn("patch %s does not exist\n" % patch) |
255 return (1, None) |
371 return (1, None) |
256 |
372 pushable, reason = self.pushable(patch) |
|
373 if not pushable: |
|
374 self.explain_pushable(patch, all_patches=True) |
|
375 continue |
257 info = mergeq.isapplied(patch) |
376 info = mergeq.isapplied(patch) |
258 if not info: |
377 if not info: |
259 self.ui.warn("patch %s is not applied\n" % patch) |
378 self.ui.warn("patch %s is not applied\n" % patch) |
260 return (1, None) |
379 return (1, None) |
261 rev = revlog.bin(info[1]) |
380 rev = revlog.bin(info[1]) |
262 (err, head) = self.mergeone(repo, mergeq, head, patch, rev, wlock) |
381 (err, head) = self.mergeone(repo, mergeq, head, patch, rev, wlock) |
263 if head: |
382 if head: |
264 self.applied.append(StatusEntry(revlog.hex(head), patch)) |
383 self.applied.append(statusentry(revlog.hex(head), patch)) |
265 self.applied_dirty = 1 |
384 self.applied_dirty = 1 |
266 if err: |
385 if err: |
267 return (err, head) |
386 return (err, head) |
268 return (0, head) |
387 return (0, head) |
269 |
388 |
403 def check_localchanges(self, repo): |
526 def check_localchanges(self, repo): |
404 (c, a, r, d, u) = repo.changes(None, None) |
527 (c, a, r, d, u) = repo.changes(None, None) |
405 if c or a or d or r: |
528 if c or a or d or r: |
406 raise util.Abort(_("local changes found, refresh first")) |
529 raise util.Abort(_("local changes found, refresh first")) |
407 def new(self, repo, patch, msg=None, force=None): |
530 def new(self, repo, patch, msg=None, force=None): |
408 if os.path.exists(os.path.join(self.path, patch)): |
531 if os.path.exists(self.join(patch)): |
409 raise util.Abort(_('patch "%s" already exists') % patch) |
532 raise util.Abort(_('patch "%s" already exists') % patch) |
410 commitfiles = [] |
533 commitfiles = [] |
411 (c, a, r, d, u) = repo.changes(None, None) |
534 (c, a, r, d, u) = repo.changes(None, None) |
412 if c or a or d or r: |
535 if c or a or d or r: |
413 if not force: |
536 if not force: |
423 n = repo.commit(commitfiles, |
546 n = repo.commit(commitfiles, |
424 "New patch: %s" % patch, force=True, wlock=wlock) |
547 "New patch: %s" % patch, force=True, wlock=wlock) |
425 if n == None: |
548 if n == None: |
426 raise util.Abort(_("repo commit failed")) |
549 raise util.Abort(_("repo commit failed")) |
427 self.full_series[insert:insert] = [patch] |
550 self.full_series[insert:insert] = [patch] |
428 self.applied.append(StatusEntry(revlog.hex(n), patch)) |
551 self.applied.append(statusentry(revlog.hex(n), patch)) |
429 self.parse_series() |
552 self.parse_series() |
430 self.series_dirty = 1 |
553 self.series_dirty = 1 |
431 self.applied_dirty = 1 |
554 self.applied_dirty = 1 |
432 p = self.opener(patch, "w") |
555 p = self.opener(patch, "w") |
433 if msg: |
556 if msg: |
626 # sure the file name passed in does not exist (checked below) |
749 # sure the file name passed in does not exist (checked below) |
627 res = partial_name(patch) |
750 res = partial_name(patch) |
628 if res and res == patch: |
751 if res and res == patch: |
629 return res |
752 return res |
630 |
753 |
631 if not os.path.isfile(os.path.join(self.path, patch)): |
754 if not os.path.isfile(self.join(patch)): |
632 try: |
755 try: |
633 sno = int(patch) |
756 sno = int(patch) |
634 except(ValueError, OverflowError): |
757 except(ValueError, OverflowError): |
635 pass |
758 pass |
636 else: |
759 else: |
637 if sno < len(self.series): |
760 if sno < len(self.series): |
638 patch = self.series[sno] |
761 return self.series[sno] |
639 return patch |
|
640 if not strict: |
762 if not strict: |
641 # return any partial match made above |
763 # return any partial match made above |
642 if res: |
764 if res: |
643 return res |
765 return res |
644 minus = patch.rsplit('-', 1) |
766 minus = patch.rsplit('-', 1) |
898 else: |
1020 else: |
899 message = msg |
1021 message = msg |
900 |
1022 |
901 self.strip(repo, top, update=False, backup='strip', wlock=wlock) |
1023 self.strip(repo, top, update=False, backup='strip', wlock=wlock) |
902 n = repo.commit(filelist, message, changes[1], force=1, wlock=wlock) |
1024 n = repo.commit(filelist, message, changes[1], force=1, wlock=wlock) |
903 self.applied[-1] = StatusEntry(revlog.hex(n), patch) |
1025 self.applied[-1] = statusentry(revlog.hex(n), patch) |
904 self.applied_dirty = 1 |
1026 self.applied_dirty = 1 |
905 else: |
1027 else: |
906 commands.dodiff(patchf, self.ui, repo, patchparent, None) |
1028 commands.dodiff(patchf, self.ui, repo, patchparent, None) |
907 patchf.close() |
1029 patchf.close() |
908 self.pop(repo, force=True, wlock=wlock) |
1030 self.pop(repo, force=True, wlock=wlock) |
920 raise util.Abort(_("patch %s is not in series file") % patch) |
1042 raise util.Abort(_("patch %s is not in series file") % patch) |
921 if not patch: |
1043 if not patch: |
922 start = self.series_end() |
1044 start = self.series_end() |
923 else: |
1045 else: |
924 start = self.series.index(patch) + 1 |
1046 start = self.series.index(patch) + 1 |
925 return [(i, self.series[i]) for i in xrange(start, len(self.series))] |
1047 unapplied = [] |
|
1048 for i in xrange(start, len(self.series)): |
|
1049 pushable, reason = self.pushable(i) |
|
1050 if pushable: |
|
1051 unapplied.append((i, self.series[i])) |
|
1052 self.explain_pushable(i) |
|
1053 return unapplied |
926 |
1054 |
927 def qseries(self, repo, missing=None, summary=False): |
1055 def qseries(self, repo, missing=None, summary=False): |
928 start = self.series_end() |
1056 start = self.series_end(all_patches=True) |
929 if not missing: |
1057 if not missing: |
930 for i in range(len(self.series)): |
1058 for i in range(len(self.series)): |
931 patch = self.series[i] |
1059 patch = self.series[i] |
932 if self.ui.verbose: |
1060 if self.ui.verbose: |
933 if i < start: |
1061 if i < start: |
934 status = 'A' |
1062 status = 'A' |
|
1063 elif self.pushable(i)[0]: |
|
1064 status = 'U' |
935 else: |
1065 else: |
936 status = 'U' |
1066 status = 'G' |
937 self.ui.write('%d %s ' % (i, status)) |
1067 self.ui.write('%d %s ' % (i, status)) |
938 if summary: |
1068 if summary: |
939 msg = self.readheaders(patch)[0] |
1069 msg = self.readheaders(patch)[0] |
940 msg = msg and ': ' + msg[0] or ': ' |
1070 msg = msg and ': ' + msg[0] or ': ' |
941 else: |
1071 else: |
956 if self.ui.verbose: |
1086 if self.ui.verbose: |
957 self.ui.write("D ") |
1087 self.ui.write("D ") |
958 self.ui.write("%s\n" % x) |
1088 self.ui.write("%s\n" % x) |
959 |
1089 |
960 def issaveline(self, l): |
1090 def issaveline(self, l): |
961 name = l.split(':')[1] |
1091 if l.name == '.hg.patches.save.line': |
962 if name == '.hg.patches.save.line': |
|
963 return True |
1092 return True |
964 |
1093 |
965 def qrepo(self, create=False): |
1094 def qrepo(self, create=False): |
966 if create or os.path.isdir(os.path.join(self.path, ".hg")): |
1095 if create or os.path.isdir(self.join(".hg")): |
967 return hg.repository(self.ui, path=self.path, create=create) |
1096 return hg.repository(self.ui, path=self.path, create=create) |
968 |
1097 |
969 def restore(self, repo, rev, delete=None, qupdate=None): |
1098 def restore(self, repo, rev, delete=None, qupdate=None): |
970 c = repo.changelog.read(rev) |
1099 c = repo.changelog.read(rev) |
971 desc = c[4].strip() |
1100 desc = c[4].strip() |
1037 r = self.qrepo() |
1166 r = self.qrepo() |
1038 if r: |
1167 if r: |
1039 pp = r.dirstate.parents() |
1168 pp = r.dirstate.parents() |
1040 msg += "\nDirstate: %s %s" % (hg.hex(pp[0]), hg.hex(pp[1])) |
1169 msg += "\nDirstate: %s %s" % (hg.hex(pp[0]), hg.hex(pp[1])) |
1041 msg += "\n\nPatch Data:\n" |
1170 msg += "\n\nPatch Data:\n" |
1042 text = msg + "\n".join(str(self.applied)) + '\n' + (ar and "\n".join(ar) |
1171 text = msg + "\n".join([str(x) for x in self.applied]) + '\n' + (ar and |
1043 + '\n' or "") |
1172 "\n".join(ar) + '\n' or "") |
1044 n = repo.commit(None, text, user=None, force=1) |
1173 n = repo.commit(None, text, user=None, force=1) |
1045 if not n: |
1174 if not n: |
1046 self.ui.warn("repo commit failed\n") |
1175 self.ui.warn("repo commit failed\n") |
1047 return 1 |
1176 return 1 |
1048 self.applied.append(StatusEntry(revlog.hex(n),'.hg.patches.save.line')) |
1177 self.applied.append(statusentry(revlog.hex(n),'.hg.patches.save.line')) |
1049 self.applied_dirty = 1 |
1178 self.applied_dirty = 1 |
1050 |
1179 |
1051 def full_series_end(self): |
1180 def full_series_end(self): |
1052 if len(self.applied) > 0: |
1181 if len(self.applied) > 0: |
1053 p = self.applied[-1].name |
1182 p = self.applied[-1].name |
1055 if end == None: |
1184 if end == None: |
1056 return len(self.full_series) |
1185 return len(self.full_series) |
1057 return end + 1 |
1186 return end + 1 |
1058 return 0 |
1187 return 0 |
1059 |
1188 |
1060 def series_end(self): |
1189 def series_end(self, all_patches=False): |
1061 end = 0 |
1190 end = 0 |
|
1191 def next(start): |
|
1192 if all_patches: |
|
1193 return start |
|
1194 i = start |
|
1195 while i < len(self.series): |
|
1196 p, reason = self.pushable(i) |
|
1197 if p: |
|
1198 break |
|
1199 self.explain_pushable(i) |
|
1200 i += 1 |
|
1201 return i |
1062 if len(self.applied) > 0: |
1202 if len(self.applied) > 0: |
1063 p = self.applied[-1].name |
1203 p = self.applied[-1].name |
1064 try: |
1204 try: |
1065 end = self.series.index(p) |
1205 end = self.series.index(p) |
1066 except ValueError: |
1206 except ValueError: |
1067 return 0 |
1207 return 0 |
1068 return end + 1 |
1208 return next(end + 1) |
1069 return end |
1209 return next(end) |
1070 |
1210 |
1071 def qapplied(self, repo, patch=None): |
1211 def qapplied(self, repo, patch=None): |
1072 if patch and patch not in self.series: |
1212 if patch and patch not in self.series: |
1073 raise util.Abort(_("patch %s is not in series file") % patch) |
1213 raise util.Abort(_("patch %s is not in series file") % patch) |
1074 if not patch: |
1214 if not patch: |
1121 added = [] |
1261 added = [] |
1122 for filename in files: |
1262 for filename in files: |
1123 if existing: |
1263 if existing: |
1124 if not patch: |
1264 if not patch: |
1125 patch = filename |
1265 patch = filename |
1126 if not os.path.isfile(os.path.join(self.path, patch)): |
1266 if not os.path.isfile(self.join(patch)): |
1127 raise util.Abort(_("patch %s does not exist") % patch) |
1267 raise util.Abort(_("patch %s does not exist") % patch) |
1128 else: |
1268 else: |
1129 try: |
1269 try: |
1130 text = file(filename).read() |
1270 text = file(filename).read() |
1131 except IOError: |
1271 except IOError: |
1132 raise util.Abort(_("unable to read %s") % patch) |
1272 raise util.Abort(_("unable to read %s") % patch) |
1133 if not patch: |
1273 if not patch: |
1134 patch = os.path.split(filename)[1] |
1274 patch = os.path.split(filename)[1] |
1135 if not force and os.path.exists(os.path.join(self.path, patch)): |
1275 if not force and os.path.exists(self.join(patch)): |
1136 raise util.Abort(_('patch "%s" already exists') % patch) |
1276 raise util.Abort(_('patch "%s" already exists') % patch) |
1137 patchf = self.opener(patch, "w") |
1277 patchf = self.opener(patch, "w") |
1138 patchf.write(text) |
1278 patchf.write(text) |
1139 if patch in self.series: |
1279 if patch in self.series: |
1140 raise util.Abort(_('patch %s is already in the series file') |
1280 raise util.Abort(_('patch %s is already in the series file') |
1366 |
1506 |
1367 for patch in patches: |
1507 for patch in patches: |
1368 q.delete(repo, patch, force=opts['force']) |
1508 q.delete(repo, patch, force=opts['force']) |
1369 |
1509 |
1370 q.save_dirty() |
1510 q.save_dirty() |
|
1511 |
|
1512 def guard(ui, repo, *args, **opts): |
|
1513 '''set or print guards for a patch |
|
1514 |
|
1515 guards control whether a patch can be pushed. a patch with no |
|
1516 guards is aways pushed. a patch with posative guard ("+foo") is |
|
1517 pushed only if qselect command enables guard "foo". a patch with |
|
1518 nagative guard ("-foo") is never pushed if qselect command enables |
|
1519 guard "foo". |
|
1520 |
|
1521 with no arguments, default is to print current active guards. |
|
1522 with arguments, set active guards for patch. |
|
1523 |
|
1524 to set nagative guard "-foo" on topmost patch ("--" is needed so |
|
1525 hg will not interpret "-foo" as argument): |
|
1526 hg qguard -- -foo |
|
1527 |
|
1528 to set guards on other patch: |
|
1529 hg qguard other.patch +2.6.17 -stable |
|
1530 ''' |
|
1531 def status(idx): |
|
1532 guards = q.series_guards[idx] or ['unguarded'] |
|
1533 ui.write('%s: %s\n' % (q.series[idx], ' '.join(guards))) |
|
1534 q = repo.mq |
|
1535 patch = None |
|
1536 args = list(args) |
|
1537 if opts['list']: |
|
1538 if args or opts['none']: |
|
1539 raise util.Abort(_('cannot mix -l/--list with options or arguments')) |
|
1540 for i in xrange(len(q.series)): |
|
1541 status(i) |
|
1542 return |
|
1543 if not args or args[0][0:1] in '-+': |
|
1544 if not q.applied: |
|
1545 raise util.Abort(_('no patches applied')) |
|
1546 patch = q.applied[-1].name |
|
1547 if patch is None and args[0][0:1] not in '-+': |
|
1548 patch = args.pop(0) |
|
1549 if patch is None: |
|
1550 raise util.Abort(_('no patch to work with')) |
|
1551 if args or opts['none']: |
|
1552 q.set_guards(q.find_series(patch), args) |
|
1553 q.save_dirty() |
|
1554 else: |
|
1555 status(q.series.index(q.lookup(patch))) |
1371 |
1556 |
1372 def header(ui, repo, patch=None): |
1557 def header(ui, repo, patch=None): |
1373 """Print the header of the topmost or specified patch""" |
1558 """Print the header of the topmost or specified patch""" |
1374 q = repo.mq |
1559 q = repo.mq |
1375 |
1560 |
1541 elif opts['nobackup']: |
1726 elif opts['nobackup']: |
1542 backup = 'none' |
1727 backup = 'none' |
1543 repo.mq.strip(repo, rev, backup=backup) |
1728 repo.mq.strip(repo, rev, backup=backup) |
1544 return 0 |
1729 return 0 |
1545 |
1730 |
1546 def version(ui, q=None): |
1731 def select(ui, repo, *args, **opts): |
1547 """print the version number of the mq extension""" |
1732 '''set or print guarded patches to push |
1548 ui.write("mq version %s\n" % versionstr) |
1733 |
1549 return 0 |
1734 use qguard command to set or print guards on patch. then use |
|
1735 qselect to tell mq which guards to use. example: |
|
1736 |
|
1737 qguard foo.patch -stable (nagative guard) |
|
1738 qguard bar.patch +stable (posative guard) |
|
1739 qselect stable |
|
1740 |
|
1741 this sets "stable" guard. mq will skip foo.patch (because it has |
|
1742 nagative match) but push bar.patch (because it has posative |
|
1743 match). patch is pushed only if all posative guards match and no |
|
1744 nagative guards match. |
|
1745 |
|
1746 with no arguments, default is to print current active guards. |
|
1747 with arguments, set active guards as given. |
|
1748 |
|
1749 use -n/--none to deactivate guards (no other arguments needed). |
|
1750 when no guards active, patches with posative guards are skipped, |
|
1751 patches with nagative guards are pushed. |
|
1752 |
|
1753 use -s/--series to print list of all guards in series file (no |
|
1754 other arguments needed). use -v for more information.''' |
|
1755 |
|
1756 q = repo.mq |
|
1757 guards = q.active() |
|
1758 if args or opts['none']: |
|
1759 q.set_active(args) |
|
1760 q.save_dirty() |
|
1761 if not args: |
|
1762 ui.status(_('guards deactivated\n')) |
|
1763 if q.series: |
|
1764 ui.status(_('%d of %d unapplied patches active\n') % |
|
1765 (len(q.unapplied(repo)), len(q.series))) |
|
1766 elif opts['series']: |
|
1767 guards = {} |
|
1768 noguards = 0 |
|
1769 for gs in q.series_guards: |
|
1770 if not gs: |
|
1771 noguards += 1 |
|
1772 for g in gs: |
|
1773 guards.setdefault(g, 0) |
|
1774 guards[g] += 1 |
|
1775 if ui.verbose: |
|
1776 guards['NONE'] = noguards |
|
1777 guards = guards.items() |
|
1778 guards.sort(lambda a, b: cmp(a[0][1:], b[0][1:])) |
|
1779 if guards: |
|
1780 ui.note(_('guards in series file:\n')) |
|
1781 for guard, count in guards: |
|
1782 ui.note('%2d ' % count) |
|
1783 ui.write(guard, '\n') |
|
1784 else: |
|
1785 ui.note(_('no guards in series file\n')) |
|
1786 else: |
|
1787 if guards: |
|
1788 ui.note(_('active guards:\n')) |
|
1789 for g in guards: |
|
1790 ui.write(g, '\n') |
|
1791 else: |
|
1792 ui.write(_('no active guards\n')) |
1550 |
1793 |
1551 def reposetup(ui, repo): |
1794 def reposetup(ui, repo): |
1552 class MqRepo(repo.__class__): |
1795 class mqrepo(repo.__class__): |
1553 def tags(self): |
1796 def tags(self): |
1554 if self.tagscache: |
1797 if self.tagscache: |
1555 return self.tagscache |
1798 return self.tagscache |
1556 |
1799 |
1557 tagscache = super(MqRepo, self).tags() |
1800 tagscache = super(mqrepo, self).tags() |
1558 |
1801 |
1559 q = self.mq |
1802 q = self.mq |
1560 if not q.applied: |
1803 if not q.applied: |
1561 return tagscache |
1804 return tagscache |
1562 |
1805 |
1600 [('e', 'edit', None, _('edit patch header')), |
1843 [('e', 'edit', None, _('edit patch header')), |
1601 ('f', 'force', None, _('delete folded patch files')), |
1844 ('f', 'force', None, _('delete folded patch files')), |
1602 ('m', 'message', '', _('set patch header to <text>')), |
1845 ('m', 'message', '', _('set patch header to <text>')), |
1603 ('l', 'logfile', '', _('set patch header to contents of <file>'))], |
1846 ('l', 'logfile', '', _('set patch header to contents of <file>'))], |
1604 'hg qfold [-e] [-m <text>] [-l <file] PATCH...'), |
1847 'hg qfold [-e] [-m <text>] [-l <file] PATCH...'), |
|
1848 'qguard': (guard, [('l', 'list', None, _('list all patches and guards')), |
|
1849 ('n', 'none', None, _('drop all guards'))], |
|
1850 'hg qguard [PATCH] [+GUARD...] [-GUARD...]'), |
1605 'qheader': (header, [], |
1851 'qheader': (header, [], |
1606 _('hg qheader [PATCH]')), |
1852 _('hg qheader [PATCH]')), |
1607 "^qimport": |
1853 "^qimport": |
1608 (qimport, |
1854 (qimport, |
1609 [('e', 'existing', None, 'import file in patch dir'), |
1855 [('e', 'existing', None, 'import file in patch dir'), |
1657 ('c', 'copy', None, 'copy patch directory'), |
1903 ('c', 'copy', None, 'copy patch directory'), |
1658 ('n', 'name', '', 'copy directory name'), |
1904 ('n', 'name', '', 'copy directory name'), |
1659 ('e', 'empty', None, 'clear queue status file'), |
1905 ('e', 'empty', None, 'clear queue status file'), |
1660 ('f', 'force', None, 'force copy')], |
1906 ('f', 'force', None, 'force copy')], |
1661 'hg qsave [-m TEXT] [-l FILE] [-c] [-n NAME] [-e] [-f]'), |
1907 'hg qsave [-m TEXT] [-l FILE] [-c] [-n NAME] [-e] [-f]'), |
|
1908 "qselect": (select, |
|
1909 [('n', 'none', None, _('disable all guards')), |
|
1910 ('s', 'series', None, _('list all guards in series file'))], |
|
1911 'hg qselect [GUARDS]'), |
1662 "qseries": |
1912 "qseries": |
1663 (series, |
1913 (series, |
1664 [('m', 'missing', None, 'print patches not in series'), |
1914 [('m', 'missing', None, 'print patches not in series'), |
1665 ('s', 'summary', None, _('print first line of patch header'))], |
1915 ('s', 'summary', None, _('print first line of patch header'))], |
1666 'hg qseries [-m]'), |
1916 'hg qseries [-m]'), |
1670 ('b', 'backup', None, 'bundle unrelated changesets'), |
1920 ('b', 'backup', None, 'bundle unrelated changesets'), |
1671 ('n', 'nobackup', None, 'no backups')], |
1921 ('n', 'nobackup', None, 'no backups')], |
1672 'hg strip [-f] [-b] [-n] REV'), |
1922 'hg strip [-f] [-b] [-n] REV'), |
1673 "qtop": (top, [], 'hg qtop'), |
1923 "qtop": (top, [], 'hg qtop'), |
1674 "qunapplied": (unapplied, [], 'hg qunapplied [PATCH]'), |
1924 "qunapplied": (unapplied, [], 'hg qunapplied [PATCH]'), |
1675 "qversion": (version, [], 'hg qversion') |
|
1676 } |
1925 } |
1677 |
1926 |