Merge branch 'ar/add-unreadable'
authorJunio C Hamano <gitster@pobox.com>
Wed, 21 May 2008 21:16:46 +0000 (14:16 -0700)
committerJunio C Hamano <gitster@pobox.com>
Wed, 21 May 2008 21:16:46 +0000 (14:16 -0700)
* ar/add-unreadable:
Add a config option to ignore errors for git-add
Add a test for git-add --ignore-errors
Add --ignore-errors to git-add to allow it to skip files with read errors
Extend interface of add_files_to_cache to allow ignore indexing errors
Make the exit code of add_file_to_index actually useful

1  2 
builtin-commit.c
cache.h
t/t3700-add.sh
diff --combined builtin-commit.c
index 0baec6db6ac76de81b93f4c990f8347814618be7,6a2f5c3d96be44591e170222b42e48241182f8ed..d75224381b7ad88d6bbb67db3a85bbb881cea941
@@@ -47,7 -47,6 +47,7 @@@ static enum 
  
  static char *logfile, *force_author, *template_file;
  static char *edit_message, *use_message;
 +static char *author_name, *author_email, *author_date;
  static int all, edit_flag, also, interactive, only, amend, signoff;
  static int quiet, verbose, untracked_files, no_verify, allow_empty;
  /*
@@@ -179,9 -178,10 +179,10 @@@ static void add_remove_files(struct pat
                struct stat st;
                struct path_list_item *p = &(list->items[i]);
  
-               if (!lstat(p->path, &st))
-                       add_to_cache(p->path, &st, 0);
-               else
+               if (!lstat(p->path, &st)) {
+                       if (add_to_cache(p->path, &st, 0))
+                               die("updating files failed");
+               } else
                        remove_file_from_cache(p->path);
        }
  }
@@@ -246,7 -246,7 +247,7 @@@ static char *prepare_index(int argc, co
         */
        if (all || (also && pathspec && *pathspec)) {
                int fd = hold_locked_index(&index_lock, 1);
-               add_files_to_cache(0, also ? prefix : NULL, pathspec);
+               add_files_to_cache(also ? prefix : NULL, pathspec, 0);
                refresh_cache(REFRESH_QUIET);
                if (write_cache(fd, active_cache, active_nr) ||
                    close_lock_file(&index_lock))
@@@ -398,47 -398,6 +399,47 @@@ static int is_a_merge(const unsigned ch
  
  static const char sign_off_header[] = "Signed-off-by: ";
  
 +static void determine_author_info(void)
 +{
 +      char *name, *email, *date;
 +
 +      name = getenv("GIT_AUTHOR_NAME");
 +      email = getenv("GIT_AUTHOR_EMAIL");
 +      date = getenv("GIT_AUTHOR_DATE");
 +
 +      if (use_message) {
 +              const char *a, *lb, *rb, *eol;
 +
 +              a = strstr(use_message_buffer, "\nauthor ");
 +              if (!a)
 +                      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", use_message);
 +
 +              name = xstrndup(a + 8, lb - (a + 8));
 +              email = xstrndup(lb + 2, rb - (lb + 2));
 +              date = xstrndup(rb + 2, eol - (rb + 2));
 +      }
 +
 +      if (force_author) {
 +              const char *lb = strstr(force_author, " <");
 +              const char *rb = strchr(force_author, '>');
 +
 +              if (!lb || !rb)
 +                      die("malformed --author parameter");
 +              name = xstrndup(force_author, lb - force_author);
 +              email = xstrndup(lb + 2, rb - (lb + 2));
 +      }
 +
 +      author_name = name;
 +      author_email = email;
 +      author_date = date;
 +}
 +
  static int prepare_to_commit(const char *index_file, const char *prefix)
  {
        struct stat statbuf;
        FILE *fp;
        const char *hook_arg1 = NULL;
        const char *hook_arg2 = NULL;
 +      int ident_shown = 0;
  
        if (!no_verify && run_hook(index_file, "pre-commit", NULL))
                return 0;
  
        strbuf_release(&sb);
  
 +      determine_author_info();
 +
 +      /* This checks if committer ident is explicitly given */
 +      git_committer_info(0);
        if (use_editor) {
 +              char *author_ident;
 +              const char *committer_ident;
 +
                if (in_merge)
                        fprintf(fp,
                                "#\n"
                if (only_include_assumed)
                        fprintf(fp, "# %s\n", only_include_assumed);
  
 +              author_ident = xstrdup(fmt_name(author_name, author_email));
 +              committer_ident = fmt_name(getenv("GIT_COMMITTER_NAME"),
 +                                         getenv("GIT_COMMITTER_EMAIL"));
 +              if (strcmp(author_ident, committer_ident))
 +                      fprintf(fp,
 +                              "%s"
 +                              "# Author:    %s\n",
 +                              ident_shown++ ? "" : "#\n",
 +                              author_ident);
 +              free(author_ident);
 +
 +              if (!user_ident_explicitly_given)
 +                      fprintf(fp,
 +                              "%s"
 +                              "# Committer: %s\n",
 +                              ident_shown++ ? "" : "#\n",
 +                              committer_ident);
 +
 +              if (ident_shown)
 +                      fprintf(fp, "#\n");
 +
                saved_color_setting = wt_status_use_color;
                wt_status_use_color = 0;
                commitable = run_status(fp, index_file, prefix, 1);
@@@ -695,6 -625,45 +696,6 @@@ static int message_is_empty(struct strb
        return 1;
  }
  
 -static void determine_author_info(struct strbuf *sb)
 -{
 -      char *name, *email, *date;
 -
 -      name = getenv("GIT_AUTHOR_NAME");
 -      email = getenv("GIT_AUTHOR_EMAIL");
 -      date = getenv("GIT_AUTHOR_DATE");
 -
 -      if (use_message) {
 -              const char *a, *lb, *rb, *eol;
 -
 -              a = strstr(use_message_buffer, "\nauthor ");
 -              if (!a)
 -                      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", use_message);
 -
 -              name = xstrndup(a + 8, lb - (a + 8));
 -              email = xstrndup(lb + 2, rb - (lb + 2));
 -              date = xstrndup(rb + 2, eol - (rb + 2));
 -      }
 -
 -      if (force_author) {
 -              const char *lb = strstr(force_author, " <");
 -              const char *rb = strchr(force_author, '>');
 -
 -              if (!lb || !rb)
 -                      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, IDENT_ERROR_ON_NO_NAME));
 -}
 -
  static int parse_and_validate_options(int argc, const char *argv[],
                                      const char * const usage[])
  {
@@@ -954,8 -923,7 +955,8 @@@ int cmd_commit(int argc, const char **a
                strbuf_addf(&sb, "parent %s\n", sha1_to_hex(head_sha1));
        }
  
 -      determine_author_info(&sb);
 +      strbuf_addf(&sb, "author %s\n",
 +                  fmt_ident(author_name, author_email, author_date, IDENT_ERROR_ON_NO_NAME));
        strbuf_addf(&sb, "committer %s\n", git_committer_info(IDENT_ERROR_ON_NO_NAME));
        if (!is_encoding_utf8(git_commit_encoding))
                strbuf_addf(&sb, "encoding %s\n", git_commit_encoding);
diff --combined cache.h
index 093f04cec0459e67c54f3fc5b536f59fb0f343dc,4fb629000e9d11b22c54ade075acf59d272df291..0f89f1569a6b70766c2f2e04fcc6a5992df5db01
+++ b/cache.h
@@@ -735,7 -735,6 +735,7 @@@ extern int config_error_nonbool(const c
  #define MAX_GITNAME (1000)
  extern char git_default_email[MAX_GITNAME];
  extern char git_default_name[MAX_GITNAME];
 +extern int user_ident_explicitly_given;
  
  extern const char *git_commit_encoding;
  extern const char *git_log_output_encoding;
@@@ -782,7 -781,13 +782,13 @@@ extern int convert_to_git(const char *p
  extern int convert_to_working_tree(const char *path, const char *src, size_t len, struct strbuf *dst);
  
  /* add */
- void add_files_to_cache(int verbose, const char *prefix, const char **pathspec);
+ #define ADD_FILES_VERBOSE     01
+ #define ADD_FILES_IGNORE_ERRORS       02
+ /*
+  * return 0 if success, 1 - if addition of a file failed and
+  * ADD_FILES_IGNORE_ERRORS was specified in flags
+  */
+ int add_files_to_cache(const char *prefix, const char **pathspec, int flags);
  
  /* diff.c */
  extern int diff_auto_refresh_index;
diff --combined t/t3700-add.sh
index 68c5ddebdf565912af5f481283980169f069a7a6,5b46ba356089436cd075e99b1f979afcb1fa4172..e83fa1f6894dd13eb11cae6afb8ecbd3dcb999db
@@@ -81,17 -81,17 +81,17 @@@ test_expect_success '.gitignore test se
  
  test_expect_success '.gitignore is honored' '
        git add . &&
 -      ! git ls-files | grep "\\.ig"
 +      ! (git ls-files | grep "\\.ig")
  '
  
  test_expect_success 'error out when attempting to add ignored ones without -f' '
        ! git add a.?? &&
 -      ! git ls-files | grep "\\.ig"
 +      ! (git ls-files | grep "\\.ig")
  '
  
  test_expect_success 'error out when attempting to add ignored ones without -f' '
        ! git add d.?? &&
 -      ! git ls-files | grep "\\.ig"
 +      ! (git ls-files | grep "\\.ig")
  '
  
  test_expect_success 'add ignored ones with -f' '
@@@ -179,4 -179,47 +179,47 @@@ test_expect_success 'git add --refresh
        test -z "`git diff-index HEAD -- foo`"
  '
  
+ test_expect_success 'git add should fail atomically upon an unreadable file' '
+       git reset --hard &&
+       date >foo1 &&
+       date >foo2 &&
+       chmod 0 foo2 &&
+       test_must_fail git add --verbose . &&
+       ! ( git ls-files foo1 | grep foo1 )
+ '
+ rm -f foo2
+ test_expect_success 'git add --ignore-errors' '
+       git reset --hard &&
+       date >foo1 &&
+       date >foo2 &&
+       chmod 0 foo2 &&
+       test_must_fail git add --verbose --ignore-errors . &&
+       git ls-files foo1 | grep foo1
+ '
+ rm -f foo2
+ test_expect_success 'git add (add.ignore-errors)' '
+       git config add.ignore-errors 1 &&
+       git reset --hard &&
+       date >foo1 &&
+       date >foo2 &&
+       chmod 0 foo2 &&
+       test_must_fail git add --verbose . &&
+       git ls-files foo1 | grep foo1
+ '
+ rm -f foo2
+ test_expect_success 'git add (add.ignore-errors = false)' '
+       git config add.ignore-errors 0 &&
+       git reset --hard &&
+       date >foo1 &&
+       date >foo2 &&
+       chmod 0 foo2 &&
+       test_must_fail git add --verbose . &&
+       ! ( git ls-files foo1 | grep foo1 )
+ '
  test_done