Merge branch 'jc/add-addremove'

* jc/add-addremove:
  git-add --all: documentation
  git-add --all: tests
  git-add --all: add all files
  builtin-add.c: restructure the code for maintainability

Conflicts:
	builtin-add.c
This commit is contained in:
Junio C Hamano 2008-07-20 17:53:17 -07:00
commit 378335b37c
3 changed files with 104 additions and 34 deletions

View file

@ -9,7 +9,7 @@ SYNOPSIS
-------- --------
[verse] [verse]
'git add' [-n] [-v] [--force | -f] [--interactive | -i] [--patch | -p] 'git add' [-n] [-v] [--force | -f] [--interactive | -i] [--patch | -p]
[--update | -u] [--refresh] [--ignore-errors] [--] [--all | [--update | -u]] [--refresh] [--ignore-errors] [--]
<filepattern>... <filepattern>...
DESCRIPTION DESCRIPTION
@ -86,6 +86,12 @@ OPTIONS
command line. If no paths are specified, all tracked files in the command line. If no paths are specified, all tracked files in the
current directory and its subdirectories are updated. current directory and its subdirectories are updated.
-A::
--all::
Update files that git already knows about (same as '\--update')
and add all untracked files that are not ignored by '.gitignore'
mechanism.
--refresh:: --refresh::
Don't add the file(s), but only refresh their stat() Don't add the file(s), but only refresh their stat()
information in the index. information in the index.

View file

