Signed-off-by: Felipe Contreras <felipe.contre...@gmail.com>
---
 Documentation/git-stage.txt            |  5 +++
 builtin/stage.c                        | 74 ++++++++++++++++++++++++++++++++++
 contrib/completion/git-completion.bash |  4 +-
 3 files changed, 82 insertions(+), 1 deletion(-)

diff --git a/Documentation/git-stage.txt b/Documentation/git-stage.txt
index 318bf45..3e52a66 100644
--- a/Documentation/git-stage.txt
+++ b/Documentation/git-stage.txt
@@ -15,6 +15,7 @@ SYNOPSIS
 'git stage diff' [options] [<commit>] [--] [<paths>...]
 'git stage rm' [options] [--] [<paths>...]
 'git stage apply' [options] [--] [<paths>...]
+'git stage edit'
 
 DESCRIPTION
 -----------
@@ -45,6 +46,10 @@ Remove files from the staging area only. See 
linkgit:git-rm[1] --staged.
 
 Apply a patch to the staging area. See linkgit:git-rm[1] --staged.
 
+'edit'::
+
+Manually edit the staging area (as a diff).
+
 SEE ALSO
 --------
 linkgit:git-add[1]
diff --git a/builtin/stage.c b/builtin/stage.c
index 3023d17..d3c58d5 100644
--- a/builtin/stage.c
+++ b/builtin/stage.c
@@ -6,6 +6,9 @@
 
 #include "builtin.h"
 #include "parse-options.h"
+#include "diff.h"
+#include "diffcore.h"
+#include "revision.h"
 
 static const char *const stage_usage[] = {
        N_("git stage [options] [--] <paths>..."),
@@ -16,6 +19,74 @@ static const char *const stage_usage[] = {
        NULL
 };
 
+static int do_reset(const char *prefix)
+{
+       const char *argv[] = { "reset", "--quiet", NULL };
+       return cmd_reset(2, argv, prefix);
+}
+
+static int do_apply(const char *file, const char *prefix)
+{
+       const char *argv[] = { "apply", "--recount", "--cached", file, NULL };
+       return cmd_apply(4, argv, prefix);
+}
+
+static int edit(int argc, const char **argv, const char *prefix)
+{
+       char *file = git_pathdup("STAGE_EDIT.patch");
+       int out;
+       struct rev_info rev;
+       int ret = 0;
+       struct stat st;
+
+       read_cache();
+
+       init_revisions(&rev, prefix);
+       rev.diffopt.context = 7;
+
+       argc = setup_revisions(argc, argv, &rev, NULL);
+       add_head_to_pending(&rev);
+       if (!rev.pending.nr) {
+               struct tree *tree;
+               tree = lookup_tree(EMPTY_TREE_SHA1_BIN);
+               add_pending_object(&rev, &tree->object, "HEAD");
+       }
+
+       rev.diffopt.output_format = DIFF_FORMAT_PATCH;
+       rev.diffopt.use_color = 0;
+       DIFF_OPT_SET(&rev.diffopt, IGNORE_DIRTY_SUBMODULES);
+
+       out = open(file, O_CREAT | O_WRONLY, 0666);
+       if (out < 0)
+               die(_("Could not open '%s' for writing."), file);
+       rev.diffopt.file = xfdopen(out, "w");
+       rev.diffopt.close_file = 1;
+
+       if (run_diff_index(&rev, 1))
+               die(_("Could not write patch"));
+       if (launch_editor(file, NULL, NULL))
+               exit(1);
+
+       if (stat(file, &st))
+               die_errno(_("Could not stat '%s'"), file);
+
+       ret = do_reset(prefix);
+       if (ret)
+               goto leave;
+
+       if (!st.st_size)
+               goto leave;
+
+       ret = do_apply(file, prefix);
+       if (ret)
+               goto leave;
+
+leave:
+       unlink(file);
+       free(file);
+       return ret;
+}
+
 int cmd_stage(int argc, const char **argv, const char *prefix)
 {
        struct option options[] = { OPT_END() };
@@ -46,6 +117,9 @@ int cmd_stage(int argc, const char **argv, const char 
*prefix)
 
                        return cmd_apply(argc, argv, prefix);
                }
+               if (!strcmp(argv[1], "edit")) {
+                       return edit(argc - 1, argv + 1, prefix);
+               }
        }
 
        return cmd_add(argc, argv, prefix);
diff --git a/contrib/completion/git-completion.bash 
b/contrib/completion/git-completion.bash
index 8cf26e2..2b81e78 100644
--- a/contrib/completion/git-completion.bash
+++ b/contrib/completion/git-completion.bash
@@ -1693,7 +1693,7 @@ _git_stage ()
 {
        __git_has_doubledash && return
 
-       local subcommands="add reset diff rm apply"
+       local subcommands="add reset diff rm apply edit"
        local subcommand="$(__git_find_on_cmdline "$subcommands")"
        if [ -z "$subcommand" ]; then
                __gitcomp "$subcommands"
@@ -1711,6 +1711,8 @@ _git_stage ()
                _git_rm;;
        apply)
                _git_apply;;
+       edit)
+               ;;
        *)
                _git_add;
        esac
-- 
1.8.4-fc

--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to