Browse Source

Merge branch 'ar/add-unreadable'

* 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
maint
Junio C Hamano 17 years ago
parent
commit
9d880582ee
  1. 7
      Documentation/git-add.txt
  2. 57
      builtin-add.c
  3. 2
      builtin-checkout.c
  4. 9
      builtin-commit.c
  5. 3
      builtin-mv.c
  6. 8
      cache.h
  7. 6
      read-cache.c
  8. 43
      t/t3700-add.sh

7
Documentation/git-add.txt

@ -9,7 +9,7 @@ SYNOPSIS @@ -9,7 +9,7 @@ SYNOPSIS
--------
[verse]
'git-add' [-n] [-v] [-f] [--interactive | -i] [--patch | -p] [-u] [--refresh]
[--] <filepattern>...
[--ignore-errors] [--] <filepattern>...

DESCRIPTION
-----------
@ -83,6 +83,11 @@ OPTIONS @@ -83,6 +83,11 @@ OPTIONS
Don't add the file(s), but only refresh their stat()
information in the index.

\--ignore-errors::
If some files could not be added because of errors indexing
them, do not abort the operation, but continue adding the
others. The command shall still exit with non-zero status.

\--::
This option can be used to separate command-line options from
the list of files, (useful when filenames might be mistaken

57
builtin-add.c

@ -79,12 +79,18 @@ static void fill_directory(struct dir_struct *dir, const char **pathspec, @@ -79,12 +79,18 @@ static void fill_directory(struct dir_struct *dir, const char **pathspec,
prune_directory(dir, pathspec, baselen);
}

struct update_callback_data
{
int flags;
int add_errors;
};

static void update_callback(struct diff_queue_struct *q,
struct diff_options *opt, void *cbdata)
{
int i, verbose;
int i;
struct update_callback_data *data = cbdata;

verbose = *((int *)cbdata);
for (i = 0; i < q->nr; i++) {
struct diff_filepair *p = q->queue[i];
const char *path = p->one->path;
@ -94,27 +100,35 @@ static void update_callback(struct diff_queue_struct *q, @@ -94,27 +100,35 @@ static void update_callback(struct diff_queue_struct *q,
case DIFF_STATUS_UNMERGED:
case DIFF_STATUS_MODIFIED:
case DIFF_STATUS_TYPE_CHANGED:
add_file_to_cache(path, verbose);
if (add_file_to_cache(path, data->flags & ADD_FILES_VERBOSE)) {
if (!(data->flags & ADD_FILES_IGNORE_ERRORS))
die("updating files failed");
data->add_errors++;
}
break;
case DIFF_STATUS_DELETED:
remove_file_from_cache(path);
if (verbose)
if (data->flags & ADD_FILES_VERBOSE)
printf("remove '%s'\n", path);
break;
}
}
}

void add_files_to_cache(int verbose, const char *prefix, const char **pathspec)
int add_files_to_cache(const char *prefix, const char **pathspec, int flags)
{
struct update_callback_data data;
struct rev_info rev;
init_revisions(&rev, prefix);
setup_revisions(0, NULL, &rev, NULL);
rev.prune_data = pathspec;
rev.diffopt.output_format = DIFF_FORMAT_CALLBACK;
rev.diffopt.format_callback = update_callback;
rev.diffopt.format_callback_data = &verbose;
data.flags = flags;
data.add_errors = 0;
rev.diffopt.format_callback_data = &data;
run_diff_files(&rev, DIFF_RACY_IS_MODIFIED);
return !!data.add_errors;
}

static void refresh(int verbose, const char **pathspec)
@ -177,6 +191,7 @@ static const char ignore_error[] = @@ -177,6 +191,7 @@ static const char ignore_error[] =
"The following paths are ignored by one of your .gitignore files:\n";

static int verbose = 0, show_only = 0, ignored_too = 0, refresh_only = 0;
static int ignore_add_errors;

static struct option builtin_add_options[] = {
OPT__DRY_RUN(&show_only),
@ -187,11 +202,22 @@ static struct option builtin_add_options[] = { @@ -187,11 +202,22 @@ static struct option builtin_add_options[] = {
OPT_BOOLEAN('f', NULL, &ignored_too, "allow adding otherwise ignored files"),
OPT_BOOLEAN('u', NULL, &take_worktree_changes, "update tracked files"),
OPT_BOOLEAN( 0 , "refresh", &refresh_only, "don't add, only refresh the index"),
OPT_BOOLEAN( 0 , "ignore-errors", &ignore_add_errors, "just skip files which cannot be added because of errors"),
OPT_END(),
};

static int add_config(const char *var, const char *value)
{
if (!strcasecmp(var, "add.ignore-errors")) {
ignore_add_errors = git_config_bool(var, value);
return 0;
}
return git_default_config(var, value);
}

int cmd_add(int argc, const char **argv, const char *prefix)
{
int exit_status = 0;
int i, newfd;
const char **pathspec;
struct dir_struct dir;
@ -203,16 +229,23 @@ int cmd_add(int argc, const char **argv, const char *prefix) @@ -203,16 +229,23 @@ int cmd_add(int argc, const char **argv, const char *prefix)
if (add_interactive)
exit(interactive_add(argc, argv, prefix));

git_config(git_default_config);
git_config(add_config);

newfd = hold_locked_index(&lock_file, 1);

if (take_worktree_changes) {
int flags = 0;
const char **pathspec;
if (read_cache() < 0)
die("index file corrupt");
pathspec = get_pathspec(prefix, argv);
add_files_to_cache(verbose, prefix, pathspec);

if (verbose)
flags |= ADD_FILES_VERBOSE;
if (ignore_add_errors)
flags |= ADD_FILES_IGNORE_ERRORS;

exit_status = add_files_to_cache(prefix, pathspec, flags);
goto finish;
}

@ -254,7 +287,11 @@ int cmd_add(int argc, const char **argv, const char *prefix) @@ -254,7 +287,11 @@ int cmd_add(int argc, const char **argv, const char *prefix)
}

for (i = 0; i < dir.nr; i++)
add_file_to_cache(dir.entries[i]->name, verbose);
if (add_file_to_cache(dir.entries[i]->name, verbose)) {
if (!ignore_add_errors)
die("adding files failed");
exit_status = 1;
}

finish:
if (active_cache_changed) {
@ -263,5 +300,5 @@ int cmd_add(int argc, const char **argv, const char *prefix) @@ -263,5 +300,5 @@ int cmd_add(int argc, const char **argv, const char *prefix)
die("Unable to write new index file");
}

return 0;
return exit_status;
}

2
builtin-checkout.c

@ -282,7 +282,7 @@ static int merge_working_tree(struct checkout_opts *opts, @@ -282,7 +282,7 @@ static int merge_working_tree(struct checkout_opts *opts,
* entries in the index.
*/

add_files_to_cache(0, NULL, NULL);
add_files_to_cache(NULL, NULL, 0);
work = write_tree_from_memory();

ret = reset_to_new(new->commit->tree, opts->quiet);

9
builtin-commit.c

@ -179,9 +179,10 @@ static void add_remove_files(struct path_list *list) @@ -179,9 +179,10 @@ static void add_remove_files(struct path_list *list)
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 +247,7 @@ static char *prepare_index(int argc, const char **argv, const char *prefix) @@ -246,7 +247,7 @@ static char *prepare_index(int argc, const char **argv, const char *prefix)
*/
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))

3
builtin-mv.c

@ -256,7 +256,8 @@ int cmd_mv(int argc, const char **argv, const char *prefix) @@ -256,7 +256,8 @@ int cmd_mv(int argc, const char **argv, const char *prefix)

for (i = 0; i < added.nr; i++) {
const char *path = added.items[i].path;
add_file_to_cache(path, verbose);
if (add_file_to_cache(path, verbose))
die("updating index entries failed");
}

for (i = 0; i < deleted.nr; i++)

8
cache.h

@ -782,7 +782,13 @@ extern int convert_to_git(const char *path, const char *src, size_t len, @@ -782,7 +782,13 @@ extern int convert_to_git(const char *path, const char *src, size_t len,
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;

6
read-cache.c

@ -470,7 +470,7 @@ int add_to_index(struct index_state *istate, const char *path, struct stat *st, @@ -470,7 +470,7 @@ int add_to_index(struct index_state *istate, const char *path, struct stat *st,
unsigned ce_option = CE_MATCH_IGNORE_VALID|CE_MATCH_RACY_IS_DIRTY;

if (!S_ISREG(st_mode) && !S_ISLNK(st_mode) && !S_ISDIR(st_mode))
die("%s: can only add regular files, symbolic links or git-directories", path);
return error("%s: can only add regular files, symbolic links or git-directories", path);

namelen = strlen(path);
if (S_ISDIR(st_mode)) {
@ -505,12 +505,12 @@ int add_to_index(struct index_state *istate, const char *path, struct stat *st, @@ -505,12 +505,12 @@ int add_to_index(struct index_state *istate, const char *path, struct stat *st,
return 0;
}
if (index_path(ce->sha1, path, st, 1))
die("unable to index file %s", path);
return error("unable to index file %s", path);
if (ignore_case && alias && different_name(ce, alias))
ce = create_alias_ce(ce, alias);
ce->ce_flags |= CE_ADDED;
if (add_index_entry(istate, ce, ADD_CACHE_OK_TO_ADD|ADD_CACHE_OK_TO_REPLACE))
die("unable to add %s to index",path);
return error("unable to add %s to index",path);
if (verbose)
printf("add '%s'\n", path);
return 0;

43
t/t3700-add.sh

@ -179,4 +179,47 @@ test_expect_success 'git add --refresh' ' @@ -179,4 +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

Loading…
Cancel
Save