chiark / gitweb /
Implement "stg refresh --edit" again
authorKarl Hasselström <kha@treskal.com>
Sun, 21 Sep 2008 12:17:43 +0000 (14:17 +0200)
committerKarl Hasselström <kha@treskal.com>
Sun, 21 Sep 2008 12:19:07 +0000 (14:19 +0200)
The -e/--edit flag to "stg refresh" was dropped between v0.13 and
v0.14, causing severe user dissatisfaction. This patch restores it,
along with -m/--message, -f/--file, --sign, --ack, --author,
--authname, --authemail, and --authdate.

I omitted the --committer options on purpose; I think they are a
mistake. Falsifying the committer info is not a common operation, and
if one wishes to do it for some reason, one can always set the
GIT_COMMITTER_* environment variables.

Signed-off-by: Karl Hasselström <kha@treskal.com>
stgit/argparse.py
stgit/commands/coalesce.py
stgit/commands/edit.py
stgit/commands/new.py
stgit/commands/refresh.py

index d0134f80a33f6110f153dec10c1e0f8da63fb66f..bd71817f918dc8fed5d3f4ccda2167e3301bf1cc 100644 (file)
@@ -112,13 +112,13 @@ def sign_options():
             short = 'Add "Acked-by:" line', long = """
             Add an "Acked-by:" line to the end of the patch.""")]
 
-def message_options():
+def message_options(save_template):
     def no_dup(parser):
         if parser.values.message != None:
             raise optparse.OptionValueError(
                 'Cannot give more than one --message or --file')
     def no_combine(parser):
-        if (parser.values.message != None
+        if (save_template and parser.values.message != None
             and parser.values.save_template != None):
             raise optparse.OptionValueError(
                 'Cannot give both --message/--file and --save-template')
@@ -146,7 +146,7 @@ def message_options():
                 f.close()
         parser.values.save_template = w
         no_combine(parser)
-    return [
+    opts = [
         opt('-m', '--message', action = 'callback',
             callback = msg_callback, dest = 'message', type = 'string',
             short = 'Use MESSAGE instead of invoking the editor'),
@@ -154,18 +154,21 @@ def message_options():
             dest = 'message', type = 'string',
             short = 'Use FILE instead of invoking the editor', long = """
             Use the contents of FILE instead of invoking the editor.
-            (If FILE is "-", write to stdout.)"""),
-        opt('--save-template', action = 'callback', dest = 'save_template',
-            callback = templ_callback, metavar = 'FILE', type = 'string',
-            short = 'Save the message template to FILE and exit', long = """
-            Instead of running the command, just write the message
-            template to FILE, and exit. (If FILE is "-", write to
-            stdout.)
+            (If FILE is "-", write to stdout.)""")]
+    if save_template:
+        opts.append(
+            opt('--save-template', action = 'callback', dest = 'save_template',
+                callback = templ_callback, metavar = 'FILE', type = 'string',
+                short = 'Save the message template to FILE and exit', long = """
+                Instead of running the command, just write the message
+                template to FILE, and exit. (If FILE is "-", write to
+                stdout.)
 
-            When driving StGit from another program, it is often
-            useful to first call a command with '--save-template',
-            then let the user edit the message, and then call the same
-            command with '--file'.""")]
+                When driving StGit from another program, it is often
+                useful to first call a command with '--save-template',
+                then let the user edit the message, and then call the
+                same command with '--file'."""))
+    return opts
 
 def diff_opts_option():
     def diff_opts_callback(option, opt_str, value, parser):
@@ -204,5 +207,8 @@ def _person_opts(person, short):
              callback_args = (f,), short = 'Set the %s %s' % (person, f))
          for f in ['name', 'email', 'date']])
 
+def author_options():
+    return _person_opts('author', 'auth')
+
 def author_committer_options():
     return _person_opts('author', 'auth') + _person_opts('committer', 'comm')
index 024668a69fb7b817a847463e984e9c70ea97244c..ef8e912a9cdd31735c393ba8053b6b1d268944aa 100644 (file)
@@ -35,7 +35,7 @@ you specify, you will have to resolve them manually just as if you had
 done a sequence of pushes and pops yourself."""
 
 options = [opt('-n', '--name', short = 'Name of coalesced patch')
-           ] + argparse.message_options()
+           ] + argparse.message_options(save_template = True)
 
 directory = common.DirectoryHasRepositoryLib()
 
index 9043c0cf4e3fd57fb7fffd7d5f4846f0af16d43f..b370f5cbeb916be1d2695f6c5c8772285586be7f 100644 (file)
@@ -59,7 +59,8 @@ options = [
         short = 'Edit the patch diff'),
     opt('-e', '--edit', action = 'store_true',
         short = 'Invoke interactive editor'),
-    ] + (argparse.sign_options() + argparse.message_options() +
+    ] + (argparse.sign_options() +
+         argparse.message_options(save_template = True) +
          argparse.author_committer_options() + argparse.diff_opts_option())
 
 directory = common.DirectoryHasRepositoryLib()
