65 self.series_path = "series" |
65 self.series_path = "series" |
66 self.status_path = "status" |
66 self.status_path = "status" |
67 |
67 |
68 if os.path.exists(os.path.join(self.path, self.series_path)): |
68 if os.path.exists(os.path.join(self.path, self.series_path)): |
69 self.full_series = self.opener(self.series_path).read().splitlines() |
69 self.full_series = self.opener(self.series_path).read().splitlines() |
70 self.read_series(self.full_series) |
70 self.parse_series() |
71 |
71 |
72 if os.path.exists(os.path.join(self.path, self.status_path)): |
72 if os.path.exists(os.path.join(self.path, self.status_path)): |
73 self.applied = [StatusEntry(l) |
73 self.applied = [StatusEntry(l) |
74 for l in self.opener(self.status_path).read().splitlines()] |
74 for l in self.opener(self.status_path).read().splitlines()] |
75 |
75 |
84 if s == patch: |
84 if s == patch: |
85 return index |
85 return index |
86 index += 1 |
86 index += 1 |
87 return None |
87 return None |
88 |
88 |
89 def read_series(self, list): |
89 def parse_series(self): |
90 def matcher(list): |
|
91 pre = re.compile("(\s*)([^#]+)") |
|
92 for l in list: |
|
93 m = pre.match(l) |
|
94 if m: |
|
95 s = m.group(2) |
|
96 s = s.rstrip() |
|
97 if len(s) > 0: |
|
98 yield s |
|
99 self.series = [] |
90 self.series = [] |
100 self.series = [ x for x in matcher(list) ] |
91 for l in self.full_series: |
|
92 s = l.split('#', 1)[0].strip() |
|
93 if s: |
|
94 self.series.append(s) |
101 |
95 |
102 def save_dirty(self): |
96 def save_dirty(self): |
103 if self.applied_dirty: |
97 def write_list(items, path): |
104 if len(self.applied) > 0: |
98 fp = self.opener(path, 'w') |
105 nl = "\n" |
99 for i in items: |
106 else: |
100 print >> fp, i |
107 nl = "" |
101 fp.close() |
108 f = self.opener(self.status_path, "w") |
102 if self.applied_dirty: write_list(map(str, self.applied), self.status_path) |
109 f.write("\n".join([str(x) for x in self.applied]) + nl) |
103 if self.series_dirty: write_list(self.full_series, self.series_path) |
110 if self.series_dirty: |
|
111 if len(self.full_series) > 0: |
|
112 nl = "\n" |
|
113 else: |
|
114 nl = "" |
|
115 f = self.opener(self.series_path, "w") |
|
116 f.write("\n".join(self.full_series) + nl) |
|
117 |
104 |
118 def readheaders(self, patch): |
105 def readheaders(self, patch): |
119 def eatdiff(lines): |
106 def eatdiff(lines): |
120 while lines: |
107 while lines: |
121 l = lines[-1] |
108 l = lines[-1] |
404 r.remove([patch], True) |
391 r.remove([patch], True) |
405 else: |
392 else: |
406 os.unlink(os.path.join(self.path, patch)) |
393 os.unlink(os.path.join(self.path, patch)) |
407 i = self.find_series(patch) |
394 i = self.find_series(patch) |
408 del self.full_series[i] |
395 del self.full_series[i] |
409 self.read_series(self.full_series) |
396 self.parse_series() |
410 self.series_dirty = 1 |
397 self.series_dirty = 1 |
411 |
398 |
412 def check_toppatch(self, repo): |
399 def check_toppatch(self, repo): |
413 if len(self.applied) > 0: |
400 if len(self.applied) > 0: |
414 top = revlog.bin(self.applied[-1].rev) |
401 top = revlog.bin(self.applied[-1].rev) |
441 "New patch: %s" % patch, force=True, wlock=wlock) |
428 "New patch: %s" % patch, force=True, wlock=wlock) |
442 if n == None: |
429 if n == None: |
443 raise util.Abort(_("repo commit failed")) |
430 raise util.Abort(_("repo commit failed")) |
444 self.full_series[insert:insert] = [patch] |
431 self.full_series[insert:insert] = [patch] |
445 self.applied.append(StatusEntry(revlog.hex(n), patch)) |
432 self.applied.append(StatusEntry(revlog.hex(n), patch)) |
446 self.read_series(self.full_series) |
433 self.parse_series() |
447 self.series_dirty = 1 |
434 self.series_dirty = 1 |
448 self.applied_dirty = 1 |
435 self.applied_dirty = 1 |
449 p = self.opener(patch, "w") |
436 p = self.opener(patch, "w") |
450 if msg: |
437 if msg: |
451 msg = msg + "\n" |
438 msg = msg + "\n" |
939 raise util.Abort(_("patch %s is not in series file") % patch) |
926 raise util.Abort(_("patch %s is not in series file") % patch) |
940 if not patch: |
927 if not patch: |
941 start = self.series_end() |
928 start = self.series_end() |
942 else: |
929 else: |
943 start = self.series.index(patch) + 1 |
930 start = self.series.index(patch) + 1 |
944 for p in self.series[start:]: |
931 return [(i, self.series[i]) for i in xrange(start, len(self.series))] |
945 if self.ui.verbose: |
|
946 self.ui.write("%d " % self.series.index(p)) |
|
947 self.ui.write("%s\n" % p) |
|
948 |
932 |
949 def qseries(self, repo, missing=None, summary=False): |
933 def qseries(self, repo, missing=None, summary=False): |
950 start = self.series_end() |
934 start = self.series_end() |
951 if not missing: |
935 if not missing: |
952 for i in range(len(self.series)): |
936 for i in range(len(self.series)): |
1017 self.ui.warn("No saved patch data found\n") |
1001 self.ui.warn("No saved patch data found\n") |
1018 return 1 |
1002 return 1 |
1019 self.ui.warn("restoring status: %s\n" % lines[0]) |
1003 self.ui.warn("restoring status: %s\n" % lines[0]) |
1020 self.full_series = series |
1004 self.full_series = series |
1021 self.applied = applied |
1005 self.applied = applied |
1022 self.read_series(self.full_series) |
1006 self.parse_series() |
1023 self.series_dirty = 1 |
1007 self.series_dirty = 1 |
1024 self.applied_dirty = 1 |
1008 self.applied_dirty = 1 |
1025 heads = repo.changelog.heads() |
1009 heads = repo.changelog.heads() |
1026 if delete: |
1010 if delete: |
1027 if rev not in heads: |
1011 if rev not in heads: |
1163 if patch in self.series: |
1147 if patch in self.series: |
1164 raise util.Abort(_('patch %s is already in the series file') |
1148 raise util.Abort(_('patch %s is already in the series file') |
1165 % patch) |
1149 % patch) |
1166 index = self.full_series_end() + i |
1150 index = self.full_series_end() + i |
1167 self.full_series[index:index] = [patch] |
1151 self.full_series[index:index] = [patch] |
1168 self.read_series(self.full_series) |
1152 self.parse_series() |
1169 self.ui.warn("adding %s to series file\n" % patch) |
1153 self.ui.warn("adding %s to series file\n" % patch) |
1170 i += 1 |
1154 i += 1 |
1171 added.append(patch) |
1155 added.append(patch) |
1172 patch = None |
1156 patch = None |
1173 self.series_dirty = 1 |
1157 self.series_dirty = 1 |
1190 repo.mq.qapplied(repo, patch) |
1174 repo.mq.qapplied(repo, patch) |
1191 return 0 |
1175 return 0 |
1192 |
1176 |
1193 def unapplied(ui, repo, patch=None, **opts): |
1177 def unapplied(ui, repo, patch=None, **opts): |
1194 """print the patches not yet applied""" |
1178 """print the patches not yet applied""" |
1195 repo.mq.unapplied(repo, patch) |
1179 for i, p in repo.mq.unapplied(repo, patch): |
1196 return 0 |
1180 if ui.verbose: |
|
1181 ui.write("%d " % i) |
|
1182 ui.write("%s\n" % p) |
1197 |
1183 |
1198 def qimport(ui, repo, *filename, **opts): |
1184 def qimport(ui, repo, *filename, **opts): |
1199 """import a patch""" |
1185 """import a patch""" |
1200 q = repo.mq |
1186 q = repo.mq |
1201 q.qimport(repo, filename, patch=opts['name'], |
1187 q.qimport(repo, filename, patch=opts['name'], |
1232 before that it has no patches applied. |
1218 before that it has no patches applied. |
1233 |
1219 |
1234 Source patch repository is looked for in <src>/.hg/patches by |
1220 Source patch repository is looked for in <src>/.hg/patches by |
1235 default. Use -p <url> to change. |
1221 default. Use -p <url> to change. |
1236 ''' |
1222 ''' |
1237 commands.setremoteconfig(**opts) |
1223 commands.setremoteconfig(ui, opts) |
1238 if dest is None: |
1224 if dest is None: |
1239 dest = hg.defaultdest(source) |
1225 dest = hg.defaultdest(source) |
1240 sr = hg.repository(ui, ui.expandpath(source)) |
1226 sr = hg.repository(ui, ui.expandpath(source)) |
1241 qbase, destrev = None, None |
1227 qbase, destrev = None, None |
1242 if sr.local(): |
1228 if sr.local(): |
1301 changes unless -f is specified, in which case the patch will |
1287 changes unless -f is specified, in which case the patch will |
1302 be initialised with them. |
1288 be initialised with them. |
1303 |
1289 |
1304 -m or -l set the patch header as well as the commit message. |
1290 -m or -l set the patch header as well as the commit message. |
1305 If neither is specified, the patch header is empty and the |
1291 If neither is specified, the patch header is empty and the |
1306 commit message is 'New patch: PATCH' |
1292 commit message is 'New patch: PATCH'""" |
1307 |
|
1308 If -f is specified, the patch will be initialized with any |
|
1309 uncommitted changes. Otherwise, if there outsta""" |
|
1310 q = repo.mq |
1293 q = repo.mq |
1311 message=commands.logmessage(**opts) |
1294 message=commands.logmessage(**opts) |
1312 q.new(repo, patch, msg=message, force=opts['force']) |
1295 q.new(repo, patch, msg=message, force=opts['force']) |
1313 q.save_dirty() |
1296 q.save_dirty() |
1314 return 0 |
1297 return 0 |
1334 return 0 |
1317 return 0 |
1335 |
1318 |
1336 def fold(ui, repo, *files, **opts): |
1319 def fold(ui, repo, *files, **opts): |
1337 """fold the named patches into the current patch |
1320 """fold the named patches into the current patch |
1338 |
1321 |
1339 Patches must not yet be applied. |
1322 Patches must not yet be applied. Each patch will be successively |
|
1323 applied to the current patch in the order given. If all the |
|
1324 patches apply successfully, the current patch will be refreshed |
|
1325 with the new cumulative patch, and the folded patches will |
|
1326 be deleted. With -f/--force, the folded patch files will |
|
1327 be removed afterwards. |
|
1328 |
1340 The header for each folded patch will be concatenated with |
1329 The header for each folded patch will be concatenated with |
1341 the current patch header, separated by a line of '* * *'.""" |
1330 the current patch header, separated by a line of '* * *'.""" |
1342 |
1331 |
1343 q = repo.mq |
1332 q = repo.mq |
1344 |
1333 |
1382 message = ui.edit(message, user or ui.username()) |
1371 message = ui.edit(message, user or ui.username()) |
1383 |
1372 |
1384 q.refresh(repo, msg=message) |
1373 q.refresh(repo, msg=message) |
1385 |
1374 |
1386 for patch in patches: |
1375 for patch in patches: |
1387 q.delete(repo, patch) |
1376 q.delete(repo, patch, force=opts['force']) |
1388 |
1377 |
1389 q.save_dirty() |
1378 q.save_dirty() |
1390 |
1379 |
1391 def header(ui, repo, patch=None): |
1380 def header(ui, repo, patch=None): |
1392 """Print the header of the topmost or specified patch""" |
1381 """Print the header of the topmost or specified patch""" |
1491 |
1480 |
1492 if ui.verbose: |
1481 if ui.verbose: |
1493 ui.write('Renaming %s to %s\n' % (patch, name)) |
1482 ui.write('Renaming %s to %s\n' % (patch, name)) |
1494 i = q.find_series(patch) |
1483 i = q.find_series(patch) |
1495 q.full_series[i] = name |
1484 q.full_series[i] = name |
1496 q.read_series(q.full_series) |
1485 q.parse_series() |
1497 q.series_dirty = 1 |
1486 q.series_dirty = 1 |
1498 |
1487 |
1499 info = q.isapplied(patch) |
1488 info = q.isapplied(patch) |
1500 if info: |
1489 if info: |
1501 q.applied[info[0]] = StatusEntry(info[1], name) |
1490 q.applied[info[0]] = StatusEntry(info[1], name) |
1615 [('f', 'force', None, _('delete patch file'))], |
1604 [('f', 'force', None, _('delete patch file'))], |
1616 'hg qdelete [-f] PATCH'), |
1605 'hg qdelete [-f] PATCH'), |
1617 'qfold': |
1606 'qfold': |
1618 (fold, |
1607 (fold, |
1619 [('e', 'edit', None, _('edit patch header')), |
1608 [('e', 'edit', None, _('edit patch header')), |
|
1609 ('f', 'force', None, _('delete folded patch files')), |
1620 ('m', 'message', '', _('set patch header to <text>')), |
1610 ('m', 'message', '', _('set patch header to <text>')), |
1621 ('l', 'logfile', '', _('set patch header to contents of <file>'))], |
1611 ('l', 'logfile', '', _('set patch header to contents of <file>'))], |
1622 'hg qfold [-e] [-m <text>] [-l <file] PATCH...'), |
1612 'hg qfold [-e] [-m <text>] [-l <file] PATCH...'), |
1623 'qheader': (header, [], |
1613 'qheader': (header, [], |
1624 _('hg qheader [PATCH]')), |
1614 _('hg qheader [PATCH]')), |