Merge branch 'wc/add-i'
authorJunio C Hamano <gitster@pobox.com>
Wed, 5 Dec 2007 05:38:28 +0000 (21:38 -0800)
committerJunio C Hamano <gitster@pobox.com>
Wed, 5 Dec 2007 05:38:28 +0000 (21:38 -0800)
* wc/add-i:
git-add -i: add help text for list-and-choose UI
add -i: allow prefix highlighting for "Add untracked" as well.
Highlight keyboard shortcuts in git-add--interactive
Document all help keys in "git add -i" patch mode.
Add "--patch" option to git-add--interactive
add -i: Fix running from a subdirectory
builtin-add: fix command line building to call interactive
git-add -i: allow multiple selection in patch subcommand
Add path-limiting to git-add--interactive
Teach builtin-add to pass multiple paths to git-add--interactive

1  2 
builtin-commit.c
diff --combined builtin-commit.c
index e635d9963b6ff6ade7742e801bc1cb0583059027,45e51b1d5f8446b5c6bc6e69f1bf1b95eb870826..2ec8223132807e1df77512d3d77efd71b790496a
@@@ -27,11 -27,6 +27,11 @@@ static const char * const builtin_commi
        NULL
  };
  
 +static const char * const builtin_status_usage[] = {
 +      "git-status [options] [--] <filepattern>...",
 +      NULL
 +};
 +
  static unsigned char head_sha1[20], merge_head_sha1[20];
  static char *use_message_buffer;
  static const char commit_editmsg[] = "COMMIT_EDITMSG";
@@@ -46,7 -41,7 +46,7 @@@ static enum 
  static char *logfile, *force_author, *template_file;
  static char *edit_message, *use_message;
  static int all, edit_flag, also, interactive, only, amend, signoff;
 -static int quiet, verbose, untracked_files, no_verify;
 +static int quiet, verbose, untracked_files, no_verify, allow_empty;
  
  static int no_edit, initial_commit, in_merge;
  const char *only_include_assumed;
@@@ -87,7 -82,6 +87,7 @@@ static struct option builtin_commit_opt
        OPT_BOOLEAN('n', "no-verify", &no_verify, "bypass pre-commit hook"),
        OPT_BOOLEAN(0, "amend", &amend, "amend previous commit"),
        OPT_BOOLEAN(0, "untracked-files", &untracked_files, "show all untracked files"),
 +      OPT_BOOLEAN(0, "allow-empty", &allow_empty, "ok to record an empty change"),
  
        OPT_END()
  };
@@@ -163,7 -157,7 +163,7 @@@ static void add_remove_files(struct pat
        }
  }
  