@ -140,8 +140,6 @@ static void refresh(int verbose, const char **pathspec)
for (specs = 0; pathspec[specs]; specs++) for (specs = 0; pathspec[specs]; specs++)
/* nothing */; /* nothing */;
seen = xcalloc(specs, 1); seen = xcalloc(specs, 1);
if (read_cache() < 0)
die("index file corrupt");
refresh_index(&the_index, verbose ? REFRESH_SAY_CHANGED : REFRESH_QUIET, refresh_index(&the_index, verbose ? REFRESH_SAY_CHANGED : REFRESH_QUIET,
pathspec, seen); pathspec, seen);
for (i = 0; i < specs; i++) { for (i = 0; i < specs; i++) {
@ -193,7 +191,7 @@ static const char ignore_error[] =
"The following paths are ignored by one of your .gitignore files:\n"; "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 verbose = 0, show_only = 0, ignored_too = 0, refresh_only = 0;
static int ignore_add_errors; static int ignore_add_errors, addremove;
static struct option builtin_add_options[] = { static struct option builtin_add_options[] = {
OPT__DRY_RUN(&show_only), OPT__DRY_RUN(&show_only),
@ -203,6 +201,7 @@ static struct option builtin_add_options[] = {
OPT_BOOLEAN('p', "patch", &patch_interactive, "interactive patching"), OPT_BOOLEAN('p', "patch", &patch_interactive, "interactive patching"),
OPT_BOOLEAN('f', "force", &ignored_too, "allow adding otherwise ignored files"), OPT_BOOLEAN('f', "force", &ignored_too, "allow adding otherwise ignored files"),
OPT_BOOLEAN('u', "update", &take_worktree_changes, "update tracked files"), OPT_BOOLEAN('u', "update", &take_worktree_changes, "update tracked files"),
OPT_BOOLEAN('A', "all", &addremove, "add all, noticing removal of tracked files"),
OPT_BOOLEAN( 0 , "refresh", &refresh_only, "don't add, only refresh the index"), 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_BOOLEAN( 0 , "ignore-errors", &ignore_add_errors, "just skip files which cannot be added because of errors"),
OPT_END(), OPT_END(),
@ -217,13 +216,36 @@ static int add_config(const char *var, const char *value, void *cb)
return git_default_config(var, value, cb); return git_default_config(var, value, cb);
} }
static int add_files(struct dir_struct *dir, int flags)
{
int i, exit_status = 0;
if (dir->ignored_nr) {
fprintf(stderr, ignore_error);
for (i = 0; i < dir->ignored_nr; i++)
fprintf(stderr, "%s\n", dir->ignored[i]->name);
fprintf(stderr, "Use -f if you really want to add them.\n");
die("no files added");
}
for (i = 0; i < dir->nr; i++)
if (add_file_to_cache(dir->entries[i]->name, flags)) {
if (!ignore_add_errors)
die("adding files failed");
exit_status = 1;
}
return exit_status;
}
int cmd_add(int argc, const char **argv, const char *prefix) int cmd_add(int argc, const char **argv, const char *prefix)
{ {
int exit_status = 0; int exit_status = 0;
int i, newfd; int newfd;
const char **pathspec; const char **pathspec;
struct dir_struct dir; struct dir_struct dir;
int flags; int flags;
int add_new_files;
int require_pathspec;
argc = parse_options(argc, argv, builtin_add_options, argc = parse_options(argc, argv, builtin_add_options,
builtin_add_usage, 0); builtin_add_usage, 0);
@ -234,53 +256,51 @@ int cmd_add(int argc, const char **argv, const char *prefix)
git_config(add_config, NULL); git_config(add_config, NULL);
if (addremove && take_worktree_changes)
die("-A and -u are mutually incompatible");
if (addremove && !argc) {
static const char *here[2] = { ".", NULL };
argc = 1;
argv = here;
}
add_new_files = !take_worktree_changes && !refresh_only;
require_pathspec = !take_worktree_changes;
newfd = hold_locked_index(&lock_file, 1); newfd = hold_locked_index(&lock_file, 1);
flags = ((verbose ? ADD_CACHE_VERBOSE : 0) | flags = ((verbose ? ADD_CACHE_VERBOSE : 0) |
(show_only ? ADD_CACHE_PRETEND : 0) | (show_only ? ADD_CACHE_PRETEND : 0) |
(ignore_add_errors ? ADD_CACHE_IGNORE_ERRORS : 0)); (ignore_add_errors ? ADD_CACHE_IGNORE_ERRORS : 0));
if (take_worktree_changes) { if (require_pathspec && argc == 0) {
const char **pathspec;
if (read_cache() < 0)
die("index file corrupt");
pathspec = get_pathspec(prefix, argv);
exit_status = add_files_to_cache(prefix, pathspec, flags);
goto finish;
}
if (argc == 0) {
fprintf(stderr, "Nothing specified, nothing added.\n"); fprintf(stderr, "Nothing specified, nothing added.\n");
fprintf(stderr, "Maybe you wanted to say 'git add .'?\n"); fprintf(stderr, "Maybe you wanted to say 'git add .'?\n");
return 0; return 0;
} }
pathspec = get_pathspec(prefix, argv); pathspec = get_pathspec(prefix, argv);
/*
* If we are adding new files, we need to scan the working
* tree to find the ones that match pathspecs; this needs
* to be done before we read the index.
*/
if (add_new_files)
fill_directory(&dir, pathspec, ignored_too);
if (read_cache() < 0)
die("index file corrupt");
if (refresh_only) { if (refresh_only) {
refresh(verbose, pathspec); refresh(verbose, pathspec);
goto finish; goto finish;
} }
fill_directory(&dir, pathspec, ignored_too); if (take_worktree_changes || addremove)
exit_status |= add_files_to_cache(prefix, pathspec, flags);
if (read_cache() < 0) if (add_new_files)
die("index file corrupt"); exit_status |= add_files(&dir, flags);
if (dir.ignored_nr) {
fprintf(stderr, ignore_error);
for (i = 0; i < dir.ignored_nr; i++) {
fprintf(stderr, "%s\n", dir.ignored[i]->name);
}
fprintf(stderr, "Use -f if you really want to add them.\n");
die("no files added");
}
for (i = 0; i < dir.nr; i++)
if (add_file_to_cache(dir.entries[i]->name, flags)) {
if (!ignore_add_errors)
die("adding files failed");
exit_status = 1;
}
finish: finish:
if (active_cache_changed) { if (active_cache_changed) {

44
t/t2202-add-addremove.sh Executable file
View file

@ -0,0 +1,44 @@
#!/bin/sh
test_description='git add --all'
. ./test-lib.sh
test_expect_success setup '
(
echo .gitignore
echo will-remove
) >expect &&
(
echo actual
echo expect
echo ignored
) >.gitignore &&
>will-remove &&
git add --all &&
test_tick &&
git commit -m initial &&
git ls-files >actual &&
test_cmp expect actual
'
test_expect_success 'git add --all' '
(
echo .gitignore
echo not-ignored
echo "M .gitignore"
echo "A not-ignored"
echo "D will-remove"
) >expect &&
>ignored &&
>not-ignored &&
echo modification >>.gitignore &&
rm -f will-remove &&
git add --all &&
git update-index --refresh &&
git ls-files >actual &&
git diff-index --name-status --cached HEAD >>actual &&
test_cmp expect actual
'
test_done