Add support for merge-friendly branches
[stgit] / stgit / commands / new.py
index 2c1e94b..9fd51c3 100644 (file)
@@ -16,60 +16,70 @@ along with this program; if not, write to the Free Software
 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 """
 
-import sys, os
-from optparse import OptionParser, make_option
-
-from stgit.commands.common import *
-from stgit.utils import *
-from stgit import stack, git
-
-
-help = 'create a new patch and make it the topmost one'
-usage = """%prog [options] <name>
-
-Create a new, empty patch and make it the topmost one. If the
-'--message' option is not passed, an editor is invoked with the
-.git/patchdescr.tmpl, ~/.stgit/templates/patchdescr.tmpl or
-/usr/share/stgit/templates/patchdescr.tmpl file used a as template,
-together with generated lines. By default, the local changes in the
-working tree are not included in the patch. A 'refresh' command is
-needed for this."""
-
-options = [make_option('-m', '--message',
-                       help = 'use MESSAGE as the patch description'),
-           make_option('-s', '--showpatch',
-                       help = 'show the patch content in the editor buffer',
-                       action = 'store_true'),
-           make_option('-a', '--author', metavar = '"NAME <EMAIL>"',
-                       help = 'use "NAME <EMAIL>" as the author details'),
-           make_option('--authname',
-                       help = 'use AUTHNAME as the author name'),
-           make_option('--authemail',
-                       help = 'use AUTHEMAIL as the author e-mail'),
-           make_option('--authdate',
-                       help = 'use AUTHDATE as the author date'),
-           make_option('--commname',
-                       help = 'use COMMNAME as the committer name'),
-           make_option('--commemail',
-                       help = 'use COMMEMAIL as the committer e-mail')]
+from stgit import argparse, utils
+from stgit.commands import common
+from stgit.lib import git as gitlib, transaction
+from stgit.config import config
 
+help = 'Create a new, empty patch'
+kind = 'patch'
+usage = ['[options] [<name>]']
+description = """
+Create a new, empty patch on the current stack. The new patch is
+created on top of the currently applied patches, and is made the new
+top of the stack. Uncommitted changes in the work tree are not
+included in the patch -- that is handled by linkstg:refresh[].
+
+The given name must be unique in the stack, and may only contain
+alphanumeric characters, dashes and underscores. If no name is given,
+one is generated from the first line of the patch's commit message.
+
+An editor will be launched to edit the commit message to be used for
+the patch, unless the '--message' flag already specified one. The
+'patchdescr.tmpl' template file (if available) is used to pre-fill the
+editor."""
+
+args = []
+options = (argparse.author_options()
+           + argparse.message_options(save_template = True)
+           + argparse.sign_options())
+
+directory = common.DirectoryHasRepositoryLib()
 
 def func(parser, options, args):
-    """Creates a new patch
-    """
-    if len(args) != 1:
+    """Create a new patch."""
+    stack = directory.repository.current_stack
+    if stack.repository.default_index.conflicts():
+        raise common.CmdException(
+            'Cannot create a new patch -- resolve conflicts first')
+
+    # Choose a name for the new patch -- or None, which means make one
+    # up later when we've gotten hold of the commit message.
+    if len(args) == 0:
+        name = None
+    elif len(args) == 1:
+        name = args[0]
+        if stack.patches.exists(name):
+            raise common.CmdException('%s: patch already exists' % name)
+    else:
         parser.error('incorrect number of arguments')
 
-    check_conflicts()
-    check_head_top_equal()
+    cd = gitlib.CommitData(
+        tree = stack.head.data.tree, parents = [stack.head], message = '',
+        author = gitlib.Person.author(), committer = gitlib.Person.committer())
+    cd = common.update_commit_data(cd, options, allow_edit = True)
+
+    if options.save_template:
+        options.save_template(cd.message)
+        return utils.STGIT_SUCCESS
 
-    if options.author:
-        options.authname, options.authemail = name_email(options.author)
+    if name == None:
+        name = utils.make_patch_name(cd.message,
+                                     lambda name: stack.patches.exists(name))
 
-    crt_series.new_patch(args[0], message = options.message,
-                         show_patch = options.showpatch,
-                         author_name = options.authname,
-                         author_email = options.authemail,
-                         author_date = options.authdate,
-                         committer_name = options.commname,
-                         committer_email = options.commemail)
+    # Write the new patch.
+    iw = stack.repository.default_iw
+    trans = transaction.StackTransaction(stack, 'new')
+    trans.patches[name] = stack.repository.commit(cd)
+    trans.applied.append(name)
+    return trans.run()