- static char *prepare_index(const char **files, const char *prefix)
+ static char *prepare_index(int argc, const char **argv, const char *prefix)
  {
        int fd;
        struct tree *tree;
        const char **pathspec = NULL;
  
        if (interactive) {
-               interactive_add();
+               interactive_add(argc, argv, prefix);
                commit_style = COMMIT_AS_IS;
                return get_index_file();
        }
        if (read_cache() < 0)
                die("index file corrupt");
  
-       if (*files)
-               pathspec = get_pathspec(prefix, files);
+       if (*argv)
+               pathspec = get_pathspec(prefix, argv);
  
        /*
         * Non partial, non as-is commit.
@@@ -342,7 -336,7 +342,7 @@@ static int prepare_log_message(const ch
  
        fp = fopen(git_path(commit_editmsg), "w");
        if (fp == NULL)
 -              die("could not open %s\n", git_path(commit_editmsg));
 +              die("could not open %s", git_path(commit_editmsg));
  
        stripspace(&sb, 0);
  
  
                strbuf_init(&sob, 0);
                strbuf_addstr(&sob, sign_off_header);
 -              strbuf_addstr(&sob, fmt_ident(getenv("GIT_COMMITTER_NAME"),
 -                                            getenv("GIT_COMMITTER_EMAIL"),
 -                                            "", 1));
 +              strbuf_addstr(&sob, fmt_name(getenv("GIT_COMMITTER_NAME"),
 +                                           getenv("GIT_COMMITTER_EMAIL")));
                strbuf_addch(&sob, '\n');
 -
                for (i = sb.len - 1; i > 0 && sb.buf[i - 1] != '\n'; i--)
                        ; /* do nothing */
                if (prefixcmp(sb.buf + i, sob.buf)) {
        }
  
        if (fwrite(sb.buf, 1, sb.len, fp) < sb.len)
 -              die("could not write commit template: %s\n",
 -                  strerror(errno));
 +              die("could not write commit template: %s", strerror(errno));
  
        strbuf_release(&sb);
  
 +      if (no_edit) {
 +              struct rev_info rev;
 +              unsigned char sha1[40];
 +
 +              fclose(fp);
 +
 +              if (!active_nr && read_cache() < 0)
 +                      die("Cannot read index");
 +
 +              if (get_sha1("HEAD", sha1) != 0)
 +                      return !!active_nr;
 +
 +              init_revisions(&rev, "");
 +              rev.abbrev = 0;
 +              setup_revisions(0, NULL, &rev, "HEAD");
 +              DIFF_OPT_SET(&rev.diffopt, QUIET);
 +              DIFF_OPT_SET(&rev.diffopt, EXIT_WITH_STATUS);
 +              run_diff_index(&rev, 1 /* cached */);
 +
 +              return !!DIFF_OPT_TST(&rev.diffopt, HAS_CHANGES);
 +      }
 +
        if (in_merge && !no_edit)
                fprintf(fp,
                        "#\n"
@@@ -473,13 -448,13 +473,13 @@@ static void determine_author_info(struc
  
                a = strstr(use_message_buffer, "\nauthor ");
                if (!a)
 -                      die("invalid commit: %s\n", use_message);
 +                      die("invalid commit: %s", use_message);
  
                lb = strstr(a + 8, " <");
                rb = strstr(a + 8, "> ");
                eol = strchr(a + 8, '\n');
                if (!lb || !rb || !eol)
 -                      die("invalid commit: %s\n", use_message);
 +                      die("invalid commit: %s", use_message);
  
                name = xstrndup(a + 8, lb - (a + 8));
                email = xstrndup(lb + 2, rb - (lb + 2));
                const char *rb = strchr(force_author, '>');
  
                if (!lb || !rb)
 -                      die("malformed --author parameter\n");
 +                      die("malformed --author parameter");
                name = xstrndup(force_author, lb - force_author);
                email = xstrndup(lb + 2, rb - (lb + 2));
        }
        strbuf_addf(sb, "author %s\n", fmt_ident(name, email, date, 1));
  }
  
 -static int parse_and_validate_options(int argc, const char *argv[])
 +static int parse_and_validate_options(int argc, const char *argv[],
 +                                    const char * const usage[])
  {
        int f = 0;
  
 -      argc = parse_options(argc, argv, builtin_commit_options,
 -                           builtin_commit_usage, 0);
 +      argc = parse_options(argc, argv, builtin_commit_options, usage, 0);
  
        if (logfile || message.len || use_message)
                no_edit = 1;
        if (amend && initial_commit)
                die("You have nothing to amend.");
        if (amend && in_merge)
 -              die("You are in the middle of a merger -- cannot amend.");
 +              die("You are in the middle of a merge -- cannot amend.");
  
        if (use_message)
                f++;
@@@ -601,9 -576,9 +601,9 @@@ int cmd_status(int argc, const char **a
  
        git_config(git_status_config);
  
 -      argc = parse_and_validate_options(argc, argv);
 +      argc = parse_and_validate_options(argc, argv, builtin_status_usage);
  
-       index_file = prepare_index(argv, prefix);
+       index_file = prepare_index(argc, argv, prefix);
  
        commitable = run_status(stdout, index_file, prefix);
  
@@@ -644,7 -619,7 +644,7 @@@ static void print_summary(const char *p
  
        commit = lookup_commit(sha1);
        if (!commit)
 -              die("couldn't look up newly created commit\n");
 +              die("couldn't look up newly created commit");
        if (!commit || parse_commit(commit))
                die("could not parse newly created commit");
  
@@@ -677,14 -652,6 +677,14 @@@ int git_commit_config(const char *k, co
        return git_status_config(k, v);
  }
  
 +static int is_a_merge(const unsigned char *sha1)
 +{
 +      struct commit *commit = lookup_commit(sha1);
 +      if (!commit || parse_commit(commit))
 +              die("could not parse HEAD commit");
 +      return !!(commit->parents && commit->parents->next);
 +}
 +
  static const char commit_utf8_warn[] =
  "Warning: commit message does not conform to UTF-8.\n"
  "You may want to amend it after fixing the message, or set the config\n"
@@@ -701,17 -668,16 +701,17 @@@ int cmd_commit(int argc, const char **a
  
        git_config(git_commit_config);
  
 -      argc = parse_and_validate_options(argc, argv);
 +      argc = parse_and_validate_options(argc, argv, builtin_commit_usage);
  
-       index_file = prepare_index(argv, prefix);
+       index_file = prepare_index(argc, argv, prefix);
  
        if (!no_verify && run_hook(index_file, "pre-commit", NULL)) {
                rollback_index_files();
                return 1;
        }
  
 -      if (!prepare_log_message(index_file, prefix) && !in_merge) {
 +      if (!prepare_log_message(index_file, prefix) && !in_merge &&
 +          !allow_empty && !(amend && is_a_merge(head_sha1))) {
                run_status(stdout, index_file, prefix);
                rollback_index_files();
                unlink(commit_editmsg);
  
        /* Get the commit message and validate it */
        header_len = sb.len;
 -      if (!no_edit)
 -              launch_editor(git_path(commit_editmsg), &sb);
 -      else if (strbuf_read_file(&sb, git_path(commit_editmsg), 0) < 0) {
 +      if (!no_edit) {
 +              char index[PATH_MAX];
 +              const char *env[2] = { index, NULL };
 +              snprintf(index, sizeof(index), "GIT_INDEX_FILE=%s", index_file);
 +              launch_editor(git_path(commit_editmsg), &sb, env);
 +      } else if (strbuf_read_file(&sb, git_path(commit_editmsg), 0) < 0) {
                rollback_index_files();
 -              die("could not read commit message\n");
 +              die("could not read commit message");
        }
        if (run_hook(index_file, "commit-msg", git_path(commit_editmsg))) {
                rollback_index_files();
        /* Truncate the message just before the diff, if any. */
        p = strstr(sb.buf, "\ndiff --git a/");
        if (p != NULL)
 -              strbuf_setlen(&sb, p - sb.buf);
 +              strbuf_setlen(&sb, p - sb.buf + 1);
  
        stripspace(&sb, 1);
        if (sb.len < header_len || message_is_empty(&sb, header_len)) {
                rollback_index_files();
 -              die("no commit message?  aborting commit.");
 +              die("no commit message?  aborting commit.");
        }
        strbuf_addch(&sb, '\0');
        if (is_encoding_utf8(git_commit_encoding) && !is_utf8(sb.buf))