Generate unique patch names
[stgit] / stgit / commands / uncommit.py
... / ...
CommitLineData
1# -*- coding: utf-8 -*-
2
3__copyright__ = """
4Copyright (C) 2006, Karl Hasselström <kha@treskal.com>
5
6This program is free software; you can redistribute it and/or modify
7it under the terms of the GNU General Public License version 2 as
8published by the Free Software Foundation.
9
10This program is distributed in the hope that it will be useful,
11but WITHOUT ANY WARRANTY; without even the implied warranty of
12MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13GNU General Public License for more details.
14
15You should have received a copy of the GNU General Public License
16along with this program; if not, write to the Free Software
17Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18"""
19
20import sys, os
21from optparse import OptionParser, make_option
22
23from stgit.commands.common import *
24from stgit.utils import *
25from stgit import stack, git
26
27help = 'turn regular GIT commits into StGIT patches'
28usage = """%prog [options] [<patchname1> [<patchname2> ... ]]
29
30Take one or more git commits at the base of the current stack and turn
31them into StGIT patches. The new patches are created as applied patches
32at the bottom of the stack. This is the exact opposite of 'stg commit'.
33
34By default, the number of patches to uncommit is determined by the
35number of patch names provided on the command line. First name is used
36for the first patch to uncommit, i.e. for the newest patch.
37
38The --number option specifies the number of patches to uncommit. In
39this case, at most one patch name may be specified. It is used as
40prefix to which the patch number is appended.
41
42If no patch names are provided on the command line, StGIT
43automatically generates them based on the first line of the patch
44description.
45
46Only commits with exactly one parent can be uncommitted; in other
47words, you can't uncommit a merge."""
48
49options = [make_option('-n', '--number', type = 'int',
50 help = 'uncommit the specified number of commits')]
51
52def func(parser, options, args):
53 """Uncommit a number of patches.
54 """
55 if options.number:
56 if options.number <= 0:
57 parser.error('invalid value passed to --number')
58
59 patch_nr = options.number
60
61 if len(args) == 0:
62 patchnames = None
63 elif len(args) == 1:
64 # prefix specified
65 patchnames = ['%s%d' % (args[0], i)
66 for i in xrange(patch_nr, 0, -1)]
67 else:
68 parser.error('when using --number, specify at most one patch name')
69 elif len(args) == 0:
70 patchnames = None
71 patch_nr = 1
72 else:
73 patchnames = args
74 patch_nr = len(patchnames)
75
76 if crt_series.get_protected():
77 raise CmdException, \
78 'This branch is protected. Uncommit is not permitted'
79
80 print 'Uncommitting %d patches...' % patch_nr,
81 sys.stdout.flush()
82
83 base_file = crt_series.get_base_file()
84
85 for n in xrange(0, patch_nr):
86 # retrieve the commit (only commits with a single parent are allowed)
87 commit_id = read_string(base_file)
88 commit = git.Commit(commit_id)
89 try:
90 parent, = commit.get_parents()
91 except ValueError:
92 raise CmdException, 'Commit %s does not have exactly one parent' \
93 % commit_id
94 author_name, author_email, author_date = \
95 name_email_date(commit.get_author())
96
97 if patchnames:
98 patchname = patchnames[n]
99 else:
100 patchname = make_patch_name(commit.get_log(),
101 crt_series.patch_exists)
102
103 crt_series.new_patch(patchname,
104 can_edit = False, before_existing = True,
105 top = commit_id, bottom = parent,
106 message = commit.get_log(),
107 author_name = author_name,
108 author_email = author_email,
109 author_date = author_date)
110 write_string(base_file, parent)
111
112 print 'done'