Mercurial > hg > mercurial-crew-with-dirclash
comparison hgext/mq.py @ 3098:fe9b13e35e46
Merge with crew
author | Matt Mackall <mpm@selenic.com> |
---|---|
date | Fri, 15 Sep 2006 15:22:45 -0500 |
parents | 7fa3d38a99b6 |
children | 15fde1970003 |
comparison
equal
deleted
inserted
replaced
3097:1b738357bba9 | 3098:fe9b13e35e46 |
---|---|
29 refresh contents of top applied patch qrefresh | 29 refresh contents of top applied patch qrefresh |
30 ''' | 30 ''' |
31 | 31 |
32 from mercurial.demandload import * | 32 from mercurial.demandload import * |
33 from mercurial.i18n import gettext as _ | 33 from mercurial.i18n import gettext as _ |
34 from mercurial import commands | |
34 demandload(globals(), "os sys re struct traceback errno bz2") | 35 demandload(globals(), "os sys re struct traceback errno bz2") |
35 demandload(globals(), "mercurial:cmdutil,commands,hg,patch,revlog,ui,util") | 36 demandload(globals(), "mercurial:cmdutil,hg,patch,revlog,ui,util") |
36 | 37 |
37 commands.norepo += " qclone qversion" | 38 commands.norepo += " qclone qversion" |
38 | 39 |
39 class statusentry: | 40 class statusentry: |
40 def __init__(self, rev, name=None): | 41 def __init__(self, rev, name=None): |
41 if not name: | 42 if not name: |
42 fields = rev.split(':') | 43 fields = rev.split(':', 1) |
43 if len(fields) == 2: | 44 if len(fields) == 2: |
44 self.rev, self.name = fields | 45 self.rev, self.name = fields |
45 else: | 46 else: |
46 self.rev, self.name = None, None | 47 self.rev, self.name = None, None |
47 else: | 48 else: |
480 err = 1 | 481 err = 1 |
481 break | 482 break |
482 tr.close() | 483 tr.close() |
483 return (err, n) | 484 return (err, n) |
484 | 485 |
485 def delete(self, repo, patches, keep=False): | 486 def delete(self, repo, patches, opts): |
486 realpatches = [] | 487 realpatches = [] |
488 appliedbase = 0 | |
489 forget = opts.get('forget') | |
487 for patch in patches: | 490 for patch in patches: |
488 patch = self.lookup(patch, strict=True) | 491 patch = self.lookup(patch, strict=True) |
489 info = self.isapplied(patch) | 492 info = self.isapplied(patch) |
490 if info: | 493 if info and not forget: |
491 raise util.Abort(_("cannot delete applied patch %s") % patch) | 494 raise util.Abort(_("cannot delete applied patch %s") % patch) |
492 if patch not in self.series: | 495 if patch not in self.series: |
493 raise util.Abort(_("patch %s not in series file") % patch) | 496 raise util.Abort(_("patch %s not in series file") % patch) |
497 if forget: | |
498 if not info: | |
499 raise util.Abort(_("cannot forget unapplied patch %s") % patch) | |
500 if info[0] != appliedbase: | |
501 raise util.Abort(_("patch %s not at base") % patch) | |
502 appliedbase += 1 | |
494 realpatches.append(patch) | 503 realpatches.append(patch) |
495 | 504 |
496 if not keep: | 505 if not opts.get('keep'): |
497 r = self.qrepo() | 506 r = self.qrepo() |
498 if r: | 507 if r: |
499 r.remove(realpatches, True) | 508 r.remove(realpatches, True) |
500 else: | 509 else: |
501 os.unlink(self.join(patch)) | 510 os.unlink(self.join(patch)) |
502 | 511 |
512 if forget: | |
513 del self.applied[:appliedbase] | |
514 self.applied_dirty = 1 | |
503 indices = [self.find_series(p) for p in realpatches] | 515 indices = [self.find_series(p) for p in realpatches] |
504 indices.sort() | 516 indices.sort() |
505 for i in indices[-1::-1]: | 517 for i in indices[-1::-1]: |
506 del self.full_series[i] | 518 del self.full_series[i] |
507 self.parse_series() | 519 self.parse_series() |
691 chgrpfile = bundle(backupch) | 703 chgrpfile = bundle(backupch) |
692 | 704 |
693 stripall(rev, revnum) | 705 stripall(rev, revnum) |
694 | 706 |
695 change = chlog.read(rev) | 707 change = chlog.read(rev) |
708 chlog.strip(revnum, revnum) | |
696 repo.manifest.strip(repo.manifest.rev(change[0]), revnum) | 709 repo.manifest.strip(repo.manifest.rev(change[0]), revnum) |
697 chlog.strip(revnum, revnum) | |
698 if saveheads: | 710 if saveheads: |
699 self.ui.status("adding branch\n") | 711 self.ui.status("adding branch\n") |
700 commands.unbundle(self.ui, repo, chgrpfile, update=False) | 712 commands.unbundle(self.ui, repo, chgrpfile, update=False) |
701 if backup != "strip": | 713 if backup != "strip": |
702 os.unlink(chgrpfile) | 714 os.unlink(chgrpfile) |
754 return self.series[sno] | 766 return self.series[sno] |
755 if not strict: | 767 if not strict: |
756 # return any partial match made above | 768 # return any partial match made above |
757 if res: | 769 if res: |
758 return res | 770 return res |
759 minus = patch.rsplit('-', 1) | 771 minus = patch.rfind('-') |
760 if len(minus) > 1: | 772 if minus >= 0: |
761 res = partial_name(minus[0]) | 773 res = partial_name(patch[:minus]) |
762 if res: | 774 if res: |
763 i = self.series.index(res) | 775 i = self.series.index(res) |
764 try: | 776 try: |
765 off = int(minus[1] or 1) | 777 off = int(patch[minus+1:] or 1) |
766 except(ValueError, OverflowError): | 778 except(ValueError, OverflowError): |
767 pass | 779 pass |
768 else: | 780 else: |
769 if i - off >= 0: | 781 if i - off >= 0: |
770 return self.series[i - off] | 782 return self.series[i - off] |
771 plus = patch.rsplit('+', 1) | 783 plus = patch.rfind('+') |
772 if len(plus) > 1: | 784 if plus >= 0: |
773 res = partial_name(plus[0]) | 785 res = partial_name(patch[:plus]) |
774 if res: | 786 if res: |
775 i = self.series.index(res) | 787 i = self.series.index(res) |
776 try: | 788 try: |
777 off = int(plus[1] or 1) | 789 off = int(patch[plus+1:] or 1) |
778 except(ValueError, OverflowError): | 790 except(ValueError, OverflowError): |
779 pass | 791 pass |
780 else: | 792 else: |
781 if i + off < len(self.series): | 793 if i + off < len(self.series): |
782 return self.series[i + off] | 794 return self.series[i + off] |
913 self.printdiff(repo, qp, files=pats, opts=opts) | 925 self.printdiff(repo, qp, files=pats, opts=opts) |
914 | 926 |
915 def refresh(self, repo, pats=None, **opts): | 927 def refresh(self, repo, pats=None, **opts): |
916 if len(self.applied) == 0: | 928 if len(self.applied) == 0: |
917 self.ui.write("No patches applied\n") | 929 self.ui.write("No patches applied\n") |
918 return | 930 return 1 |
919 wlock = repo.wlock() | 931 wlock = repo.wlock() |
920 self.check_toppatch(repo) | 932 self.check_toppatch(repo) |
921 (top, patch) = (self.applied[-1].rev, self.applied[-1].name) | 933 (top, patchfn) = (self.applied[-1].rev, self.applied[-1].name) |
922 top = revlog.bin(top) | 934 top = revlog.bin(top) |
923 cparents = repo.changelog.parents(top) | 935 cparents = repo.changelog.parents(top) |
924 patchparent = self.qparents(repo, top) | 936 patchparent = self.qparents(repo, top) |
925 message, comments, user, date, patchfound = self.readheaders(patch) | 937 message, comments, user, date, patchfound = self.readheaders(patchfn) |
926 | 938 |
927 patchf = self.opener(patch, "w") | 939 patchf = self.opener(patchfn, "w") |
928 msg = opts.get('msg', '').rstrip() | 940 msg = opts.get('msg', '').rstrip() |
929 if msg: | 941 if msg: |
930 if comments: | 942 if comments: |
931 # Remove existing message. | 943 # Remove existing message. |
932 ci = 0 | 944 ci = 0 |
992 | 1004 |
993 m = list(util.unique(mm)) | 1005 m = list(util.unique(mm)) |
994 r = list(util.unique(dd)) | 1006 r = list(util.unique(dd)) |
995 a = list(util.unique(aa)) | 1007 a = list(util.unique(aa)) |
996 filelist = filter(matchfn, util.unique(m + r + a)) | 1008 filelist = filter(matchfn, util.unique(m + r + a)) |
997 self.printdiff(repo, patchparent, files=filelist, | 1009 if opts.get('git'): |
998 changes=(m, a, r, [], u), fp=patchf) | 1010 self.diffopts().git = True |
1011 patch.diff(repo, patchparent, files=filelist, match=matchfn, | |
1012 fp=patchf, changes=(m, a, r, [], u), | |
1013 opts=self.diffopts()) | |
999 patchf.close() | 1014 patchf.close() |
1000 | 1015 |
1001 changes = repo.changelog.read(tip) | 1016 changes = repo.changelog.read(tip) |
1002 repo.dirstate.setparents(*cparents) | 1017 repo.dirstate.setparents(*cparents) |
1003 copies = [(f, repo.dirstate.copied(f)) for f in a] | 1018 copies = [(f, repo.dirstate.copied(f)) for f in a] |
1016 repo.dirstate.update(mm, 'n', st_mtime=0) | 1031 repo.dirstate.update(mm, 'n', st_mtime=0) |
1017 repo.dirstate.forget(forget) | 1032 repo.dirstate.forget(forget) |
1018 | 1033 |
1019 if not msg: | 1034 if not msg: |
1020 if not message: | 1035 if not message: |
1021 message = "patch queue: %s\n" % patch | 1036 message = "patch queue: %s\n" % patchfn |
1022 else: | 1037 else: |
1023 message = "\n".join(message) | 1038 message = "\n".join(message) |
1024 else: | 1039 else: |
1025 message = msg | 1040 message = msg |
1026 | 1041 |
1027 self.strip(repo, top, update=False, backup='strip', wlock=wlock) | 1042 self.strip(repo, top, update=False, backup='strip', wlock=wlock) |
1028 n = repo.commit(filelist, message, changes[1], force=1, wlock=wlock) | 1043 n = repo.commit(filelist, message, changes[1], force=1, wlock=wlock) |
1029 self.applied[-1] = statusentry(revlog.hex(n), patch) | 1044 self.applied[-1] = statusentry(revlog.hex(n), patchfn) |
1030 self.applied_dirty = 1 | 1045 self.applied_dirty = 1 |
1031 else: | 1046 else: |
1032 self.printdiff(repo, patchparent, fp=patchf) | 1047 self.printdiff(repo, patchparent, fp=patchf) |
1033 patchf.close() | 1048 patchf.close() |
1034 self.pop(repo, force=True, wlock=wlock) | 1049 self.pop(repo, force=True, wlock=wlock) |
1235 if len(self.applied): | 1250 if len(self.applied): |
1236 p = self.appliedname(-1) | 1251 p = self.appliedname(-1) |
1237 self.ui.write(p + '\n') | 1252 self.ui.write(p + '\n') |
1238 else: | 1253 else: |
1239 self.ui.write("No patches applied\n") | 1254 self.ui.write("No patches applied\n") |
1255 return 1 | |
1240 | 1256 |
1241 def next(self, repo): | 1257 def next(self, repo): |
1242 end = self.series_end() | 1258 end = self.series_end() |
1243 if end == len(self.series): | 1259 if end == len(self.series): |
1244 self.ui.write("All patches applied\n") | 1260 self.ui.write("All patches applied\n") |
1261 return 1 | |
1245 else: | 1262 else: |
1246 p = self.series[end] | 1263 p = self.series[end] |
1247 if self.ui.verbose: | 1264 if self.ui.verbose: |
1248 self.ui.write("%d " % self.series.index(p)) | 1265 self.ui.write("%d " % self.series.index(p)) |
1249 self.ui.write(p + '\n') | 1266 self.ui.write(p + '\n') |
1252 if len(self.applied) > 1: | 1269 if len(self.applied) > 1: |
1253 p = self.appliedname(-2) | 1270 p = self.appliedname(-2) |
1254 self.ui.write(p + '\n') | 1271 self.ui.write(p + '\n') |
1255 elif len(self.applied) == 1: | 1272 elif len(self.applied) == 1: |
1256 self.ui.write("Only one patch applied\n") | 1273 self.ui.write("Only one patch applied\n") |
1274 return 1 | |
1257 else: | 1275 else: |
1258 self.ui.write("No patches applied\n") | 1276 self.ui.write("No patches applied\n") |
1277 return 1 | |
1259 | 1278 |
1260 def qimport(self, repo, files, patch=None, existing=None, force=None): | 1279 def qimport(self, repo, files, patch=None, existing=None, force=None): |
1261 if len(files) > 1 and patch: | 1280 if len(files) > 1 and patch: |
1262 raise util.Abort(_('option "-n" not valid when importing multiple ' | 1281 raise util.Abort(_('option "-n" not valid when importing multiple ' |
1263 'files')) | 1282 'files')) |
1296 qrepo.add(added) | 1315 qrepo.add(added) |
1297 | 1316 |
1298 def delete(ui, repo, patch, *patches, **opts): | 1317 def delete(ui, repo, patch, *patches, **opts): |
1299 """remove patches from queue | 1318 """remove patches from queue |
1300 | 1319 |
1301 The patches must not be applied. | 1320 With --forget, mq will stop managing the named patches. The |
1302 With -k, the patch files are preserved in the patch directory.""" | 1321 patches must be applied and at the base of the stack. This option |
1322 is useful when the patches have been applied upstream. | |
1323 | |
1324 Otherwise, the patches must not be applied. | |
1325 | |
1326 With --keep, the patch files are preserved in the patch directory.""" | |
1303 q = repo.mq | 1327 q = repo.mq |
1304 q.delete(repo, (patch,) + patches, keep=opts.get('keep')) | 1328 q.delete(repo, (patch,) + patches, opts) |
1305 q.save_dirty() | 1329 q.save_dirty() |
1306 return 0 | 1330 return 0 |
1307 | 1331 |
1308 def applied(ui, repo, patch=None, **opts): | 1332 def applied(ui, repo, patch=None, **opts): |
1309 """print the patches already applied""" | 1333 """print the patches already applied""" |
1400 repo.mq.qseries(repo, missing=opts['missing'], summary=opts['summary']) | 1424 repo.mq.qseries(repo, missing=opts['missing'], summary=opts['summary']) |
1401 return 0 | 1425 return 0 |
1402 | 1426 |
1403 def top(ui, repo, **opts): | 1427 def top(ui, repo, **opts): |
1404 """print the name of the current patch""" | 1428 """print the name of the current patch""" |
1405 repo.mq.top(repo) | 1429 return repo.mq.top(repo) |
1406 return 0 | |
1407 | 1430 |
1408 def next(ui, repo, **opts): | 1431 def next(ui, repo, **opts): |
1409 """print the name of the next patch""" | 1432 """print the name of the next patch""" |
1410 repo.mq.next(repo) | 1433 return repo.mq.next(repo) |
1411 return 0 | |
1412 | 1434 |
1413 def prev(ui, repo, **opts): | 1435 def prev(ui, repo, **opts): |
1414 """print the name of the previous patch""" | 1436 """print the name of the previous patch""" |
1415 repo.mq.prev(repo) | 1437 return repo.mq.prev(repo) |
1416 return 0 | |
1417 | 1438 |
1418 def new(ui, repo, patch, **opts): | 1439 def new(ui, repo, patch, **opts): |
1419 """create a new patch | 1440 """create a new patch |
1420 | 1441 |
1421 qnew creates a new patch on top of the currently-applied patch | 1442 qnew creates a new patch on top of the currently-applied patch |
1447 if message: | 1468 if message: |
1448 raise util.Abort(_('option "-e" incompatible with "-m" or "-l"')) | 1469 raise util.Abort(_('option "-e" incompatible with "-m" or "-l"')) |
1449 patch = q.applied[-1].name | 1470 patch = q.applied[-1].name |
1450 (message, comment, user, date, hasdiff) = q.readheaders(patch) | 1471 (message, comment, user, date, hasdiff) = q.readheaders(patch) |
1451 message = ui.edit('\n'.join(message), user or ui.username()) | 1472 message = ui.edit('\n'.join(message), user or ui.username()) |
1452 q.refresh(repo, pats, msg=message, **opts) | 1473 ret = q.refresh(repo, pats, msg=message, **opts) |
1453 q.save_dirty() | 1474 q.save_dirty() |
1454 return 0 | 1475 return ret |
1455 | 1476 |
1456 def diff(ui, repo, *pats, **opts): | 1477 def diff(ui, repo, *pats, **opts): |
1457 """diff of the current patch""" | 1478 """diff of the current patch""" |
1458 repo.mq.diff(repo, pats, opts) | 1479 repo.mq.diff(repo, pats, opts) |
1459 return 0 | 1480 return 0 |
1474 q = repo.mq | 1495 q = repo.mq |
1475 | 1496 |
1476 if not files: | 1497 if not files: |
1477 raise util.Abort(_('qfold requires at least one patch name')) | 1498 raise util.Abort(_('qfold requires at least one patch name')) |
1478 if not q.check_toppatch(repo): | 1499 if not q.check_toppatch(repo): |
1479 raise util.Abort(_('No patches applied\n')) | 1500 raise util.Abort(_('No patches applied')) |
1480 | 1501 |
1481 message = commands.logmessage(opts) | 1502 message = commands.logmessage(opts) |
1482 if opts['edit']: | 1503 if opts['edit']: |
1483 if message: | 1504 if message: |
1484 raise util.Abort(_('option "-e" incompatible with "-m" or "-l"')) | 1505 raise util.Abort(_('option "-e" incompatible with "-m" or "-l"')) |
1569 if patch: | 1590 if patch: |
1570 patch = q.lookup(patch) | 1591 patch = q.lookup(patch) |
1571 else: | 1592 else: |
1572 if not q.applied: | 1593 if not q.applied: |
1573 ui.write('No patches applied\n') | 1594 ui.write('No patches applied\n') |
1574 return | 1595 return 1 |
1575 patch = q.lookup('qtip') | 1596 patch = q.lookup('qtip') |
1576 message = repo.mq.readheaders(patch)[0] | 1597 message = repo.mq.readheaders(patch)[0] |
1577 | 1598 |
1578 ui.write('\n'.join(message) + '\n') | 1599 ui.write('\n'.join(message) + '\n') |
1579 | 1600 |
1646 | 1667 |
1647 if not name: | 1668 if not name: |
1648 name = patch | 1669 name = patch |
1649 patch = None | 1670 patch = None |
1650 | 1671 |
1651 if name in q.series: | |
1652 raise util.Abort(_('A patch named %s already exists in the series file') % name) | |
1653 | |
1654 absdest = q.join(name) | |
1655 if os.path.exists(absdest): | |
1656 raise util.Abort(_('%s already exists') % absdest) | |
1657 | |
1658 if patch: | 1672 if patch: |
1659 patch = q.lookup(patch) | 1673 patch = q.lookup(patch) |
1660 else: | 1674 else: |
1661 if not q.applied: | 1675 if not q.applied: |
1662 ui.write(_('No patches applied\n')) | 1676 ui.write(_('No patches applied\n')) |
1663 return | 1677 return |
1664 patch = q.lookup('qtip') | 1678 patch = q.lookup('qtip') |
1679 absdest = q.join(name) | |
1680 if os.path.isdir(absdest): | |
1681 name = os.path.join(name, os.path.basename(patch)) | |
1682 absdest = q.join(name) | |
1683 if os.path.exists(absdest): | |
1684 raise util.Abort(_('%s already exists') % absdest) | |
1685 | |
1686 if name in q.series: | |
1687 raise util.Abort(_('A patch named %s already exists in the series file') % name) | |
1665 | 1688 |
1666 if ui.verbose: | 1689 if ui.verbose: |
1667 ui.write('Renaming %s to %s\n' % (patch, name)) | 1690 ui.write('Renaming %s to %s\n' % (patch, name)) |
1668 i = q.find_series(patch) | 1691 i = q.find_series(patch) |
1669 q.full_series[i] = name | 1692 q.full_series[i] = name |
1731 backup = 'all' | 1754 backup = 'all' |
1732 if opts['backup']: | 1755 if opts['backup']: |
1733 backup = 'strip' | 1756 backup = 'strip' |
1734 elif opts['nobackup']: | 1757 elif opts['nobackup']: |
1735 backup = 'none' | 1758 backup = 'none' |
1736 repo.mq.strip(repo, rev, backup=backup) | 1759 update = repo.dirstate.parents()[0] != revlog.nullid |
1760 repo.mq.strip(repo, rev, backup=backup, update=update) | |
1737 return 0 | 1761 return 0 |
1738 | 1762 |
1739 def select(ui, repo, *args, **opts): | 1763 def select(ui, repo, *args, **opts): |
1740 '''set or print guarded patches to push | 1764 '''set or print guarded patches to push |
1741 | 1765 |
1907 [('I', 'include', [], _('include names matching the given patterns')), | 1931 [('I', 'include', [], _('include names matching the given patterns')), |
1908 ('X', 'exclude', [], _('exclude names matching the given patterns'))], | 1932 ('X', 'exclude', [], _('exclude names matching the given patterns'))], |
1909 'hg qdiff [-I] [-X] [FILE]...'), | 1933 'hg qdiff [-I] [-X] [FILE]...'), |
1910 "qdelete|qremove|qrm": | 1934 "qdelete|qremove|qrm": |
1911 (delete, | 1935 (delete, |
1912 [('k', 'keep', None, _('keep patch file'))], | 1936 [('f', 'forget', None, _('stop managing an applied patch')), |
1913 'hg qdelete [-k] PATCH'), | 1937 ('k', 'keep', None, _('keep patch file'))], |
1938 'hg qdelete [-f] [-k] PATCH'), | |
1914 'qfold': | 1939 'qfold': |
1915 (fold, | 1940 (fold, |
1916 [('e', 'edit', None, _('edit patch header')), | 1941 [('e', 'edit', None, _('edit patch header')), |
1917 ('k', 'keep', None, _('keep folded patch files')), | 1942 ('k', 'keep', None, _('keep folded patch files')), |
1918 ('m', 'message', '', _('set patch header to <text>')), | 1943 ('m', 'message', '', _('set patch header to <text>')), |
1959 "^qrefresh": | 1984 "^qrefresh": |
1960 (refresh, | 1985 (refresh, |
1961 [('e', 'edit', None, _('edit commit message')), | 1986 [('e', 'edit', None, _('edit commit message')), |
1962 ('m', 'message', '', _('change commit message with <text>')), | 1987 ('m', 'message', '', _('change commit message with <text>')), |
1963 ('l', 'logfile', '', _('change commit message with <file> content')), | 1988 ('l', 'logfile', '', _('change commit message with <file> content')), |
1989 ('g', 'git', None, _('use git extended diff format')), | |
1964 ('s', 'short', None, 'short refresh'), | 1990 ('s', 'short', None, 'short refresh'), |
1965 ('I', 'include', [], _('include names matching the given patterns')), | 1991 ('I', 'include', [], _('include names matching the given patterns')), |
1966 ('X', 'exclude', [], _('exclude names matching the given patterns'))], | 1992 ('X', 'exclude', [], _('exclude names matching the given patterns'))], |
1967 'hg qrefresh [-I] [-X] [-e] [-m TEXT] [-l FILE] [-s] FILES...'), | 1993 'hg qrefresh [-I] [-X] [-e] [-m TEXT] [-l FILE] [-s] FILES...'), |
1968 'qrename|qmv': | 1994 'qrename|qmv': |
1990 'hg qselect [OPTION...] [GUARD...]'), | 2016 'hg qselect [OPTION...] [GUARD...]'), |
1991 "qseries": | 2017 "qseries": |
1992 (series, | 2018 (series, |
1993 [('m', 'missing', None, 'print patches not in series'), | 2019 [('m', 'missing', None, 'print patches not in series'), |
1994 ('s', 'summary', None, _('print first line of patch header'))], | 2020 ('s', 'summary', None, _('print first line of patch header'))], |
1995 'hg qseries [-m]'), | 2021 'hg qseries [-ms]'), |
1996 "^strip": | 2022 "^strip": |
1997 (strip, | 2023 (strip, |
1998 [('f', 'force', None, 'force multi-head removal'), | 2024 [('f', 'force', None, 'force multi-head removal'), |
1999 ('b', 'backup', None, 'bundle unrelated changesets'), | 2025 ('b', 'backup', None, 'bundle unrelated changesets'), |
2000 ('n', 'nobackup', None, 'no backups')], | 2026 ('n', 'nobackup', None, 'no backups')], |