From: Junio C Hamano Date: Mon, 16 May 2011 23:47:10 +0000 (-0700) Subject: Merge branch 'ci/commit--interactive-atomic' X-Git-Tag: v1.7.6-rc0~64 X-Git-Url: https://git.lorimer.id.au/gitweb.git/diff_plain/7a77754cf6fde7b513da1283fe76179ffa930ecc?hp=-c Merge branch 'ci/commit--interactive-atomic' * ci/commit--interactive-atomic: Test atomic git-commit --interactive Add commit to list of config.singlekey commands Add support for -p/--patch to git-commit Allow git commit --interactive with paths t7501.8: feed a meaningful command Use a temporary index for git commit --interactive --- 7a77754cf6fde7b513da1283fe76179ffa930ecc diff --combined Documentation/config.txt index 285c7f73ca,1c7336ccb8..1a060ecbc8 --- a/Documentation/config.txt +++ b/Documentation/config.txt @@@ -442,6 -442,8 +442,6 @@@ for most projects as source code and ot be delta compressed, but larger binary media files won't be. + Common unit suffixes of 'k', 'm', or 'g' are supported. -+ -Currently only linkgit:git-fast-import[1] honors this setting. core.excludesfile:: In addition to '.gitignore' (per-directory) and @@@ -587,8 -589,6 +587,8 @@@ it will be treated as a shell command "gitk --all --not ORIG_HEAD". Note that shell commands will be executed from the top-level directory of a repository, which may not necessarily be the current directory. +'GIT_PREFIX' is set as returned by running 'git rev-parse --show-prefix' +from the original current directory. See linkgit:git-rev-parse[1]. am.keepcr:: If true, git-am will call git-mailsplit for patches in mbox format @@@ -643,7 -643,7 +643,7 @@@ branch..remote: branch..merge:: Defines, together with branch..remote, the upstream branch - for the given branch. It tells 'git fetch'/'git pull' which + for the given branch. It tells 'git fetch'/'git pull'/'git rebase' which branch to merge and can also affect 'git push' (see push.default). When in branch , it tells 'git fetch' the default refspec to be marked for merging in FETCH_HEAD. The value is @@@ -708,16 -708,9 +708,16 @@@ second is the background. The positio doesn't matter. color.diff:: - When set to `always`, always use colors in patch. - When false (or `never`), never. When set to `true` or `auto`, use - colors only when the output is to the terminal. Defaults to false. + Whether to use ANSI escape sequences to add color to patches. + If this is set to `always`, linkgit:git-diff[1], + linkgit:git-log[1], and linkgit:git-show[1] will use color + for all patches. If it is set to `true` or `auto`, those + commands will only use color when output is to the terminal. + Defaults to false. ++ +This does not affect linkgit:git-format-patch[1] nor the +'git-diff-{asterisk}' plumbing commands. Can be overridden on the +command line with the `--color[=]` option. color.diff.:: Use customized color for diff colorization. `` specifies @@@ -803,15 -796,11 +803,15 @@@ color.status.: color.branch.. color.ui:: - When set to `always`, always use colors in all git commands which - are capable of colored output. When false (or `never`), never. When - set to `true` or `auto`, use colors only when the output is to the - terminal. When more specific variables of color.* are set, they always - take precedence over this setting. Defaults to false. + This variable determines the default value for variables such + as `color.diff` and `color.grep` that control the use of color + per command family. Its scope will expand as more commands learn + configuration to set a default for the `--color` option. Set it + to `always` if you want all output not intended for machine + consumption to use color, to `true` or `auto` if you want such + output to use color when written to the terminal, or to `false` or + `never` if you prefer git commands not to use color unless enabled + explicitly with some other configuration or the `--color` option. commit.status:: A boolean to enable/disable inclusion of status information in the @@@ -823,7 -812,68 +823,7 @@@ commit.template: "{tilde}/" is expanded to the value of `$HOME` and "{tilde}user/" to the specified user's home directory. -diff.autorefreshindex:: - When using 'git diff' to compare with work tree - files, do not consider stat-only change as changed. - Instead, silently run `git update-index --refresh` to - update the cached stat information for paths whose - contents in the work tree match the contents in the - index. This option defaults to true. Note that this - affects only 'git diff' Porcelain, and not lower level - 'diff' commands such as 'git diff-files'. - -diff.external:: - If this config variable is set, diff generation is not - performed using the internal diff machinery, but using the - given command. Can be overridden with the `GIT_EXTERNAL_DIFF' - environment variable. The command is called with parameters - as described under "git Diffs" in linkgit:git[1]. Note: if - you want to use an external diff program only on a subset of - your files, you might want to use linkgit:gitattributes[5] instead. - -diff.mnemonicprefix:: - If set, 'git diff' uses a prefix pair that is different from the - standard "a/" and "b/" depending on what is being compared. When - this configuration is in effect, reverse diff output also swaps - the order of the prefixes: -`git diff`;; - compares the (i)ndex and the (w)ork tree; -`git diff HEAD`;; - compares a (c)ommit and the (w)ork tree; -`git diff --cached`;; - compares a (c)ommit and the (i)ndex; -`git diff HEAD:file1 file2`;; - compares an (o)bject and a (w)ork tree entity; -`git diff --no-index a b`;; - compares two non-git things (1) and (2). - -diff.noprefix:: - If set, 'git diff' does not show any source or destination prefix. - -diff.renameLimit:: - The number of files to consider when performing the copy/rename - detection; equivalent to the 'git diff' option '-l'. - -diff.renames:: - Tells git to detect renames. If set to any boolean value, it - will enable basic rename detection. If set to "copies" or - "copy", it will detect copies, as well. - -diff.ignoreSubmodules:: - Sets the default value of --ignore-submodules. Note that this - affects only 'git diff' Porcelain, and not lower level 'diff' - commands such as 'git diff-files'. 'git checkout' also honors - this setting when reporting uncommitted changes. - -diff.suppressBlankEmpty:: - A boolean to inhibit the standard behavior of printing a space - before each empty output line. Defaults to false. - -diff.tool:: - Controls which diff tool is used. `diff.tool` overrides - `merge.tool` when used by linkgit:git-difftool[1] and has - the same valid values as `merge.tool` minus "tortoisemerge" - and plus "kompare". +include::diff-config.txt[] difftool..path:: Override the path for the given tool. This is useful in case @@@ -927,16 -977,6 +927,16 @@@ format.signoff: the rights to submit this work under the same open source license. Please see the 'SubmittingPatches' document for further discussion. +filter..clean:: + The command which is used to convert the content of a worktree + file to a blob upon checkin. See linkgit:gitattributes[5] for + details. + +filter..smudge:: + The command which is used to convert the content of a blob + object to a worktree file upon checkout. See + linkgit:gitattributes[5] for details. + gc.aggressiveWindow:: The window size parameter used in the delta compression algorithm used by 'git gc --aggressive'. This defaults @@@ -1310,9 -1350,10 +1310,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. diff --combined builtin/add.c index e57abddf52,f02524bae0..c59b0c98fe --- a/builtin/add.c +++ b/builtin/add.c @@@ -26,27 -26,6 +26,27 @@@ struct update_callback_data int add_errors; }; +static int fix_unmerged_status(struct diff_filepair *p, + struct update_callback_data *data) +{ + if (p->status != DIFF_STATUS_UNMERGED) + return p->status; + if (!(data->flags & ADD_CACHE_IGNORE_REMOVAL) && !p->two->mode) + /* + * This is not an explicit add request, and the + * path is missing from the working tree (deleted) + */ + return DIFF_STATUS_DELETED; + else + /* + * Either an explicit add request, or path exists + * in the working tree. An attempt to explicitly + * add a path that does not exist in the working tree + * will be caught as an error by the caller immediately. + */ + return DIFF_STATUS_MODIFIED; +} + static void update_callback(struct diff_queue_struct *q, struct diff_options *opt, void *cbdata) { @@@ -56,9 -35,30 +56,9 @@@ for (i = 0; i < q->nr; i++) { struct diff_filepair *p = q->queue[i]; const char *path = p->one->path; - switch (p->status) { + switch (fix_unmerged_status(p, data)) { default: die(_("unexpected diff status %c"), p->status); - case DIFF_STATUS_UNMERGED: - /* - * ADD_CACHE_IGNORE_REMOVAL is unset if "git - * add -u" is calling us, In such a case, a - * missing work tree file needs to be removed - * if there is an unmerged entry at stage #2, - * but such a diff record is followed by - * another with DIFF_STATUS_DELETED (and if - * there is no stage #2, we won't see DELETED - * nor MODIFIED). We can simply continue - * either way. - */ - if (!(data->flags & ADD_CACHE_IGNORE_REMOVAL)) - continue; - /* - * Otherwise, it is "git add path" is asking - * to explicitly add it; we fall through. A - * missing work tree file is an error and is - * caught by add_file_to_index() in such a - * case. - */ case DIFF_STATUS_MODIFIED: case DIFF_STATUS_TYPE_CHANGED: if (add_file_to_index(&the_index, path, data->flags)) { @@@ -91,7 -91,6 +91,7 @@@ int add_files_to_cache(const char *pref data.flags = flags; data.add_errors = 0; rev.diffopt.format_callback_data = &data; + rev.max_count = 0; /* do not compare unmerged paths with stage #2 */ run_diff_files(&rev, DIFF_RACY_IS_MODIFIED); return !!data.add_errors; } @@@ -242,7 -241,7 +242,7 @@@ int run_add_interactive(const char *rev 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; @@@ -253,7 -252,7 +253,7 @@@ } return run_add_interactive(NULL, - patch_interactive ? "--patch" : NULL, + patch ? "--patch" : NULL, pathspec); } @@@ -331,8 -330,8 +331,8 @@@ static struct option builtin_add_option static int add_config(const char *var, const char *value, void *cb) { - if (!strcasecmp(var, "add.ignoreerrors") || - !strcasecmp(var, "add.ignore-errors")) { + if (!strcmp(var, "add.ignoreerrors") || + !strcmp(var, "add.ignore-errors")) { ignore_add_errors = git_config_bool(var, value); return 0; } @@@ -378,7 -377,7 +378,7 @@@ int cmd_add(int argc, const char **argv 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 --combined builtin/commit.c index 411d5e4153,008c1ec838..5286432f39 --- a/builtin/commit.c +++ b/builtin/commit.c @@@ -83,7 -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 +152,7 @@@ static struct option builtin_commit_opt 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"), @@@ -336,18 -337,11 +337,11 @@@ static char *prepare_index(int argc, co 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 -349,33 +349,33 @@@ 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, patch_interactive) != 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. * @@@ -615,7 -636,6 +636,7 @@@ static int prepare_to_commit(const cha const char *hook_arg1 = NULL; const char *hook_arg2 = NULL; int ident_shown = 0; + int clean_message_contents = (cleanup_mode != CLEANUP_NONE); if (!no_verify && run_hook(index_file, "pre-commit", NULL)) return 0; @@@ -682,7 -702,6 +703,7 @@@ if (strbuf_read_file(&sb, template_file, 0) < 0) die_errno(_("could not read '%s'"), template_file); hook_arg1 = "template"; + clean_message_contents = 0; } /* @@@ -710,7 -729,7 +731,7 @@@ if (s->fp == NULL) die_errno(_("could not open '%s'"), git_path(commit_editmsg)); - if (cleanup_mode != CLEANUP_NONE) + if (clean_message_contents) stripspace(&sb, 0); if (signoff) { @@@ -1043,8 -1062,11 +1064,11 @@@ static int parse_and_validate_options(i 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) @@@ -1066,8 -1088,6 +1090,6 @@@ 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 --combined commit.h index b3c3bb70c5,b432642b99..43940e2bdd --- a/commit.h +++ b/commit.h @@@ -90,8 -90,6 +90,8 @@@ extern char *logmsg_reencode(const stru extern char *reencode_commit_message(const struct commit *commit, const char **encoding_p); extern void get_commit_format(const char *arg, struct rev_info *); +extern const char *format_subject(struct strbuf *sb, const char *msg, + const char *line_separator); extern void userformat_find_requirements(const char *fmt, struct userformat_want *w); extern void format_commit_message(const struct commit *commit, const char *format, struct strbuf *sb, @@@ -161,7 -159,7 +161,7 @@@ extern struct commit_list *get_shallow_ 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); diff --combined t/t7501-commit.sh index 7f7f7c7b95,73e19c50b0..3ad04363b5 --- a/t/t7501-commit.sh +++ b/t/t7501-commit.sh @@@ -16,10 -16,9 +16,10 @@@ test_expect_success "echo 'bongo bongo' >file && git add file" -test_expect_success C_LOCALE_OUTPUT \ - "Constructing initial commit" \ - "git status | grep 'Initial commit'" +test_expect_success "Constructing initial commit" ' + git status >actual && + test_i18ngrep "Initial commit" actual +' test_expect_success \ "fail initial amend" \ @@@ -42,10 -41,13 +42,13 @@@ 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 '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 ) | + git commit -m foo --interactive file && + git reset --hard HEAD^ + ' test_expect_success \ "using invalid commit with -C" \ @@@ -130,6 -132,16 +133,16 @@@ test_expect_success 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" \