From 1020d08786c1413d488845f9175d01c0ea073a6c Mon Sep 17 00:00:00 2001 From: Conrad Irwin Date: Fri, 6 May 2011 22:59:59 -0700 Subject: Use a temporary index for git commit --interactive Change the behaviour of git commit --interactive so that when you abort the commit (by leaving the commit message empty) the index remains unchanged. Hitherto an aborted commit --interactive has added the selected hunks to the index regardless of whether the commit succeeded or not. Signed-off-by: Conrad Irwin Signed-off-by: Junio C Hamano diff --git a/Documentation/git-commit.txt b/Documentation/git-commit.txt index d0534b8..ed50271 100644 --- a/Documentation/git-commit.txt +++ b/Documentation/git-commit.txt @@ -41,7 +41,8 @@ The content to be added can be specified in several ways: 5. by using the --interactive switch with the 'commit' command to decide one by one which files should be part of the commit, before finalizing the - operation. Currently, this is done by invoking 'git add --interactive'. + operation. Currently, this is done by invoking 'git add --interactive' + on a temporary index. The `--dry-run` option can be used to obtain a summary of what is included by any of the above for the next diff --git a/builtin/commit.c b/builtin/commit.c index 67757e9..636aea6 100644 --- a/builtin/commit.c +++ b/builtin/commit.c @@ -336,18 +336,11 @@ static char *prepare_index(int argc, const char **argv, const char *prefix, int int fd; struct string_list partial; const char **pathspec = NULL; + char *old_index_env = NULL; int refresh_flags = REFRESH_QUIET; if (is_status) refresh_flags |= REFRESH_UNMERGED; - if (interactive) { - if (interactive_add(argc, argv, prefix) != 0) - die(_("interactive add failed")); - if (read_cache_preload(NULL) < 0) - die(_("index file corrupt")); - commit_style = COMMIT_AS_IS; - return get_index_file(); - } if (*argv) pathspec = get_pathspec(prefix, argv); @@ -355,6 +348,33 @@ static char *prepare_index(int argc, const char **argv, const char *prefix, int if (read_cache_preload(pathspec) < 0) die(_("index file corrupt")); + if (interactive) { + fd = hold_locked_index(&index_lock, 1); + + refresh_cache_or_die(refresh_flags); + + if (write_cache(fd, active_cache, active_nr) || + close_lock_file(&index_lock)) + die(_("unable to create temporary index")); + + old_index_env = getenv(INDEX_ENVIRONMENT); + setenv(INDEX_ENVIRONMENT, index_lock.filename, 1); + + if (interactive_add(argc, argv, prefix) != 0) + die(_("interactive add failed")); + + if (old_index_env && *old_index_env) + setenv(INDEX_ENVIRONMENT, old_index_env, 1); + else + unsetenv(INDEX_ENVIRONMENT); + + discard_cache(); + read_cache_from(index_lock.filename); + + commit_style = COMMIT_NORMAL; + return index_lock.filename; + } + /* * Non partial, non as-is commit. * -- cgit v0.10.2-6-g49f6 From 587ac8c9d4b4a9e054dddb4779f6206fde5950ef Mon Sep 17 00:00:00 2001 From: Jeff King Date: Mon, 9 May 2011 16:53:00 -0700 Subject: t7501.8: feed a meaningful command The command expects "git commit --interactive " to fail because you cannot (yet) limit "commit --interactive" with a pathspec, but even if the command allowed to take , the test would have failed as saying just 7:quit would leave the index the same as the current commit, leading to an attempt to create an empty commit that would fail without --allow-empty. Signed-off-by: Jeff King Signed-off-by: Junio C Hamano diff --git a/t/t7501-commit.sh b/t/t7501-commit.sh index a76c474..3d2b14d 100755 --- a/t/t7501-commit.sh +++ b/t/t7501-commit.sh @@ -41,10 +41,12 @@ test_expect_success \ "echo King of the bongo >file && test_must_fail git commit -m foo -a file" -test_expect_success PERL \ - "using paths with --interactive" \ - "echo bong-o-bong >file && - ! (echo 7 | git commit -m foo --interactive file)" +test_expect_success PERL 'cannot use paths with --interactive' ' + echo bong-o-bong >file && + # 2: update, 1:st path, that is all, 7: quit + ( echo 2; echo 1; echo; echo 7 ) | + test_must_fail git commit -m foo --interactive file +' test_expect_success \ "using invalid commit with -C" \ -- cgit v0.10.2-6-g49f6 From e41fcfe955cb8080bf8f0e16352d3131d1f01ac8 Mon Sep 17 00:00:00 2001 From: Conrad Irwin Date: Fri, 6 May 2011 23:00:00 -0700 Subject: Allow git commit --interactive with paths Make git commit --interactive feel more like git add --interactive by allowing the user to restrict the list of files they have to deal with. A test in t7501 used to ensure that this is not allowed; no need for that anymore. Signed-off-by: Conrad Irwin Signed-off-by: Junio C Hamano diff --git a/builtin/commit.c b/builtin/commit.c index 636aea6..7707af8 100644 --- a/builtin/commit.c +++ b/builtin/commit.c @@ -1084,8 +1084,6 @@ static int parse_and_validate_options(int argc, const char *argv[], if (all && argc > 0) die(_("Paths with -a does not make sense.")); - else if (interactive && argc > 0) - die(_("Paths with --interactive does not make sense.")); if (null_termination && status_format == STATUS_FORMAT_LONG) status_format = STATUS_FORMAT_PORCELAIN; diff --git a/t/t7501-commit.sh b/t/t7501-commit.sh index 3d2b14d..c2fd116 100755 --- a/t/t7501-commit.sh +++ b/t/t7501-commit.sh @@ -41,11 +41,12 @@ test_expect_success \ "echo King of the bongo >file && test_must_fail git commit -m foo -a file" -test_expect_success PERL 'cannot use paths with --interactive' ' +test_expect_success PERL 'can use paths with --interactive' ' echo bong-o-bong >file && # 2: update, 1:st path, that is all, 7: quit ( echo 2; echo 1; echo; echo 7 ) | - test_must_fail git commit -m foo --interactive file + git commit -m foo --interactive file && + git reset --hard HEAD^ ' test_expect_success \ -- cgit v0.10.2-6-g49f6 From b4bd466820ee272fccfefff1d23d64c7826d1d07 Mon Sep 17 00:00:00 2001 From: Conrad Irwin Date: Sat, 7 May 2011 10:58:07 -0700 Subject: Add support for -p/--patch to git-commit The --interactive flag is already shared by git add and git commit, share the -p and --patch flags too. Signed-off-by: Conrad Irwin Signed-off-by: Junio C Hamano diff --git a/Documentation/git-commit.txt b/Documentation/git-commit.txt index ed50271..7951cb7 100644 --- a/Documentation/git-commit.txt +++ b/Documentation/git-commit.txt @@ -8,11 +8,12 @@ git-commit - Record changes to the repository SYNOPSIS -------- [verse] -'git commit' [-a | --interactive] [-s] [-v] [-u] [--amend] [--dry-run] - [(-c | -C | --fixup | --squash) ] [-F | -m ] - [--reset-author] [--allow-empty] [--allow-empty-message] [--no-verify] - [-e] [--author=] [--date=] [--cleanup=] - [--status | --no-status] [-i | -o] [--] [...] +'git commit' [-a | --interactive | --patch] [-s] [-v] [-u] [--amend] + [--dry-run] [(-c | -C | --fixup | --squash) ] + [-F | -m ] [--reset-author] [--allow-empty] + [--allow-empty-message] [--no-verify] [-e] [--author=] + [--date=] [--cleanup=] [--status | --no-status] + [-i | -o] [--] [...] DESCRIPTION ----------- @@ -39,10 +40,10 @@ The content to be added can be specified in several ways: that have been removed from the working tree, and then perform the actual commit; -5. by using the --interactive switch with the 'commit' command to decide one - by one which files should be part of the commit, before finalizing the - operation. Currently, this is done by invoking 'git add --interactive' - on a temporary index. +5. by using the --interactive or --patch switches with the 'commit' command + to decide one by one which files or hunks should be part of the commit, + before finalizing the operation. See the ``Interactive Mode`` section of + linkgit:git-add[1] to learn how to operate these modes. The `--dry-run` option can be used to obtain a summary of what is included by any of the above for the next @@ -60,6 +61,12 @@ OPTIONS been modified and deleted, but new files you have not told git about are not affected. +-p:: +--patch:: + Use the interactive patch selection interface to chose + which changes to commit. See linkgit:git-add[1] for + details. + -C :: --reuse-message=:: Take an existing commit object, and reuse the log message diff --git a/builtin/add.c b/builtin/add.c index d39a6ab..f02524b 100644 --- a/builtin/add.c +++ b/builtin/add.c @@ -241,7 +241,7 @@ int run_add_interactive(const char *revision, const char *patch_mode, return status; } -int interactive_add(int argc, const char **argv, const char *prefix) +int interactive_add(int argc, const char **argv, const char *prefix, int patch) { const char **pathspec = NULL; @@ -252,7 +252,7 @@ int interactive_add(int argc, const char **argv, const char *prefix) } return run_add_interactive(NULL, - patch_interactive ? "--patch" : NULL, + patch ? "--patch" : NULL, pathspec); } @@ -377,7 +377,7 @@ int cmd_add(int argc, const char **argv, const char *prefix) if (patch_interactive) add_interactive = 1; if (add_interactive) - exit(interactive_add(argc - 1, argv + 1, prefix)); + exit(interactive_add(argc - 1, argv + 1, prefix, patch_interactive)); if (edit_interactive) return(edit_patch(argc, argv, prefix)); diff --git a/builtin/commit.c b/builtin/commit.c index 7707af8..008c1ec 100644 --- a/builtin/commit.c +++ b/builtin/commit.c @@ -83,7 +83,7 @@ static const char *template_file; static const char *author_message, *author_message_buffer; static char *edit_message, *use_message; static char *fixup_message, *squash_message; -static int all, edit_flag, also, interactive, only, amend, signoff; +static int all, edit_flag, also, interactive, patch_interactive, only, amend, signoff; static int quiet, verbose, no_verify, allow_empty, dry_run, renew_authorship; static int no_post_rewrite, allow_empty_message; static char *untracked_files_arg, *force_date, *ignore_submodule_arg; @@ -152,6 +152,7 @@ static struct option builtin_commit_options[] = { OPT_BOOLEAN('a', "all", &all, "commit all changed files"), OPT_BOOLEAN('i', "include", &also, "add specified files to index for commit"), OPT_BOOLEAN(0, "interactive", &interactive, "interactively add files"), + OPT_BOOLEAN('p', "patch", &patch_interactive, "interactively add changes"), OPT_BOOLEAN('o', "only", &only, "commit only specified files"), OPT_BOOLEAN('n', "no-verify", &no_verify, "bypass pre-commit hook"), OPT_BOOLEAN(0, "dry-run", &dry_run, "show what would be committed"), @@ -360,7 +361,7 @@ static char *prepare_index(int argc, const char **argv, const char *prefix, int old_index_env = getenv(INDEX_ENVIRONMENT); setenv(INDEX_ENVIRONMENT, index_lock.filename, 1); - if (interactive_add(argc, argv, prefix) != 0) + if (interactive_add(argc, argv, prefix, patch_interactive) != 0) die(_("interactive add failed")); if (old_index_env && *old_index_env) @@ -1061,8 +1062,11 @@ static int parse_and_validate_options(int argc, const char *argv[], author_message_buffer = read_commit_message(author_message); } + if (patch_interactive) + interactive = 1; + if (!!also + !!only + !!all + !!interactive > 1) - die(_("Only one of --include/--only/--all/--interactive can be used.")); + die(_("Only one of --include/--only/--all/--interactive/--patch can be used.")); if (argc == 0 && (also || (only && !amend))) die(_("No paths with --include/--only does not make sense.")); if (argc == 0 && only && amend) diff --git a/commit.h b/commit.h index 4198513..b432642 100644 --- a/commit.h +++ b/commit.h @@ -159,7 +159,7 @@ extern struct commit_list *get_shallow_commits(struct object_array *heads, int is_descendant_of(struct commit *, struct commit_list *); int in_merge_bases(struct commit *, struct commit **, int); -extern int interactive_add(int argc, const char **argv, const char *prefix); +extern int interactive_add(int argc, const char **argv, const char *prefix, int patch); extern int run_add_interactive(const char *revision, const char *patch_mode, const char **pathspec); -- cgit v0.10.2-6-g49f6 From e6b57a8a4ec6c7522facafe30409ecd2d6b181ba Mon Sep 17 00:00:00 2001 From: Conrad Irwin Date: Sat, 7 May 2011 10:59:04 -0700 Subject: Add commit to list of config.singlekey commands Signed-off-by: Conrad Irwin Signed-off-by: Junio C Hamano diff --git a/Documentation/config.txt b/Documentation/config.txt index 1b1d80d..1c7336c 100644 --- a/Documentation/config.txt +++ b/Documentation/config.txt @@ -1350,9 +1350,10 @@ interactive.singlekey:: In interactive commands, allow the user to provide one-letter input with a single key (i.e., without hitting enter). Currently this is used by the `\--patch` mode of - linkgit:git-add[1], linkgit:git-reset[1], linkgit:git-stash[1] and - linkgit:git-checkout[1]. Note that this setting is silently - ignored if portable keystroke input is not available. + linkgit:git-add[1], linkgit:git-checkout[1], linkgit:git-commit[1], + linkgit:git-reset[1], and linkgit:git-stash[1]. Note that this + setting is silently ignored if portable keystroke input + is not available. log.date:: Set the default date-time mode for the 'log' command. -- cgit v0.10.2-6-g49f6 From 02a481fc6aef5d8a52f900448657d1cbe7c963ef Mon Sep 17 00:00:00 2001 From: Conrad Irwin Date: Tue, 10 May 2011 12:12:31 -0700 Subject: Test atomic git-commit --interactive Signed-off-by: Conrad Irwin Helped-by: Jeff King Signed-off-by: Junio C Hamano diff --git a/t/t7501-commit.sh b/t/t7501-commit.sh index c2fd116..73e19c5 100755 --- a/t/t7501-commit.sh +++ b/t/t7501-commit.sh @@ -133,6 +133,16 @@ test_expect_success PERL \ "interactive add" \ "echo 7 | git commit --interactive | grep 'What now'" +test_expect_success PERL \ + "commit --interactive doesn't change index if editor aborts" \ + "echo zoo >file && + test_must_fail git diff --exit-code >diff1 && + (echo u ; echo '*' ; echo q) | + (EDITOR=: && export EDITOR && + test_must_fail git commit --interactive) && + git diff >diff2 && + test_cmp diff1 diff2" + test_expect_success \ "showing committed revisions" \ "git rev-list HEAD >current" -- cgit v0.10.2-6-g49f6