Skip to content

Commit c972ec0

Browse files
committed
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>
1 parent 09651dd commit c972ec0

File tree

1 file changed

+43
-32
lines changed

1 file changed

+43
-32
lines changed

builtin-add.c

Lines changed: 43 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -140,8 +140,6 @@ static void refresh(int verbose, const char **pathspec)
140140
for (specs = 0; pathspec[specs]; specs++)
141141
/* nothing */;
142142
seen = xcalloc(specs, 1);
143-
if (read_cache() < 0)
144-
die("index file corrupt");
145143
refresh_index(&the_index, verbose ? 0 : REFRESH_QUIET, pathspec, seen);
146144
for (i = 0; i < specs; i++) {
147145
if (!seen[i])
@@ -216,13 +214,36 @@ static int add_config(const char *var, const char *value, void *cb)
216214
return git_default_config(var, value, cb);
217215
}
218216

217+
static int add_files(struct dir_struct *dir, int flags)
218+
{
219+
int i, exit_status = 0;
220+
221+
if (dir->ignored_nr) {
222+
fprintf(stderr, ignore_error);
223+
for (i = 0; i < dir->ignored_nr; i++)
224+
fprintf(stderr, "%s\n", dir->ignored[i]->name);
225+
fprintf(stderr, "Use -f if you really want to add them.\n");
226+
die("no files added");
227+
}
228+
229+
for (i = 0; i < dir->nr; i++)
230+
if (add_file_to_cache(dir->entries[i]->name, flags)) {
231+
if (!ignore_add_errors)
232+
die("adding files failed");
233+
exit_status = 1;
234+
}
235+
return exit_status;
236+
}
237+
219238
int cmd_add(int argc, const char **argv, const char *prefix)
220239
{
221240
int exit_status = 0;
222-
int i, newfd;
241+
int newfd;
223242
const char **pathspec;
224243
struct dir_struct dir;
225244
int flags;
245+
int add_new_files;
246+
int require_pathspec;
226247

227248
argc = parse_options(argc, argv, builtin_add_options,
228249
builtin_add_usage, 0);
@@ -233,53 +254,43 @@ int cmd_add(int argc, const char **argv, const char *prefix)
233254

234255
git_config(add_config, NULL);
235256

257+
add_new_files = !take_worktree_changes && !refresh_only;
258+
require_pathspec = !take_worktree_changes;
259+
236260
newfd = hold_locked_index(&lock_file, 1);
237261

238262
flags = ((verbose ? ADD_CACHE_VERBOSE : 0) |
239263
(show_only ? ADD_CACHE_PRETEND : 0) |
240264
(ignore_add_errors ? ADD_CACHE_IGNORE_ERRORS : 0));
241265

242-
if (take_worktree_changes) {
243-
const char **pathspec;
244-
if (read_cache() < 0)
245-
die("index file corrupt");
246-
pathspec = get_pathspec(prefix, argv);
247-
exit_status = add_files_to_cache(prefix, pathspec, flags);
248-
goto finish;
249-
}
250-
251-
if (argc == 0) {
266+
if (require_pathspec && argc == 0) {
252267
fprintf(stderr, "Nothing specified, nothing added.\n");
253268
fprintf(stderr, "Maybe you wanted to say 'git add .'?\n");
254269
return 0;
255270
}
256271
pathspec = get_pathspec(prefix, argv);
257272

258-
if (refresh_only) {
259-
refresh(verbose, pathspec);
260-
goto finish;
261-
}
262-
263-
fill_directory(&dir, pathspec, ignored_too);
273+
/*
274+
* If we are adding new files, we need to scan the working
275+
* tree to find the ones that match pathspecs; this needs
276+
* to be done before we read the index.
277+
*/
278+
if (add_new_files)
279+
fill_directory(&dir, pathspec, ignored_too);
264280

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

268-
if (dir.ignored_nr) {
269-
fprintf(stderr, ignore_error);
270-
for (i = 0; i < dir.ignored_nr; i++) {
271-
fprintf(stderr, "%s\n", dir.ignored[i]->name);
272-
}
273-
fprintf(stderr, "Use -f if you really want to add them.\n");
274-
die("no files added");
284+
if (refresh_only) {
285+
refresh(verbose, pathspec);
286+
goto finish;
275287
}
276288

277-
for (i = 0; i < dir.nr; i++)
278-
if (add_file_to_cache(dir.entries[i]->name, flags)) {
279-
if (!ignore_add_errors)
280-
die("adding files failed");
281-
exit_status = 1;
282-
}
289+
if (take_worktree_changes)
290+
exit_status |= add_files_to_cache(prefix, pathspec, flags);
291+
292+
if (add_new_files)
293+
exit_status |= add_files(&dir, flags);
283294

284295
finish:
285296
if (active_cache_changed) {

0 commit comments

Comments
 (0)