index f36fbd6148bb41d0d02021506cd4d9327eac5fd0..4117e4e635497133489818212cf1a0f8d5c723c6 100644 (file)
@@ -40,7 +40,7 @@ the patch, unless the '--message' flag already specified one. The
 editor."""
 
 options = (argparse.author_committer_options()
-           + argparse.message_options()
+           + argparse.message_options(save_template = True)
            + argparse.sign_options())
 
 directory = common.DirectoryHasRepositoryLib()
index 384cfb958e84d9f8c24de9c6257448db130001c7..3c82906ada48be49b9776c72b603dd3e7ea3ca02 100644 (file)
@@ -20,9 +20,9 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 
 from stgit.argparse import opt
 from stgit.commands import common
-from stgit.lib import git, transaction
+from stgit.lib import git, transaction, edit
 from stgit.out import out
-from stgit import utils
+from stgit import argparse, utils
 
 help = 'Generate a new commit for the current patch'
 kind = 'patch'
@@ -56,7 +56,11 @@ options = [
         Instead of setting the patch top to the current contents of
         the worktree, set it to the current contents of the index."""),
     opt('-p', '--patch',
-        short = 'Refresh (applied) PATCH instead of the top patch')]
+        short = 'Refresh (applied) PATCH instead of the top patch'),
+    opt('-e', '--edit', action = 'store_true',
+        short = 'Invoke an editor for the patch description'),
+    ] + (argparse.message_options(save_template = False) +
+         argparse.sign_options() + argparse.author_options())
 
 directory = common.DirectoryHasRepositoryLib()
 
@@ -121,9 +125,12 @@ def make_temp_patch(stack, patch_name, paths, temp_index):
     return trans.run(stack.repository.default_iw,
                      print_current_patch = False), temp_name
 
-def absorb_applied(trans, iw, patch_name, temp_name):
+def absorb_applied(trans, iw, patch_name, temp_name, edit_fun):
     """Absorb the temp patch (C{temp_name}) into the given patch
-    (C{patch_name}), which must be applied.
+    (C{patch_name}), which must be applied. If the absorption
+    succeeds, call C{edit_fun} on the resulting
+    L{CommitData<stgit.lib.git.CommitData>} before committing it and
+    commit the return value.
 
     @return: C{True} if we managed to absorb the temp patch, C{False}
              if we had to leave it for the user to deal with."""
@@ -141,7 +148,7 @@ def absorb_applied(trans, iw, patch_name, temp_name):
         temp_cd = trans.patches[temp_name].data
         assert trans.patches[patch_name] == temp_cd.parent
         trans.patches[patch_name] = trans.stack.repository.commit(
-            trans.patches[patch_name].data.set_tree(temp_cd.tree))
+            edit_fun(trans.patches[patch_name].data.set_tree(temp_cd.tree)))
         popped = trans.delete_patches(lambda pn: pn == temp_name, quiet = True)
         assert not popped # the temp patch was topmost
         temp_absorbed = True
@@ -153,9 +160,12 @@ def absorb_applied(trans, iw, patch_name, temp_name):
         pass
     return temp_absorbed
 
-def absorb_unapplied(trans, iw, patch_name, temp_name):
+def absorb_unapplied(trans, iw, patch_name, temp_name, edit_fun):
     """Absorb the temp patch (C{temp_name}) into the given patch
-    (C{patch_name}), which must be unapplied.
+    (C{patch_name}), which must be unapplied. If the absorption
+    succeeds, call C{edit_fun} on the resulting
+    L{CommitData<stgit.lib.git.CommitData>} before committing it and
+    commit the return value.
 
     @param iw: Not used.
     @return: C{True} if we managed to absorb the temp patch, C{False}
@@ -179,7 +189,7 @@ def absorb_unapplied(trans, iw, patch_name, temp_name):
         # It worked. Refresh the patch with the new tree, and delete
         # the temp patch.
         trans.patches[patch_name] = trans.stack.repository.commit(
-            patch_cd.set_tree(new_tree))
+            edit_fun(patch_cd.set_tree(new_tree)))
         popped = trans.delete_patches(lambda pn: pn == temp_name, quiet = True)
         assert not popped # the temp patch was not applied
         return True
@@ -188,13 +198,13 @@ def absorb_unapplied(trans, iw, patch_name, temp_name):
         # leave the temp patch for the user.
         return False
 
-def absorb(stack, patch_name, temp_name):
+def absorb(stack, patch_name, temp_name, edit_fun):
     """Absorb the temp patch into the target patch."""
     trans = transaction.StackTransaction(stack, 'refresh')
     iw = stack.repository.default_iw
     f = { True: absorb_applied, False: absorb_unapplied
           }[patch_name in trans.applied]
-    if f(trans, iw, patch_name, temp_name):
+    if f(trans, iw, patch_name, temp_name, edit_fun):
         def info_msg(): pass
     else:
         def info_msg():
@@ -228,4 +238,16 @@ def func(parser, options, args):
         stack, patch_name, paths, temp_index = path_limiting)
     if retval != utils.STGIT_SUCCESS:
         return retval
-    return absorb(stack, patch_name, temp_name)
+    def edit_fun(cd):
+        cd, failed_diff = edit.auto_edit_patch(
+            stack.repository, cd, msg = options.message, contains_diff = False,
+            author = options.author, committer = lambda p: p,
+            sign_str = options.sign_str)
+        assert not failed_diff
+        if options.edit:
+            cd, failed_diff = edit.interactive_edit_patch(
+                stack.repository, cd, edit_diff = False,
+                diff_flags = [], replacement_diff = None)
+            assert not failed_diff
+        return cd
+    return absorb(stack, patch_name, temp_name, edit_fun)