Browse Source

builtin-add.c: restructure the code for maintainability

The implementation of "git add" has four major codepaths that are mutually
exclusive:

 - if "--interactive" or "--patch" is given, spawn "git add--interactive"
   and exit without doing anything else.  Otherwise things are handled
   internally in this C code;

 - if "--update" is given, update the modified files and exit without
   doing anything else;

 - if "--refresh" is given, do refresh and exit without doing anything
   else;

 - otherwise, find the paths that match pathspecs and stage their
   contents.

It led to an unholy mess in the code structure; each of the latter three
codepaths has a separate call to read_cache(), even though they are all
about "read the current index, update it and write it back", and logically
they should read the index once _anyway_.

This cleans up the latter three cases by introducing a pair of helper
variables:

 - "add_new_files" is set if we need to scan the working tree for paths
   that match the pathspec.  This variable is false for "--update" and
   "--refresh", because they only work on already tracked files.

 - "require_pathspec" is set if the user must give at least one pathspec.
   "--update" does not need it but all the other cases do.

This is in preparation for introducing a new option "--all", that does the
equivalent of "git add -u && git add ." (aka "addremove").

Signed-off-by: Junio C Hamano <gitster@pobox.com>
maint
Junio C Hamano 17 years ago
parent
commit
c972ec0420
  1. 75
      builtin-add.c

75
builtin-add.c

@ -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 ? 0 : REFRESH_QUIET, pathspec, seen); refresh_index(&the_index, verbose ? 0 : REFRESH_QUIET, pathspec, seen);
for (i = 0; i < specs; i++) { for (i = 0; i < specs; i++) {
if (!seen[i]) if (!seen[i])
@ -216,13 +214,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);
@ -233,53 +254,43 @@ int cmd_add(int argc, const char **argv, const char *prefix)


git_config(add_config, NULL); git_config(add_config, NULL);


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 (refresh_only) { /*
refresh(verbose, pathspec); * If we are adding new files, we need to scan the working
goto finish; * tree to find the ones that match pathspecs; this needs
} * to be done before we read the index.

*/
fill_directory(&dir, pathspec, ignored_too); if (add_new_files)
fill_directory(&dir, pathspec, ignored_too);


if (read_cache() < 0) if (read_cache() < 0)
die("index file corrupt"); die("index file corrupt");


if (dir.ignored_nr) { if (refresh_only) {
fprintf(stderr, ignore_error); refresh(verbose, pathspec);
for (i = 0; i < dir.ignored_nr; i++) { goto finish;
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 (take_worktree_changes)
if (add_file_to_cache(dir.entries[i]->name, flags)) { exit_status |= add_files_to_cache(prefix, pathspec, flags);
if (!ignore_add_errors)
die("adding files failed"); if (add_new_files)
exit_status = 1; exit_status |= add_files(&dir, flags);
}


finish: finish:
if (active_cache_changed) { if (active_cache_changed) {

Loading…
Cancel
Save