comparison mercurial/commands.py @ 2158:ec96c4518236

add backout command. command undoes effect of an earlier commit, commits new changeset as result.
author Vadim Gelfer <vadim.gelfer@gmail.com>
date Sat, 29 Apr 2006 20:56:46 -0700
parents 635653cd73ab
children 5c34b98ad6b1
comparison
equal deleted inserted replaced
2157:1e82f2337498 2158:ec96c4518236
16 16
17 class UnknownCommand(Exception): 17 class UnknownCommand(Exception):
18 """Exception raised if command is not in the command table.""" 18 """Exception raised if command is not in the command table."""
19 class AmbiguousCommand(Exception): 19 class AmbiguousCommand(Exception):
20 """Exception raised if command shortcut matches more than one command.""" 20 """Exception raised if command shortcut matches more than one command."""
21
22 def bail_if_changed(repo):
23 modified, added, removed, deleted, unknown = repo.changes()
24 if modified or added or removed or deleted:
25 raise util.Abort(_("outstanding uncommitted changes"))
21 26
22 def filterfiles(filters, files): 27 def filterfiles(filters, files):
23 l = [x for x in files if x in filters] 28 l = [x for x in files if x in filters]
24 29
25 for t in filters: 30 for t in filters:
927 if os.path.realpath(dest) == repo.root: 932 if os.path.realpath(dest) == repo.root:
928 raise util.Abort(_('repository root cannot be destination')) 933 raise util.Abort(_('repository root cannot be destination'))
929 _, matchfn, _ = matchpats(repo, [], opts) 934 _, matchfn, _ = matchpats(repo, [], opts)
930 archival.archive(repo, dest, node, opts.get('type') or 'files', 935 archival.archive(repo, dest, node, opts.get('type') or 'files',
931 not opts['no_decode'], matchfn, prefix) 936 not opts['no_decode'], matchfn, prefix)
937
938 def backout(ui, repo, rev, **opts):
939 '''reverse effect of earlier changeset
940
941 Commit the backed out changes as a new changeset.
942
943 If you back out a changeset other than the tip, a new head is
944 created. The --merge option remembers the parent of the working
945 directory before starting the backout, then merges the new head
946 with it afterwards, to save you from doing this by hand. The
947 result of this merge is not committed, as for a normal merge.'''
948
949 bail_if_changed(repo)
950 op1, op2 = repo.dirstate.parents()
951 if op2 != nullid:
952 raise util.Abort(_('outstanding uncommitted merge'))
953 node = repo.lookup(rev)
954 parent, p2 = repo.changelog.parents(node)
955 if parent == nullid:
956 raise util.Abort(_('cannot back out a change with no parents'))
957 if p2 != nullid:
958 raise util.Abort(_('cannot back out a merge'))
959 repo.update(node, force=True)
960 revert_opts = opts.copy()
961 revert_opts['rev'] = hex(parent)
962 revert(ui, repo, **revert_opts)
963 commit_opts = opts.copy()
964 commit_opts['addremove'] = False
965 if not commit_opts['message']:
966 commit_opts['message'] = _("Backed out changeset %s") % (hex(node))
967 commit(ui, repo, **commit_opts)
968 def nice(node):
969 return '%d:%s' % (repo.changelog.rev(node), short(node))
970 ui.status(_('changeset %s backs out changeset %s\n') %
971 (nice(repo.changelog.tip()), nice(node)))
972 if opts['merge'] and op1 != node:
973 ui.status(_('merging with changeset %s\n') % nice(op1))
974 update(ui, repo, hex(op1), **opts)
932 975
933 def bundle(ui, repo, fname, dest="default-push", **opts): 976 def bundle(ui, repo, fname, dest="default-push", **opts):
934 """create a changegroup file 977 """create a changegroup file
935 978
936 Generate a compressed changegroup file collecting all changesets 979 Generate a compressed changegroup file collecting all changesets
1795 safety check, not to import a real mail message. 1838 safety check, not to import a real mail message.
1796 """ 1839 """
1797 patches = (patch1,) + patches 1840 patches = (patch1,) + patches
1798 1841
1799 if not opts['force']: 1842 if not opts['force']:
1800 modified, added, removed, deleted, unknown = repo.changes() 1843 bail_if_changed(repo)
1801 if modified or added or removed or deleted:
1802 raise util.Abort(_("outstanding uncommitted changes"))
1803 1844
1804 d = opts["base"] 1845 d = opts["base"]
1805 strip = opts["strip"] 1846 strip = opts["strip"]
1806 1847
1807 mailre = re.compile(r'(?:From |[\w-]+:)') 1848 mailre = re.compile(r'(?:From |[\w-]+:)')
2897 ('r', 'rev', '', _('revision to distribute')), 2938 ('r', 'rev', '', _('revision to distribute')),
2898 ('t', 'type', '', _('type of distribution to create')), 2939 ('t', 'type', '', _('type of distribution to create')),
2899 ('I', 'include', [], _('include names matching the given patterns')), 2940 ('I', 'include', [], _('include names matching the given patterns')),
2900 ('X', 'exclude', [], _('exclude names matching the given patterns'))], 2941 ('X', 'exclude', [], _('exclude names matching the given patterns'))],
2901 _('hg archive [OPTION]... DEST')), 2942 _('hg archive [OPTION]... DEST')),
2943 'backout':
2944 (backout,
2945 [('', 'message', '', _('use <text> as commit message')),
2946 ('', 'merge', None, _('merge with old dirstate parent after backout')),
2947 ('l', 'logfile', '', _('read commit message from <file>')),
2948 ('d', 'date', '', _('record datecode as commit date')),
2949 ('u', 'user', '', _('record user as committer')),
2950 ('I', 'include', [], _('include names matching the given patterns')),
2951 ('X', 'exclude', [], _('exclude names matching the given patterns'))],
2952 _('hg backout [OPTION]... [FILE]...')),
2953
2902 "bundle": 2954 "bundle":
2903 (bundle, 2955 (bundle,
2904 [('f', 'force', None, 2956 [('f', 'force', None,
2905 _('run even when remote repository is unrelated'))], 2957 _('run even when remote repository is unrelated'))],
2906 _('hg bundle FILE DEST')), 2958 _('hg bundle FILE DEST')),