From f9d69fc4927827056cba918d9900e638845864f6 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Karl=20Hasselstr=C3=B6m?= Date: Sun, 21 Sep 2008 14:17:43 +0200 Subject: [PATCH] Implement "stg refresh --edit" again MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit 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 --- stgit/argparse.py | 34 ++++++++++++++++++++-------------- stgit/commands/coalesce.py | 2 +- stgit/commands/edit.py | 3 ++- stgit/commands/new.py | 2 +- stgit/commands/refresh.py | 46 ++++++++++++++++++++++++++++++++++------------ 5 files changed, 58 insertions(+), 29 deletions(-) diff --git a/stgit/argparse.py b/stgit/argparse.py index d0134f8..bd71817 100644 --- a/stgit/argparse.py +++ b/stgit/argparse.py @@ -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') diff --git a/stgit/commands/coalesce.py b/stgit/commands/coalesce.py index 024668a..ef8e912 100644 --- a/stgit/commands/coalesce.py +++ b/stgit/commands/coalesce.py @@ -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() diff --git a/stgit/commands/edit.py b/stgit/commands/edit.py index 9043c0c..b370f5c 100644 --- a/stgit/commands/edit.py +++ b/stgit/commands/edit.py @@ -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() diff --git a/stgit/commands/new.py b/stgit/commands/new.py index f36fbd6..4117e4e 100644 --- a/stgit/commands/new.py +++ b/stgit/commands/new.py @@ -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() diff --git a/stgit/commands/refresh.py b/stgit/commands/refresh.py index 384cfb9..3c82906 100644 --- a/stgit/commands/refresh.py +++ b/stgit/commands/refresh.py @@ -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} 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} 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) -- 2.11.0