2006-05-18 00:33:32 +08:00
|
|
|
/*
|
|
|
|
* "git add" builtin command
|
|
|
|
*
|
|
|
|
* Copyright (C) 2006 Linus Torvalds
|
|
|
|
*/
|
2022-11-19 21:07:38 +08:00
|
|
|
#define USE_THE_INDEX_VARIABLE
|
2023-05-16 14:33:57 +08:00
|
|
|
#include "builtin.h"
|
2023-04-11 11:00:39 +08:00
|
|
|
#include "advice.h"
|
2017-06-15 02:07:36 +08:00
|
|
|
#include "config.h"
|
2014-10-01 18:28:42 +08:00
|
|
|
#include "lockfile.h"
|
2023-04-11 15:41:57 +08:00
|
|
|
#include "editor.h"
|
2006-05-18 00:33:32 +08:00
|
|
|
#include "dir.h"
|
2023-03-21 14:25:54 +08:00
|
|
|
#include "gettext.h"
|
2013-01-07 00:58:08 +08:00
|
|
|
#include "pathspec.h"
|
2018-04-11 05:26:18 +08:00
|
|
|
#include "exec-cmd.h"
|
2006-05-20 16:28:49 +08:00
|
|
|
#include "cache-tree.h"
|
2007-09-18 08:06:44 +08:00
|
|
|
#include "run-command.h"
|
2007-10-04 05:45:02 +08:00
|
|
|
#include "parse-options.h"
|
2023-05-16 14:33:52 +08:00
|
|
|
#include "preload-index.h"
|
git-add: introduce --edit (to edit the diff vs. the index)
With "git add -e [<files>]", Git will fire up an editor with the current
diff relative to the index (i.e. what you would get with "git diff
[<files>]").
Now you can edit the patch as much as you like, including adding/removing
lines, editing the text, whatever. Make sure, though, that the first
character of the hunk lines is still a space, a plus or a minus.
After you closed the editor, Git will adjust the line counts of the hunks
if necessary, thanks to the --recount option of apply, and commit the
patch. Except if you deleted everything, in which case nothing happens
(for obvious reasons).
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2009-04-09 05:30:24 +08:00
|
|
|
#include "diff.h"
|
Remove diff machinery dependency from read-cache
Exal Sibeaz pointed out that some git files are way too big, and that
add_files_to_cache() brings in all the diff machinery to any git binary
that needs the basic git SHA1 object operations from read-cache.c. Which
is pretty much all of them.
It's doubly silly, since add_files_to_cache() is only used by builtin
programs (add, checkout and commit), so it's fairly easily fixed by just
moving the thing to builtin-add.c, and avoiding the dependency entirely.
I initially argued to Exal that it would probably be best to try to depend
on smart compilers and linkers, but after spending some time trying to
make -ffunction-sections work and giving up, I think Exal was right, and
the fix is to just do some trivial cleanups like this.
This trivial cleanup results in pretty stunning file size differences.
The diff machinery really is mostly used by just the builtin programs, and
you have things like these trivial before-and-after numbers:
-rwxr-xr-x 1 torvalds torvalds 1727420 2010-01-21 10:53 git-hash-object
-rwxrwxr-x 1 torvalds torvalds 940265 2010-01-21 11:16 git-hash-object
Now, I'm not saying that 940kB is good either, but that's mostly all the
debug information - you can see the real code with 'size':
text data bss dec hex filename
418675 3920 127408 550003 86473 git-hash-object (before)
230650 2288 111728 344666 5425a git-hash-object (after)
ie we have a nice 24% size reduction from this trivial cleanup.
It's not just that one file either. I get:
[torvalds@nehalem git]$ du -s /home/torvalds/libexec/git-core
45640 /home/torvalds/libexec/git-core (before)
33508 /home/torvalds/libexec/git-core (after)
so we're talking 12MB of diskspace here.
(Of course, stripping all the binaries brings the 33MB down to 9MB, so the
whole debug information thing is still the bulk of it all, but that's a
separate issue entirely)
Now, I'm sure there are other things we should do, and changing our
compiler flags from -O2 to -Os would bring the text size down by an
additional almost 20%, but this thing Exal pointed out seems to be some
good low-hanging fruit.
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2010-01-22 03:37:38 +08:00
|
|
|
#include "diffcore.h"
|
2023-05-16 14:33:56 +08:00
|
|
|
#include "read-cache.h"
|
git-add: introduce --edit (to edit the diff vs. the index)
With "git add -e [<files>]", Git will fire up an editor with the current
diff relative to the index (i.e. what you would get with "git diff
[<files>]").
Now you can edit the patch as much as you like, including adding/removing
lines, editing the text, whatever. Make sure, though, that the first
character of the hunk lines is still a space, a plus or a minus.
After you closed the editor, Git will adjust the line counts of the hunks
if necessary, thanks to the --recount option of apply, and commit the
patch. Except if you deleted everything, in which case nothing happens
(for obvious reasons).
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2009-04-09 05:30:24 +08:00
|
|
|
#include "revision.h"
|
2011-10-29 05:48:40 +08:00
|
|
|
#include "bulk-checkin.h"
|
2020-07-29 04:23:39 +08:00
|
|
|
#include "strvec.h"
|
2017-05-10 03:17:59 +08:00
|
|
|
#include "submodule.h"
|
2019-11-13 20:40:57 +08:00
|
|
|
#include "add-interactive.h"
|
2006-05-18 00:33:32 +08:00
|
|
|
|
2007-10-04 05:45:02 +08:00
|
|
|
static const char * const builtin_add_usage[] = {
|
2015-01-13 15:44:47 +08:00
|
|
|
N_("git add [<options>] [--] <pathspec>..."),
|
2007-10-04 05:45:02 +08:00
|
|
|
NULL
|
|
|
|
};
|
git-add: introduce --edit (to edit the diff vs. the index)
With "git add -e [<files>]", Git will fire up an editor with the current
diff relative to the index (i.e. what you would get with "git diff
[<files>]").
Now you can edit the patch as much as you like, including adding/removing
lines, editing the text, whatever. Make sure, though, that the first
character of the hunk lines is still a space, a plus or a minus.
After you closed the editor, Git will adjust the line counts of the hunks
if necessary, thanks to the --recount option of apply, and commit the
patch. Except if you deleted everything, in which case nothing happens
(for obvious reasons).
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2009-04-09 05:30:24 +08:00
|
|
|
static int patch_interactive, add_interactive, edit_interactive;
|
2007-05-12 14:42:00 +08:00
|
|
|
static int take_worktree_changes;
|
2017-11-17 00:38:28 +08:00
|
|
|
static int add_renormalize;
|
2019-12-03 22:02:13 +08:00
|
|
|
static int pathspec_file_nul;
|
2021-09-24 23:39:08 +08:00
|
|
|
static int include_sparse;
|
2019-12-03 22:02:13 +08:00
|
|
|
static const char *pathspec_from_file;
|
2007-02-28 11:31:10 +08:00
|
|
|
|
2021-02-23 09:10:35 +08:00
|
|
|
static int chmod_pathspec(struct pathspec *pathspec, char flip, int show_only)
|
2016-09-15 05:07:47 +08:00
|
|
|
{
|
2021-02-23 09:10:35 +08:00
|
|
|
int i, ret = 0;
|
2016-09-15 05:07:47 +08:00
|
|
|
|
2022-11-19 21:07:34 +08:00
|
|
|
for (i = 0; i < the_index.cache_nr; i++) {
|
|
|
|
struct cache_entry *ce = the_index.cache[i];
|
2021-02-23 09:10:33 +08:00
|
|
|
int err;
|
2016-09-15 05:07:47 +08:00
|
|
|
|
2021-09-24 23:39:09 +08:00
|
|
|
if (!include_sparse &&
|
|
|
|
(ce_skip_worktree(ce) ||
|
|
|
|
!path_in_sparse_checkout(ce->name, &the_index)))
|
2021-04-09 04:41:24 +08:00
|
|
|
continue;
|
|
|
|
|
2018-08-14 00:14:22 +08:00
|
|
|
if (pathspec && !ce_path_match(&the_index, ce, pathspec, NULL))
|
2016-09-15 05:07:47 +08:00
|
|
|
continue;
|
|
|
|
|
2021-02-23 09:10:33 +08:00
|
|
|
if (!show_only)
|
2022-11-19 21:07:30 +08:00
|
|
|
err = chmod_index_entry(&the_index, ce, flip);
|
2021-02-23 09:10:33 +08:00
|
|
|
else
|
|
|
|
err = S_ISREG(ce->ce_mode) ? 0 : -1;
|
|
|
|
|
|
|
|
if (err < 0)
|
2021-02-23 09:10:35 +08:00
|
|
|
ret = error(_("cannot chmod %cx '%s'"), flip, ce->name);
|
2016-09-15 05:07:47 +08:00
|
|
|
}
|
2021-02-23 09:10:35 +08:00
|
|
|
|
|
|
|
return ret;
|
2016-09-15 05:07:47 +08:00
|
|
|
}
|
|
|
|
|
2017-11-17 00:38:28 +08:00
|
|
|
static int renormalize_tracked_files(const struct pathspec *pathspec, int flags)
|
|
|
|
{
|
|
|
|
int i, retval = 0;
|
|
|
|
|
2022-11-19 21:07:34 +08:00
|
|
|
for (i = 0; i < the_index.cache_nr; i++) {
|
|
|
|
struct cache_entry *ce = the_index.cache[i];
|
2017-11-17 00:38:28 +08:00
|
|
|
|
2021-09-24 23:39:10 +08:00
|
|
|
if (!include_sparse &&
|
|
|
|
(ce_skip_worktree(ce) ||
|
|
|
|
!path_in_sparse_checkout(ce->name, &the_index)))
|
2021-04-09 04:41:24 +08:00
|
|
|
continue;
|
2017-11-17 00:38:28 +08:00
|
|
|
if (ce_stage(ce))
|
|
|
|
continue; /* do not touch unmerged paths */
|
|
|
|
if (!S_ISREG(ce->ce_mode) && !S_ISLNK(ce->ce_mode))
|
|
|
|
continue; /* do not touch non blobs */
|
2018-08-14 00:14:22 +08:00
|
|
|
if (pathspec && !ce_path_match(&the_index, ce, pathspec, NULL))
|
2017-11-17 00:38:28 +08:00
|
|
|
continue;
|
2022-11-19 21:07:30 +08:00
|
|
|
retval |= add_file_to_index(&the_index, ce->name,
|
|
|
|
flags | ADD_CACHE_RENORMALIZE);
|
2017-11-17 00:38:28 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
return retval;
|
|
|
|
}
|
|
|
|
|
2014-03-08 07:14:01 +08:00
|
|
|
static char *prune_directory(struct dir_struct *dir, struct pathspec *pathspec, int prefix)
|
2006-05-18 00:33:32 +08:00
|
|
|
{
|
2006-05-18 04:23:19 +08:00
|
|
|
char *seen;
|
2013-07-14 16:36:00 +08:00
|
|
|
int i;
|
2006-05-18 00:33:32 +08:00
|
|
|
struct dir_entry **src, **dst;
|
|
|
|
|
2013-07-14 16:36:00 +08:00
|
|
|
seen = xcalloc(pathspec->nr, 1);
|
2006-05-18 04:23:19 +08:00
|
|
|
|
2006-05-18 00:33:32 +08:00
|
|
|
src = dst = dir->entries;
|
|
|
|
i = dir->nr;
|
|
|
|
while (--i >= 0) {
|
|
|
|
struct dir_entry *entry = *src++;
|
2018-08-14 00:14:22 +08:00
|
|
|
if (dir_path_match(&the_index, entry, pathspec, prefix, seen))
|
2006-12-30 03:01:31 +08:00
|
|
|
*dst++ = entry;
|
2006-05-18 00:33:32 +08:00
|
|
|
}
|
|
|
|
dir->nr = dst - dir->entries;
|
2021-04-09 04:41:25 +08:00
|
|
|
add_pathspec_matches_against_index(pathspec, &the_index, seen,
|
2021-04-09 04:41:27 +08:00
|
|
|
PS_IGNORE_SKIP_WORKTREE);
|
2010-02-10 06:30:49 +08:00
|
|
|
return seen;
|
2006-05-18 00:33:32 +08:00
|
|
|
}
|
|
|
|
|
2021-04-09 04:41:27 +08:00
|
|
|
static int refresh(int verbose, const struct pathspec *pathspec)
|
2007-08-12 05:59:01 +08:00
|
|
|
{
|
|
|
|
char *seen;
|
2021-04-09 04:41:27 +08:00
|
|
|
int i, ret = 0;
|
|
|
|
char *skip_worktree_seen = NULL;
|
|
|
|
struct string_list only_match_skip_worktree = STRING_LIST_INIT_NODUP;
|
|
|
|
int flags = REFRESH_IGNORE_SKIP_WORKTREE |
|
|
|
|
(verbose ? REFRESH_IN_PORCELAIN : REFRESH_QUIET);
|
2007-08-12 05:59:01 +08:00
|
|
|
|
2013-07-14 16:35:54 +08:00
|
|
|
seen = xcalloc(pathspec->nr, 1);
|
2021-04-09 04:41:27 +08:00
|
|
|
refresh_index(&the_index, flags, pathspec, seen,
|
|
|
|
_("Unstaged changes after refreshing the index:"));
|
2013-07-14 16:35:54 +08:00
|
|
|
for (i = 0; i < pathspec->nr; i++) {
|
2021-04-09 04:41:27 +08:00
|
|
|
if (!seen[i]) {
|
2021-07-29 22:52:06 +08:00
|
|
|
const char *path = pathspec->items[i].original;
|
|
|
|
|
|
|
|
if (matches_skip_worktree(pathspec, i, &skip_worktree_seen) ||
|
2021-09-08 09:42:30 +08:00
|
|
|
!path_in_sparse_checkout(path, &the_index)) {
|
2021-04-09 04:41:27 +08:00
|
|
|
string_list_append(&only_match_skip_worktree,
|
|
|
|
pathspec->items[i].original);
|
|
|
|
} else {
|
|
|
|
die(_("pathspec '%s' did not match any files"),
|
|
|
|
pathspec->items[i].original);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (only_match_skip_worktree.nr) {
|
|
|
|
advise_on_updating_sparse_paths(&only_match_skip_worktree);
|
|
|
|
ret = 1;
|
2007-08-12 05:59:01 +08:00
|
|
|
}
|
2021-04-09 04:41:27 +08:00
|
|
|
|
2018-12-06 23:42:06 +08:00
|
|
|
free(seen);
|
2021-04-09 04:41:27 +08:00
|
|
|
free(skip_worktree_seen);
|
|
|
|
string_list_clear(&only_match_skip_worktree, 0);
|
|
|
|
return ret;
|
2007-08-12 05:59:01 +08:00
|
|
|
}
|
|
|
|
|
2020-09-30 20:28:18 +08:00
|
|
|
int interactive_add(const char **argv, const char *prefix, int patch)
|
2009-08-13 20:29:41 +08:00
|
|
|
{
|
2013-07-14 16:35:46 +08:00
|
|
|
struct pathspec pathspec;
|
2023-02-07 06:58:56 +08:00
|
|
|
int unused;
|
|
|
|
|
|
|
|
if (!git_config_get_bool("add.interactive.usebuiltin", &unused))
|
|
|
|
warning(_("the add.interactive.useBuiltin setting has been removed!\n"
|
|
|
|
"See its entry in 'git help config' for details."));
|
2009-08-13 20:29:41 +08:00
|
|
|
|
2013-09-05 11:40:39 +08:00
|
|
|
parse_pathspec(&pathspec, 0,
|
2013-07-14 16:35:46 +08:00
|
|
|
PATHSPEC_PREFER_FULL |
|
2013-07-14 16:35:50 +08:00
|
|
|
PATHSPEC_SYMLINK_LEADING_PATH |
|
|
|
|
PATHSPEC_PREFIX_ORIGIN,
|
2013-07-14 16:35:46 +08:00
|
|
|
prefix, argv);
|
2009-08-13 20:29:41 +08:00
|
|
|
|
2023-02-07 06:58:57 +08:00
|
|
|
if (patch)
|
|
|
|
return !!run_add_p(the_repository, ADD_P_ADD, NULL, &pathspec);
|
|
|
|
else
|
|
|
|
return !!run_add_i(the_repository, &pathspec);
|
2009-08-13 20:29:41 +08:00
|
|
|
}
|
|
|
|
|
2009-06-19 01:28:43 +08:00
|
|
|
static int edit_patch(int argc, const char **argv, const char *prefix)
|
git-add: introduce --edit (to edit the diff vs. the index)
With "git add -e [<files>]", Git will fire up an editor with the current
diff relative to the index (i.e. what you would get with "git diff
[<files>]").
Now you can edit the patch as much as you like, including adding/removing
lines, editing the text, whatever. Make sure, though, that the first
character of the hunk lines is still a space, a plus or a minus.
After you closed the editor, Git will adjust the line counts of the hunks
if necessary, thanks to the --recount option of apply, and commit the
patch. Except if you deleted everything, in which case nothing happens
(for obvious reasons).
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2009-04-09 05:30:24 +08:00
|
|
|
{
|
2012-09-05 01:30:21 +08:00
|
|
|
char *file = git_pathdup("ADD_EDIT.patch");
|
2014-08-20 03:09:35 +08:00
|
|
|
struct child_process child = CHILD_PROCESS_INIT;
|
git-add: introduce --edit (to edit the diff vs. the index)
With "git add -e [<files>]", Git will fire up an editor with the current
diff relative to the index (i.e. what you would get with "git diff
[<files>]").
Now you can edit the patch as much as you like, including adding/removing
lines, editing the text, whatever. Make sure, though, that the first
character of the hunk lines is still a space, a plus or a minus.
After you closed the editor, Git will adjust the line counts of the hunks
if necessary, thanks to the --recount option of apply, and commit the
patch. Except if you deleted everything, in which case nothing happens
(for obvious reasons).
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2009-04-09 05:30:24 +08:00
|
|
|
struct rev_info rev;
|
|
|
|
int out;
|
|
|
|
struct stat st;
|
|
|
|
|
|
|
|
git_config(git_diff_basic_config, NULL); /* no "diff" UI options */
|
|
|
|
|
2022-11-19 21:07:38 +08:00
|
|
|
if (repo_read_index(the_repository) < 0)
|
2013-08-31 05:56:49 +08:00
|
|
|
die(_("Could not read the index"));
|
git-add: introduce --edit (to edit the diff vs. the index)
With "git add -e [<files>]", Git will fire up an editor with the current
diff relative to the index (i.e. what you would get with "git diff
[<files>]").
Now you can edit the patch as much as you like, including adding/removing
lines, editing the text, whatever. Make sure, though, that the first
character of the hunk lines is still a space, a plus or a minus.
After you closed the editor, Git will adjust the line counts of the hunks
if necessary, thanks to the --recount option of apply, and commit the
patch. Except if you deleted everything, in which case nothing happens
(for obvious reasons).
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2009-04-09 05:30:24 +08:00
|
|
|
|
2018-09-21 23:57:38 +08:00
|
|
|
repo_init_revisions(the_repository, &rev, prefix);
|
git-add: introduce --edit (to edit the diff vs. the index)
With "git add -e [<files>]", Git will fire up an editor with the current
diff relative to the index (i.e. what you would get with "git diff
[<files>]").
Now you can edit the patch as much as you like, including adding/removing
lines, editing the text, whatever. Make sure, though, that the first
character of the hunk lines is still a space, a plus or a minus.
After you closed the editor, Git will adjust the line counts of the hunks
if necessary, thanks to the --recount option of apply, and commit the
patch. Except if you deleted everything, in which case nothing happens
(for obvious reasons).
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2009-04-09 05:30:24 +08:00
|
|
|
rev.diffopt.context = 7;
|
|
|
|
|
|
|
|
argc = setup_revisions(argc, argv, &rev, NULL);
|
|
|
|
rev.diffopt.output_format = DIFF_FORMAT_PATCH;
|
2013-07-19 06:58:04 +08:00
|
|
|
rev.diffopt.use_color = 0;
|
2017-11-01 02:19:11 +08:00
|
|
|
rev.diffopt.flags.ignore_dirty_submodules = 1;
|
2021-08-26 04:16:46 +08:00
|
|
|
out = xopen(file, O_CREAT | O_WRONLY | O_TRUNC, 0666);
|
2009-09-12 16:43:27 +08:00
|
|
|
rev.diffopt.file = xfdopen(out, "w");
|
git-add: introduce --edit (to edit the diff vs. the index)
With "git add -e [<files>]", Git will fire up an editor with the current
diff relative to the index (i.e. what you would get with "git diff
[<files>]").
Now you can edit the patch as much as you like, including adding/removing
lines, editing the text, whatever. Make sure, though, that the first
character of the hunk lines is still a space, a plus or a minus.
After you closed the editor, Git will adjust the line counts of the hunks
if necessary, thanks to the --recount option of apply, and commit the
patch. Except if you deleted everything, in which case nothing happens
(for obvious reasons).
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2009-04-09 05:30:24 +08:00
|
|
|
rev.diffopt.close_file = 1;
|
|
|
|
if (run_diff_files(&rev, 0))
|
2013-08-31 05:56:49 +08:00
|
|
|
die(_("Could not write patch"));
|
git-add: introduce --edit (to edit the diff vs. the index)
With "git add -e [<files>]", Git will fire up an editor with the current
diff relative to the index (i.e. what you would get with "git diff
[<files>]").
Now you can edit the patch as much as you like, including adding/removing
lines, editing the text, whatever. Make sure, though, that the first
character of the hunk lines is still a space, a plus or a minus.
After you closed the editor, Git will adjust the line counts of the hunks
if necessary, thanks to the --recount option of apply, and commit the
patch. Except if you deleted everything, in which case nothing happens
(for obvious reasons).
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2009-04-09 05:30:24 +08:00
|
|
|
|
2015-05-13 09:21:58 +08:00
|
|
|
if (launch_editor(file, NULL, NULL))
|
|
|
|
die(_("editing patch failed"));
|
git-add: introduce --edit (to edit the diff vs. the index)
With "git add -e [<files>]", Git will fire up an editor with the current
diff relative to the index (i.e. what you would get with "git diff
[<files>]").
Now you can edit the patch as much as you like, including adding/removing
lines, editing the text, whatever. Make sure, though, that the first
character of the hunk lines is still a space, a plus or a minus.
After you closed the editor, Git will adjust the line counts of the hunks
if necessary, thanks to the --recount option of apply, and commit the
patch. Except if you deleted everything, in which case nothing happens
(for obvious reasons).
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2009-04-09 05:30:24 +08:00
|
|
|
|
|
|
|
if (stat(file, &st))
|
2011-02-23 07:41:29 +08:00
|
|
|
die_errno(_("Could not stat '%s'"), file);
|
git-add: introduce --edit (to edit the diff vs. the index)
With "git add -e [<files>]", Git will fire up an editor with the current
diff relative to the index (i.e. what you would get with "git diff
[<files>]").
Now you can edit the patch as much as you like, including adding/removing
lines, editing the text, whatever. Make sure, though, that the first
character of the hunk lines is still a space, a plus or a minus.
After you closed the editor, Git will adjust the line counts of the hunks
if necessary, thanks to the --recount option of apply, and commit the
patch. Except if you deleted everything, in which case nothing happens
(for obvious reasons).
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2009-04-09 05:30:24 +08:00
|
|
|
if (!st.st_size)
|
2011-02-23 07:41:29 +08:00
|
|
|
die(_("Empty patch. Aborted."));
|
git-add: introduce --edit (to edit the diff vs. the index)
With "git add -e [<files>]", Git will fire up an editor with the current
diff relative to the index (i.e. what you would get with "git diff
[<files>]").
Now you can edit the patch as much as you like, including adding/removing
lines, editing the text, whatever. Make sure, though, that the first
character of the hunk lines is still a space, a plus or a minus.
After you closed the editor, Git will adjust the line counts of the hunks
if necessary, thanks to the --recount option of apply, and commit the
patch. Except if you deleted everything, in which case nothing happens
(for obvious reasons).
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2009-04-09 05:30:24 +08:00
|
|
|
|
|
|
|
child.git_cmd = 1;
|
2021-11-26 06:52:20 +08:00
|
|
|
strvec_pushl(&child.args, "apply", "--recount", "--cached", file,
|
|
|
|
NULL);
|
git-add: introduce --edit (to edit the diff vs. the index)
With "git add -e [<files>]", Git will fire up an editor with the current
diff relative to the index (i.e. what you would get with "git diff
[<files>]").
Now you can edit the patch as much as you like, including adding/removing
lines, editing the text, whatever. Make sure, though, that the first
character of the hunk lines is still a space, a plus or a minus.
After you closed the editor, Git will adjust the line counts of the hunks
if necessary, thanks to the --recount option of apply, and commit the
patch. Except if you deleted everything, in which case nothing happens
(for obvious reasons).
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2009-04-09 05:30:24 +08:00
|
|
|
if (run_command(&child))
|
2013-08-31 05:56:49 +08:00
|
|
|
die(_("Could not apply '%s'"), file);
|
git-add: introduce --edit (to edit the diff vs. the index)
With "git add -e [<files>]", Git will fire up an editor with the current
diff relative to the index (i.e. what you would get with "git diff
[<files>]").
Now you can edit the patch as much as you like, including adding/removing
lines, editing the text, whatever. Make sure, though, that the first
character of the hunk lines is still a space, a plus or a minus.
After you closed the editor, Git will adjust the line counts of the hunks
if necessary, thanks to the --recount option of apply, and commit the
patch. Except if you deleted everything, in which case nothing happens
(for obvious reasons).
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2009-04-09 05:30:24 +08:00
|
|
|
|
|
|
|
unlink(file);
|
2012-09-05 01:30:21 +08:00
|
|
|
free(file);
|
2022-04-14 04:01:36 +08:00
|
|
|
release_revisions(&rev);
|
git-add: introduce --edit (to edit the diff vs. the index)
With "git add -e [<files>]", Git will fire up an editor with the current
diff relative to the index (i.e. what you would get with "git diff
[<files>]").
Now you can edit the patch as much as you like, including adding/removing
lines, editing the text, whatever. Make sure, though, that the first
character of the hunk lines is still a space, a plus or a minus.
After you closed the editor, Git will adjust the line counts of the hunks
if necessary, thanks to the --recount option of apply, and commit the
patch. Except if you deleted everything, in which case nothing happens
(for obvious reasons).
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2009-04-09 05:30:24 +08:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2007-08-29 06:41:23 +08:00
|
|
|
static const char ignore_error[] =
|
2011-02-23 07:41:30 +08:00
|
|
|
N_("The following paths are ignored by one of your .gitignore files:\n");
|
2006-12-26 09:46:38 +08:00
|
|
|
|
2013-03-09 14:21:13 +08:00
|
|
|
static int verbose, show_only, ignored_too, refresh_only;
|
2011-04-20 03:18:20 +08:00
|
|
|
static int ignore_add_errors, intent_to_add, ignore_missing;
|
add: warn when adding an embedded repository
It's an easy mistake to add a repository inside another
repository, like:
git clone $url
git add .
The resulting entry is a gitlink, but there's no matching
.gitmodules entry. Trying to use "submodule init" (or clone
with --recursive) doesn't do anything useful. Prior to
v2.13, such an entry caused git-submodule to barf entirely.
In v2.13, the entry is considered "inactive" and quietly
ignored. Either way, no clone of your repository can do
anything useful with the gitlink without the user manually
adding the submodule config.
In most cases, the user probably meant to either add a real
submodule, or they forgot to put the embedded repository in
their .gitignore file.
Let's issue a warning when we see this case. There are a few
things to note:
- the warning will go in the git-add porcelain; anybody
wanting to do low-level manipulation of the index is
welcome to create whatever funny states they want.
- we detect the case by looking for a newly added gitlink;
updates via "git add submodule" are perfectly reasonable,
and this avoids us having to investigate .gitmodules
entirely
- there's a command-line option to suppress the warning.
This is needed for git-submodule itself (which adds the
entry before adding any submodule config), but also
provides a mechanism for other scripts doing
submodule-like things.
We could make this a hard error instead of a warning.
However, we do add lots of sub-repos in our test suite. It's
not _wrong_ to do so. It just creates a state where users
may be surprised. Pointing them in the right direction with
a gentle hint is probably the best option.
There is a config knob that can disable the (long) hint. But
I intentionally omitted a config knob to disable the warning
entirely. Whether the warning is sensible or not is
generally about context, not about the user's preferences.
If there's a tool or workflow that adds gitlinks without
matching .gitmodules, it should probably be taught about the
new command-line option, rather than blanket-disabling the
warning.
Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2017-06-14 18:58:22 +08:00
|
|
|
static int warn_on_embedded_repo = 1;
|
2011-04-20 03:18:20 +08:00
|
|
|
|
2013-04-23 05:30:22 +08:00
|
|
|
#define ADDREMOVE_DEFAULT 1
|
2011-04-20 03:18:20 +08:00
|
|
|
static int addremove = ADDREMOVE_DEFAULT;
|
|
|
|
static int addremove_explicit = -1; /* unspecified */
|
2007-10-04 05:45:02 +08:00
|
|
|
|
2016-06-01 06:08:18 +08:00
|
|
|
static char *chmod_arg;
|
|
|
|
|
2013-04-23 04:29:20 +08:00
|
|
|
static int ignore_removal_cb(const struct option *opt, const char *arg, int unset)
|
|
|
|
{
|
|
|
|
/* if we are told to ignore, we are not adding removals */
|
|
|
|
*(int *)opt->value = !unset ? 0 : 1;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2007-10-04 05:45:02 +08:00
|
|
|
static struct option builtin_add_options[] = {
|
2012-08-20 20:31:52 +08:00
|
|
|
OPT__DRY_RUN(&show_only, N_("dry run")),
|
|
|
|
OPT__VERBOSE(&verbose, N_("be verbose")),
|
2007-10-04 05:45:02 +08:00
|
|
|
OPT_GROUP(""),
|
2013-03-09 14:21:13 +08:00
|
|
|
OPT_BOOL('i', "interactive", &add_interactive, N_("interactive picking")),
|
|
|
|
OPT_BOOL('p', "patch", &patch_interactive, N_("select hunks interactively")),
|
|
|
|
OPT_BOOL('e', "edit", &edit_interactive, N_("edit current diff and apply")),
|
2018-02-09 19:01:42 +08:00
|
|
|
OPT__FORCE(&ignored_too, N_("allow adding otherwise ignored files"), 0),
|
2013-03-09 14:21:13 +08:00
|
|
|
OPT_BOOL('u', "update", &take_worktree_changes, N_("update tracked files")),
|
2017-11-17 00:38:28 +08:00
|
|
|
OPT_BOOL(0, "renormalize", &add_renormalize, N_("renormalize EOL of tracked files (implies -u)")),
|
2013-03-09 14:21:13 +08:00
|
|
|
OPT_BOOL('N', "intent-to-add", &intent_to_add, N_("record only the fact that the path will be added later")),
|
2011-04-20 03:18:20 +08:00
|
|
|
OPT_BOOL('A', "all", &addremove_explicit, N_("add changes from all tracked and untracked files")),
|
Use OPT_CALLBACK and OPT_CALLBACK_F
In the codebase, there are many options which use OPTION_CALLBACK in a
plain ol' struct definition. However, we have the OPT_CALLBACK and
OPT_CALLBACK_F macros which are meant to abstract these plain struct
definitions away. These macros are useful as they semantically signal to
developers that these are just normal callback option with nothing fancy
happening.
Replace plain struct definitions of OPTION_CALLBACK with OPT_CALLBACK or
OPT_CALLBACK_F where applicable. The heavy lifting was done using the
following (disgusting) shell script:
#!/bin/sh
do_replacement () {
tr '\n' '\r' |
sed -e 's/{\s*OPTION_CALLBACK,\s*\([^,]*\),\([^,]*\),\([^,]*\),\([^,]*\),\([^,]*\),\s*0,\(\s*[^[:space:]}]*\)\s*}/OPT_CALLBACK(\1,\2,\3,\4,\5,\6)/g' |
sed -e 's/{\s*OPTION_CALLBACK,\s*\([^,]*\),\([^,]*\),\([^,]*\),\([^,]*\),\([^,]*\),\([^,]*\),\(\s*[^[:space:]}]*\)\s*}/OPT_CALLBACK_F(\1,\2,\3,\4,\5,\6,\7)/g' |
tr '\r' '\n'
}
for f in $(git ls-files \*.c)
do
do_replacement <"$f" >"$f.tmp"
mv "$f.tmp" "$f"
done
The result was manually inspected and then reformatted to match the
style of the surrounding code. Finally, using
`git grep OPTION_CALLBACK \*.c`, leftover results which were not handled
by the script were manually transformed.
Signed-off-by: Denton Liu <liu.denton@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2020-04-28 16:36:28 +08:00
|
|
|
OPT_CALLBACK_F(0, "ignore-removal", &addremove_explicit,
|
2013-04-23 04:29:20 +08:00
|
|
|
NULL /* takes no arguments */,
|
|
|
|
N_("ignore paths removed in the working tree (same as --no-all)"),
|
Use OPT_CALLBACK and OPT_CALLBACK_F
In the codebase, there are many options which use OPTION_CALLBACK in a
plain ol' struct definition. However, we have the OPT_CALLBACK and
OPT_CALLBACK_F macros which are meant to abstract these plain struct
definitions away. These macros are useful as they semantically signal to
developers that these are just normal callback option with nothing fancy
happening.
Replace plain struct definitions of OPTION_CALLBACK with OPT_CALLBACK or
OPT_CALLBACK_F where applicable. The heavy lifting was done using the
following (disgusting) shell script:
#!/bin/sh
do_replacement () {
tr '\n' '\r' |
sed -e 's/{\s*OPTION_CALLBACK,\s*\([^,]*\),\([^,]*\),\([^,]*\),\([^,]*\),\([^,]*\),\s*0,\(\s*[^[:space:]}]*\)\s*}/OPT_CALLBACK(\1,\2,\3,\4,\5,\6)/g' |
sed -e 's/{\s*OPTION_CALLBACK,\s*\([^,]*\),\([^,]*\),\([^,]*\),\([^,]*\),\([^,]*\),\([^,]*\),\(\s*[^[:space:]}]*\)\s*}/OPT_CALLBACK_F(\1,\2,\3,\4,\5,\6,\7)/g' |
tr '\r' '\n'
}
for f in $(git ls-files \*.c)
do
do_replacement <"$f" >"$f.tmp"
mv "$f.tmp" "$f"
done
The result was manually inspected and then reformatted to match the
style of the surrounding code. Finally, using
`git grep OPTION_CALLBACK \*.c`, leftover results which were not handled
by the script were manually transformed.
Signed-off-by: Denton Liu <liu.denton@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2020-04-28 16:36:28 +08:00
|
|
|
PARSE_OPT_NOARG, ignore_removal_cb),
|
2013-03-09 14:21:13 +08:00
|
|
|
OPT_BOOL( 0 , "refresh", &refresh_only, N_("don't add, only refresh the index")),
|
|
|
|
OPT_BOOL( 0 , "ignore-errors", &ignore_add_errors, N_("just skip files which cannot be added because of errors")),
|
|
|
|
OPT_BOOL( 0 , "ignore-missing", &ignore_missing, N_("check if - even missing - files are ignored in dry run")),
|
2021-09-24 23:39:08 +08:00
|
|
|
OPT_BOOL(0, "sparse", &include_sparse, N_("allow updating entries outside of the sparse-checkout cone")),
|
2018-08-03 03:18:14 +08:00
|
|
|
OPT_STRING(0, "chmod", &chmod_arg, "(+|-)x",
|
|
|
|
N_("override the executable bit of the listed files")),
|
add: warn when adding an embedded repository
It's an easy mistake to add a repository inside another
repository, like:
git clone $url
git add .
The resulting entry is a gitlink, but there's no matching
.gitmodules entry. Trying to use "submodule init" (or clone
with --recursive) doesn't do anything useful. Prior to
v2.13, such an entry caused git-submodule to barf entirely.
In v2.13, the entry is considered "inactive" and quietly
ignored. Either way, no clone of your repository can do
anything useful with the gitlink without the user manually
adding the submodule config.
In most cases, the user probably meant to either add a real
submodule, or they forgot to put the embedded repository in
their .gitignore file.
Let's issue a warning when we see this case. There are a few
things to note:
- the warning will go in the git-add porcelain; anybody
wanting to do low-level manipulation of the index is
welcome to create whatever funny states they want.
- we detect the case by looking for a newly added gitlink;
updates via "git add submodule" are perfectly reasonable,
and this avoids us having to investigate .gitmodules
entirely
- there's a command-line option to suppress the warning.
This is needed for git-submodule itself (which adds the
entry before adding any submodule config), but also
provides a mechanism for other scripts doing
submodule-like things.
We could make this a hard error instead of a warning.
However, we do add lots of sub-repos in our test suite. It's
not _wrong_ to do so. It just creates a state where users
may be surprised. Pointing them in the right direction with
a gentle hint is probably the best option.
There is a config knob that can disable the (long) hint. But
I intentionally omitted a config knob to disable the warning
entirely. Whether the warning is sensible or not is
generally about context, not about the user's preferences.
If there's a tool or workflow that adds gitlinks without
matching .gitmodules, it should probably be taught about the
new command-line option, rather than blanket-disabling the
warning.
Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2017-06-14 18:58:22 +08:00
|
|
|
OPT_HIDDEN_BOOL(0, "warn-embedded-repo", &warn_on_embedded_repo,
|
|
|
|
N_("warn when adding an embedded repository")),
|
2019-12-03 22:02:13 +08:00
|
|
|
OPT_PATHSPEC_FROM_FILE(&pathspec_from_file),
|
|
|
|
OPT_PATHSPEC_FILE_NUL(&pathspec_file_nul),
|
2007-10-04 05:45:02 +08:00
|
|
|
OPT_END(),
|
|
|
|
};
|
|
|
|
|
2008-05-26 05:25:02 +08:00
|
|
|
static int add_config(const char *var, const char *value, void *cb)
|
2008-05-13 01:59:23 +08:00
|
|
|
{
|
2011-05-15 04:19:21 +08:00
|
|
|
if (!strcmp(var, "add.ignoreerrors") ||
|
|
|
|
!strcmp(var, "add.ignore-errors")) {
|
2008-05-13 01:59:23 +08:00
|
|
|
ignore_add_errors = git_config_bool(var, value);
|
|
|
|
return 0;
|
|
|
|
}
|
2019-11-13 20:40:57 +08:00
|
|
|
|
2008-05-26 05:25:02 +08:00
|
|
|
return git_default_config(var, value, cb);
|
2008-05-13 01:59:23 +08:00
|
|
|
}
|
|
|
|
|
add: warn when adding an embedded repository
It's an easy mistake to add a repository inside another
repository, like:
git clone $url
git add .
The resulting entry is a gitlink, but there's no matching
.gitmodules entry. Trying to use "submodule init" (or clone
with --recursive) doesn't do anything useful. Prior to
v2.13, such an entry caused git-submodule to barf entirely.
In v2.13, the entry is considered "inactive" and quietly
ignored. Either way, no clone of your repository can do
anything useful with the gitlink without the user manually
adding the submodule config.
In most cases, the user probably meant to either add a real
submodule, or they forgot to put the embedded repository in
their .gitignore file.
Let's issue a warning when we see this case. There are a few
things to note:
- the warning will go in the git-add porcelain; anybody
wanting to do low-level manipulation of the index is
welcome to create whatever funny states they want.
- we detect the case by looking for a newly added gitlink;
updates via "git add submodule" are perfectly reasonable,
and this avoids us having to investigate .gitmodules
entirely
- there's a command-line option to suppress the warning.
This is needed for git-submodule itself (which adds the
entry before adding any submodule config), but also
provides a mechanism for other scripts doing
submodule-like things.
We could make this a hard error instead of a warning.
However, we do add lots of sub-repos in our test suite. It's
not _wrong_ to do so. It just creates a state where users
may be surprised. Pointing them in the right direction with
a gentle hint is probably the best option.
There is a config knob that can disable the (long) hint. But
I intentionally omitted a config knob to disable the warning
entirely. Whether the warning is sensible or not is
generally about context, not about the user's preferences.
If there's a tool or workflow that adds gitlinks without
matching .gitmodules, it should probably be taught about the
new command-line option, rather than blanket-disabling the
warning.
Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2017-06-14 18:58:22 +08:00
|
|
|
static const char embedded_advice[] = N_(
|
|
|
|
"You've added another git repository inside your current repository.\n"
|
|
|
|
"Clones of the outer repository will not contain the contents of\n"
|
|
|
|
"the embedded repository and will not know how to obtain it.\n"
|
|
|
|
"If you meant to add a submodule, use:\n"
|
|
|
|
"\n"
|
|
|
|
" git submodule add <url> %s\n"
|
|
|
|
"\n"
|
|
|
|
"If you added this path by mistake, you can remove it from the\n"
|
|
|
|
"index with:\n"
|
|
|
|
"\n"
|
|
|
|
" git rm --cached %s\n"
|
|
|
|
"\n"
|
|
|
|
"See \"git help submodule\" for more information."
|
|
|
|
);
|
|
|
|
|
|
|
|
static void check_embedded_repo(const char *path)
|
|
|
|
{
|
|
|
|
struct strbuf name = STRBUF_INIT;
|
2021-08-23 18:44:01 +08:00
|
|
|
static int adviced_on_embedded_repo = 0;
|
add: warn when adding an embedded repository
It's an easy mistake to add a repository inside another
repository, like:
git clone $url
git add .
The resulting entry is a gitlink, but there's no matching
.gitmodules entry. Trying to use "submodule init" (or clone
with --recursive) doesn't do anything useful. Prior to
v2.13, such an entry caused git-submodule to barf entirely.
In v2.13, the entry is considered "inactive" and quietly
ignored. Either way, no clone of your repository can do
anything useful with the gitlink without the user manually
adding the submodule config.
In most cases, the user probably meant to either add a real
submodule, or they forgot to put the embedded repository in
their .gitignore file.
Let's issue a warning when we see this case. There are a few
things to note:
- the warning will go in the git-add porcelain; anybody
wanting to do low-level manipulation of the index is
welcome to create whatever funny states they want.
- we detect the case by looking for a newly added gitlink;
updates via "git add submodule" are perfectly reasonable,
and this avoids us having to investigate .gitmodules
entirely
- there's a command-line option to suppress the warning.
This is needed for git-submodule itself (which adds the
entry before adding any submodule config), but also
provides a mechanism for other scripts doing
submodule-like things.
We could make this a hard error instead of a warning.
However, we do add lots of sub-repos in our test suite. It's
not _wrong_ to do so. It just creates a state where users
may be surprised. Pointing them in the right direction with
a gentle hint is probably the best option.
There is a config knob that can disable the (long) hint. But
I intentionally omitted a config knob to disable the warning
entirely. Whether the warning is sensible or not is
generally about context, not about the user's preferences.
If there's a tool or workflow that adds gitlinks without
matching .gitmodules, it should probably be taught about the
new command-line option, rather than blanket-disabling the
warning.
Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2017-06-14 18:58:22 +08:00
|
|
|
|
|
|
|
if (!warn_on_embedded_repo)
|
|
|
|
return;
|
|
|
|
if (!ends_with(path, "/"))
|
|
|
|
return;
|
|
|
|
|
|
|
|
/* Drop trailing slash for aesthetics */
|
|
|
|
strbuf_addstr(&name, path);
|
|
|
|
strbuf_strip_suffix(&name, "/");
|
|
|
|
|
|
|
|
warning(_("adding embedded git repository: %s"), name.buf);
|
2021-08-23 18:44:01 +08:00
|
|
|
if (!adviced_on_embedded_repo &&
|
|
|
|
advice_enabled(ADVICE_ADD_EMBEDDED_REPO)) {
|
add: warn when adding an embedded repository
It's an easy mistake to add a repository inside another
repository, like:
git clone $url
git add .
The resulting entry is a gitlink, but there's no matching
.gitmodules entry. Trying to use "submodule init" (or clone
with --recursive) doesn't do anything useful. Prior to
v2.13, such an entry caused git-submodule to barf entirely.
In v2.13, the entry is considered "inactive" and quietly
ignored. Either way, no clone of your repository can do
anything useful with the gitlink without the user manually
adding the submodule config.
In most cases, the user probably meant to either add a real
submodule, or they forgot to put the embedded repository in
their .gitignore file.
Let's issue a warning when we see this case. There are a few
things to note:
- the warning will go in the git-add porcelain; anybody
wanting to do low-level manipulation of the index is
welcome to create whatever funny states they want.
- we detect the case by looking for a newly added gitlink;
updates via "git add submodule" are perfectly reasonable,
and this avoids us having to investigate .gitmodules
entirely
- there's a command-line option to suppress the warning.
This is needed for git-submodule itself (which adds the
entry before adding any submodule config), but also
provides a mechanism for other scripts doing
submodule-like things.
We could make this a hard error instead of a warning.
However, we do add lots of sub-repos in our test suite. It's
not _wrong_ to do so. It just creates a state where users
may be surprised. Pointing them in the right direction with
a gentle hint is probably the best option.
There is a config knob that can disable the (long) hint. But
I intentionally omitted a config knob to disable the warning
entirely. Whether the warning is sensible or not is
generally about context, not about the user's preferences.
If there's a tool or workflow that adds gitlinks without
matching .gitmodules, it should probably be taught about the
new command-line option, rather than blanket-disabling the
warning.
Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2017-06-14 18:58:22 +08:00
|
|
|
advise(embedded_advice, name.buf, name.buf);
|
2021-08-23 18:44:01 +08:00
|
|
|
adviced_on_embedded_repo = 1;
|
add: warn when adding an embedded repository
It's an easy mistake to add a repository inside another
repository, like:
git clone $url
git add .
The resulting entry is a gitlink, but there's no matching
.gitmodules entry. Trying to use "submodule init" (or clone
with --recursive) doesn't do anything useful. Prior to
v2.13, such an entry caused git-submodule to barf entirely.
In v2.13, the entry is considered "inactive" and quietly
ignored. Either way, no clone of your repository can do
anything useful with the gitlink without the user manually
adding the submodule config.
In most cases, the user probably meant to either add a real
submodule, or they forgot to put the embedded repository in
their .gitignore file.
Let's issue a warning when we see this case. There are a few
things to note:
- the warning will go in the git-add porcelain; anybody
wanting to do low-level manipulation of the index is
welcome to create whatever funny states they want.
- we detect the case by looking for a newly added gitlink;
updates via "git add submodule" are perfectly reasonable,
and this avoids us having to investigate .gitmodules
entirely
- there's a command-line option to suppress the warning.
This is needed for git-submodule itself (which adds the
entry before adding any submodule config), but also
provides a mechanism for other scripts doing
submodule-like things.
We could make this a hard error instead of a warning.
However, we do add lots of sub-repos in our test suite. It's
not _wrong_ to do so. It just creates a state where users
may be surprised. Pointing them in the right direction with
a gentle hint is probably the best option.
There is a config knob that can disable the (long) hint. But
I intentionally omitted a config knob to disable the warning
entirely. Whether the warning is sensible or not is
generally about context, not about the user's preferences.
If there's a tool or workflow that adds gitlinks without
matching .gitmodules, it should probably be taught about the
new command-line option, rather than blanket-disabling the
warning.
Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2017-06-14 18:58:22 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
strbuf_release(&name);
|
|
|
|
}
|
|
|
|
|
2016-09-15 05:07:47 +08:00
|
|
|
static int add_files(struct dir_struct *dir, int flags)
|
2008-07-20 10:22:25 +08:00
|
|
|
{
|
|
|
|
int i, exit_status = 0;
|
2021-09-24 23:39:06 +08:00
|
|
|
struct string_list matched_sparse_paths = STRING_LIST_INIT_NODUP;
|
2008-07-20 10:22:25 +08:00
|
|
|
|
|
|
|
if (dir->ignored_nr) {
|
2011-02-23 07:41:30 +08:00
|
|
|
fprintf(stderr, _(ignore_error));
|
2008-07-20 10:22:25 +08:00
|
|
|
for (i = 0; i < dir->ignored_nr; i++)
|
|
|
|
fprintf(stderr, "%s\n", dir->ignored[i]->name);
|
2021-08-23 18:44:00 +08:00
|
|
|
if (advice_enabled(ADVICE_ADD_IGNORED_FILE))
|
2020-02-06 18:57:30 +08:00
|
|
|
advise(_("Use -f if you really want to add them.\n"
|
|
|
|
"Turn this message off by running\n"
|
|
|
|
"\"git config advice.addIgnoredFile false\""));
|
2014-11-22 00:08:19 +08:00
|
|
|
exit_status = 1;
|
2008-07-20 10:22:25 +08:00
|
|
|
}
|
|
|
|
|
add: warn when adding an embedded repository
It's an easy mistake to add a repository inside another
repository, like:
git clone $url
git add .
The resulting entry is a gitlink, but there's no matching
.gitmodules entry. Trying to use "submodule init" (or clone
with --recursive) doesn't do anything useful. Prior to
v2.13, such an entry caused git-submodule to barf entirely.
In v2.13, the entry is considered "inactive" and quietly
ignored. Either way, no clone of your repository can do
anything useful with the gitlink without the user manually
adding the submodule config.
In most cases, the user probably meant to either add a real
submodule, or they forgot to put the embedded repository in
their .gitignore file.
Let's issue a warning when we see this case. There are a few
things to note:
- the warning will go in the git-add porcelain; anybody
wanting to do low-level manipulation of the index is
welcome to create whatever funny states they want.
- we detect the case by looking for a newly added gitlink;
updates via "git add submodule" are perfectly reasonable,
and this avoids us having to investigate .gitmodules
entirely
- there's a command-line option to suppress the warning.
This is needed for git-submodule itself (which adds the
entry before adding any submodule config), but also
provides a mechanism for other scripts doing
submodule-like things.
We could make this a hard error instead of a warning.
However, we do add lots of sub-repos in our test suite. It's
not _wrong_ to do so. It just creates a state where users
may be surprised. Pointing them in the right direction with
a gentle hint is probably the best option.
There is a config knob that can disable the (long) hint. But
I intentionally omitted a config knob to disable the warning
entirely. Whether the warning is sensible or not is
generally about context, not about the user's preferences.
If there's a tool or workflow that adds gitlinks without
matching .gitmodules, it should probably be taught about the
new command-line option, rather than blanket-disabling the
warning.
Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2017-06-14 18:58:22 +08:00
|
|
|
for (i = 0; i < dir->nr; i++) {
|
2021-09-24 23:39:08 +08:00
|
|
|
if (!include_sparse &&
|
|
|
|
!path_in_sparse_checkout(dir->entries[i]->name, &the_index)) {
|
2021-09-24 23:39:06 +08:00
|
|
|
string_list_append(&matched_sparse_paths,
|
|
|
|
dir->entries[i]->name);
|
|
|
|
continue;
|
|
|
|
}
|
2016-09-15 05:07:47 +08:00
|
|
|
if (add_file_to_index(&the_index, dir->entries[i]->name, flags)) {
|
2008-07-20 10:22:25 +08:00
|
|
|
if (!ignore_add_errors)
|
2011-02-23 07:41:29 +08:00
|
|
|
die(_("adding files failed"));
|
2008-07-20 10:22:25 +08:00
|
|
|
exit_status = 1;
|
2019-04-10 07:07:37 +08:00
|
|
|
} else {
|
|
|
|
check_embedded_repo(dir->entries[i]->name);
|
2008-07-20 10:22:25 +08:00
|
|
|
}
|
add: warn when adding an embedded repository
It's an easy mistake to add a repository inside another
repository, like:
git clone $url
git add .
The resulting entry is a gitlink, but there's no matching
.gitmodules entry. Trying to use "submodule init" (or clone
with --recursive) doesn't do anything useful. Prior to
v2.13, such an entry caused git-submodule to barf entirely.
In v2.13, the entry is considered "inactive" and quietly
ignored. Either way, no clone of your repository can do
anything useful with the gitlink without the user manually
adding the submodule config.
In most cases, the user probably meant to either add a real
submodule, or they forgot to put the embedded repository in
their .gitignore file.
Let's issue a warning when we see this case. There are a few
things to note:
- the warning will go in the git-add porcelain; anybody
wanting to do low-level manipulation of the index is
welcome to create whatever funny states they want.
- we detect the case by looking for a newly added gitlink;
updates via "git add submodule" are perfectly reasonable,
and this avoids us having to investigate .gitmodules
entirely
- there's a command-line option to suppress the warning.
This is needed for git-submodule itself (which adds the
entry before adding any submodule config), but also
provides a mechanism for other scripts doing
submodule-like things.
We could make this a hard error instead of a warning.
However, we do add lots of sub-repos in our test suite. It's
not _wrong_ to do so. It just creates a state where users
may be surprised. Pointing them in the right direction with
a gentle hint is probably the best option.
There is a config knob that can disable the (long) hint. But
I intentionally omitted a config knob to disable the warning
entirely. Whether the warning is sensible or not is
generally about context, not about the user's preferences.
If there's a tool or workflow that adds gitlinks without
matching .gitmodules, it should probably be taught about the
new command-line option, rather than blanket-disabling the
warning.
Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2017-06-14 18:58:22 +08:00
|
|
|
}
|
2021-09-24 23:39:06 +08:00
|
|
|
|
|
|
|
if (matched_sparse_paths.nr) {
|
|
|
|
advise_on_updating_sparse_paths(&matched_sparse_paths);
|
|
|
|
exit_status = 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
string_list_clear(&matched_sparse_paths, 0);
|
|
|
|
|
2008-07-20 10:22:25 +08:00
|
|
|
return exit_status;
|
|
|
|
}
|
|
|
|
|
2006-07-29 13:44:25 +08:00
|
|
|
int cmd_add(int argc, const char **argv, const char *prefix)
|
2006-05-18 00:33:32 +08:00
|
|
|
{
|
2008-05-13 01:58:10 +08:00
|
|
|
int exit_status = 0;
|
2013-07-14 16:35:46 +08:00
|
|
|
struct pathspec pathspec;
|
2021-07-01 18:51:27 +08:00
|
|
|
struct dir_struct dir = DIR_INIT;
|
2016-09-15 05:07:47 +08:00
|
|
|
int flags;
|
2008-07-20 10:22:25 +08:00
|
|
|
int add_new_files;
|
|
|
|
int require_pathspec;
|
2010-02-10 06:30:49 +08:00
|
|
|
char *seen = NULL;
|
lock_file: move static locks into functions
Placing `struct lock_file`s on the stack used to be a bad idea, because
the temp- and lockfile-machinery would keep a pointer into the struct.
But after 076aa2cbd (tempfile: auto-allocate tempfiles on heap,
2017-09-05), we can safely have lockfiles on the stack. (This applies
even if a user returns early, leaving a locked lock behind.)
Each of these `struct lock_file`s is used from within a single function.
Move them into the respective functions to make the scope clearer and
drop the staticness.
For good measure, I have inspected these sites and come to believe that
they always release the lock, with the possible exception of bailing out
using `die()` or `exit()` or by returning from a `cmd_foo()`.
As pointed out by Jeff King, it would be bad if someone held on to a
`struct lock_file *` for some reason. After some grepping, I agree with
his findings: no-one appears to be doing that.
After this commit, the remaining occurrences of "static struct
lock_file" are locks that are used from within different functions. That
is, they need to remain static. (Short of more intrusive changes like
passing around pointers to non-static locks.)
Signed-off-by: Martin Ågren <martin.agren@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2018-05-10 04:55:39 +08:00
|
|
|
struct lock_file lock_file = LOCK_INIT;
|
git-add --interactive
A script to be driven when the user says "git add --interactive"
is introduced.
When it is run, first it runs its internal 'status' command to
show the current status, and then goes into its internactive
command loop.
The command loop shows the list of subcommands available, and
gives a prompt "What now> ". In general, when the prompt ends
with a single '>', you can pick only one of the choices given
and type return, like this:
*** Commands ***
1: status 2: update 3: revert 4: add untracked
5: patch 6: diff 7: quit 8: help
What now> 1
You also could say "s" or "sta" or "status" above as long as the
choice is unique.
The main command loop has 6 subcommands (plus help and quit).
* 'status' shows the change between HEAD and index (i.e. what
will be committed if you say "git commit"), and between index
and working tree files (i.e. what you could stage further
before "git commit" using "git-add") for each path. A sample
output looks like this:
staged unstaged path
1: binary nothing foo.png
2: +403/-35 +1/-1 git-add--interactive.perl
It shows that foo.png has differences from HEAD (but that is
binary so line count cannot be shown) and there is no
difference between indexed copy and the working tree
version (if the working tree version were also different,
'binary' would have been shown in place of 'nothing'). The
other file, git-add--interactive.perl, has 403 lines added
and 35 lines deleted if you commit what is in the index, but
working tree file has further modifications (one addition and
one deletion).
* 'update' shows the status information and gives prompt
"Update>>". When the prompt ends with double '>>', you can
make more than one selection, concatenated with whitespace or
comma. Also you can say ranges. E.g. "2-5 7,9" to choose
2,3,4,5,7,9 from the list. You can say '*' to choose
everything.
What you chose are then highlighted with '*', like this:
staged unstaged path
1: binary nothing foo.png
* 2: +403/-35 +1/-1 git-add--interactive.perl
To remove selection, prefix the input with - like this:
Update>> -2
After making the selection, answer with an empty line to
stage the contents of working tree files for selected paths
in the index.
* 'revert' has a very similar UI to 'update', and the staged
information for selected paths are reverted to that of the
HEAD version. Reverting new paths makes them untracked.
* 'add untracked' has a very similar UI to 'update' and
'revert', and lets you add untracked paths to the index.
* 'patch' lets you choose one path out of 'status' like
selection. After choosing the path, it presents diff between
the index and the working tree file and asks you if you want
to stage the change of each hunk. You can say:
y - add the change from that hunk to index
n - do not add the change from that hunk to index
a - add the change from that hunk and all the rest to index
d - do not the change from that hunk nor any of the rest to index
j - do not decide on this hunk now, and view the next
undecided hunk
J - do not decide on this hunk now, and view the next hunk
k - do not decide on this hunk now, and view the previous
undecided hunk
K - do not decide on this hunk now, and view the previous hunk
After deciding the fate for all hunks, if there is any hunk
that was chosen, the index is updated with the selected hunks.
* 'diff' lets you review what will be committed (i.e. between
HEAD and index).
This is still rough, but does everything except a few things I
think are needed.
* 'patch' should be able to allow splitting a hunk into
multiple hunks.
* 'patch' does not adjust the line offsets @@ -k,l +m,n @@
in the hunk header. This does not have major problem in
practice, but it _should_ do the adjustment.
* It does not have any explicit support for a merge in
progress; it may not work at all.
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-12-11 12:55:50 +08:00
|
|
|
|
2009-06-18 17:17:54 +08:00
|
|
|
git_config(add_config, NULL);
|
|
|
|
|
2009-05-24 02:53:12 +08:00
|
|
|
argc = parse_options(argc, argv, prefix, builtin_add_options,
|
git-add: introduce --edit (to edit the diff vs. the index)
With "git add -e [<files>]", Git will fire up an editor with the current
diff relative to the index (i.e. what you would get with "git diff
[<files>]").
Now you can edit the patch as much as you like, including adding/removing
lines, editing the text, whatever. Make sure, though, that the first
character of the hunk lines is still a space, a plus or a minus.
After you closed the editor, Git will adjust the line counts of the hunks
if necessary, thanks to the --recount option of apply, and commit the
patch. Except if you deleted everything, in which case nothing happens
(for obvious reasons).
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2009-04-09 05:30:24 +08:00
|
|
|
builtin_add_usage, PARSE_OPT_KEEP_ARGV0);
|
2007-11-25 21:15:42 +08:00
|
|
|
if (patch_interactive)
|
|
|
|
add_interactive = 1;
|
2019-12-03 22:02:13 +08:00
|
|
|
if (add_interactive) {
|
2021-05-05 22:52:04 +08:00
|
|
|
if (show_only)
|
2022-01-06 04:02:16 +08:00
|
|
|
die(_("options '%s' and '%s' cannot be used together"), "--dry-run", "--interactive/--patch");
|
2019-12-03 22:02:13 +08:00
|
|
|
if (pathspec_from_file)
|
2022-01-06 04:02:16 +08:00
|
|
|
die(_("options '%s' and '%s' cannot be used together"), "--pathspec-from-file", "--interactive/--patch");
|
2020-09-30 20:28:18 +08:00
|
|
|
exit(interactive_add(argv + 1, prefix, patch_interactive));
|
2019-12-03 22:02:13 +08:00
|
|
|
}
|
2006-05-18 00:33:32 +08:00
|
|
|
|
2019-12-03 22:02:13 +08:00
|
|
|
if (edit_interactive) {
|
|
|
|
if (pathspec_from_file)
|
2022-01-06 04:02:16 +08:00
|
|
|
die(_("options '%s' and '%s' cannot be used together"), "--pathspec-from-file", "--edit");
|
git-add: introduce --edit (to edit the diff vs. the index)
With "git add -e [<files>]", Git will fire up an editor with the current
diff relative to the index (i.e. what you would get with "git diff
[<files>]").
Now you can edit the patch as much as you like, including adding/removing
lines, editing the text, whatever. Make sure, though, that the first
character of the hunk lines is still a space, a plus or a minus.
After you closed the editor, Git will adjust the line counts of the hunks
if necessary, thanks to the --recount option of apply, and commit the
patch. Except if you deleted everything, in which case nothing happens
(for obvious reasons).
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2009-04-09 05:30:24 +08:00
|
|
|
return(edit_patch(argc, argv, prefix));
|
2019-12-03 22:02:13 +08:00
|
|
|
}
|
git-add: introduce --edit (to edit the diff vs. the index)
With "git add -e [<files>]", Git will fire up an editor with the current
diff relative to the index (i.e. what you would get with "git diff
[<files>]").
Now you can edit the patch as much as you like, including adding/removing
lines, editing the text, whatever. Make sure, though, that the first
character of the hunk lines is still a space, a plus or a minus.
After you closed the editor, Git will adjust the line counts of the hunks
if necessary, thanks to the --recount option of apply, and commit the
patch. Except if you deleted everything, in which case nothing happens
(for obvious reasons).
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2009-04-09 05:30:24 +08:00
|
|
|
argc--;
|
|
|
|
argv++;
|
|
|
|
|
2011-04-20 03:18:20 +08:00
|
|
|
if (0 <= addremove_explicit)
|
|
|
|
addremove = addremove_explicit;
|
|
|
|
else if (take_worktree_changes && ADDREMOVE_DEFAULT)
|
|
|
|
addremove = 0; /* "-u" was given but not "-A" */
|
|
|
|
|
git-add --all: add all files
People sometimes find that "git add -u && git add ." are 13 keystrokes too
many. This reduces it by nine.
The support of this has been very low priority for me personally, because
I almost never do "git add ." in a directory with already tracked files,
and in a new directory, there is no point saying "git add -u".
However, for two types of people (that are very different from me), this
mode of operation may make sense and there is no reason to leave it
unsupported. That is:
(1) If you are extremely well disciplined and keep perfect .gitignore, it
always is safe to say "git add ."; or
(2) If you are extremely undisciplined and do not even know what files
you created, and you do not very much care what goes in your history,
it does not matter if "git add ." included everything.
So there it is, although I suspect I will not use it myself, ever.
It will be too much of a change that is against the expectation of the
existing users to allow "git commit -a" to include untracked files, and
it would be inconsistent if we named this new option "-a", so the short
option is "-A". We _might_ want to later add "git commit -A" but that is
a separate topic.
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2008-07-20 10:51:11 +08:00
|
|
|
if (addremove && take_worktree_changes)
|
2022-01-06 04:02:16 +08:00
|
|
|
die(_("options '%s' and '%s' cannot be used together"), "-A", "-u");
|
2011-04-20 03:18:20 +08:00
|
|
|
|
2010-07-10 06:18:38 +08:00
|
|
|
if (!show_only && ignore_missing)
|
2022-01-06 04:02:19 +08:00
|
|
|
die(_("the option '%s' requires '%s'"), "--ignore-missing", "--dry-run");
|
2013-03-20 06:53:17 +08:00
|
|
|
|
2016-09-15 05:07:47 +08:00
|
|
|
if (chmod_arg && ((chmod_arg[0] != '-' && chmod_arg[0] != '+') ||
|
|
|
|
chmod_arg[1] != 'x' || chmod_arg[2]))
|
2016-06-01 06:08:18 +08:00
|
|
|
die(_("--chmod param '%s' must be either -x or +x"), chmod_arg);
|
|
|
|
|
2017-11-17 00:38:28 +08:00
|
|
|
add_new_files = !take_worktree_changes && !refresh_only && !add_renormalize;
|
add: simplify -u/-A without pathspec
Since Git 2.0, "add -u" and "add -A" run from a subdirectory without
any pathspec mean "everything in the working tree" (before 2.0, they
were limited to the current directory). The limiting to the current
directory was implemented by inserting "." to the command line when
the end user did not give us any pathspec. At 2.0, we updated the
code to insert ":/" (instead of '.') to consider everything from the
top-level, by using a pathspec magic "top".
The call to parse_pathspec() using the command line arguments is,
however, made with PATHSPEC_PREFER_FULL option since 5a76aff1 (add:
convert to use parse_pathspec, 2013-07-14), which predates Git 2.0.
In retrospect, there was no need to turn "adding . to limit to the
directory" into "adding :/ to unlimit to everywhere" in Git 2.0;
instead we could just have done "if there is no pathspec on the
command line, just let it be". The parse_pathspec() then would give
us a pathspec that matches everything and all is well.
Incidentally such a simplification also fixes a corner case bug that
stems from the fact that ":/" does not necessarily mean any magic.
A user would say "git --literal-pathspecs add -u :/" from the
command line when she has a directory ':' and wants to add
everything in it (and she knows that her :/ will be taken as
'everything under the sun' magic pathspec unless she disables the
magic with --literal-pathspecs). The internal use of ':/' would
behave the same way as such an explicitly given ":/" when run with
"--literal-pathspecs", and will not add everything under the sun as
the code originally intended.
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2015-10-25 10:31:11 +08:00
|
|
|
require_pathspec = !(take_worktree_changes || (0 < addremove_explicit));
|
2008-07-20 10:22:25 +08:00
|
|
|
|
2021-07-29 22:52:04 +08:00
|
|
|
prepare_repo_settings(the_repository);
|
|
|
|
the_repository->settings.command_requires_full_index = 0;
|
|
|
|
|
2022-11-19 21:07:38 +08:00
|
|
|
repo_hold_locked_index(the_repository, &lock_file, LOCK_DIE_ON_ERROR);
|
2006-05-18 00:33:32 +08:00
|
|
|
|
2013-07-14 16:35:46 +08:00
|
|
|
/*
|
|
|
|
* Check the "pathspec '%s' did not match any files" block
|
|
|
|
* below before enabling new magic.
|
|
|
|
*/
|
2018-09-19 01:31:59 +08:00
|
|
|
parse_pathspec(&pathspec, PATHSPEC_ATTR,
|
2013-07-14 16:35:46 +08:00
|
|
|
PATHSPEC_PREFER_FULL |
|
2017-05-12 06:04:24 +08:00
|
|
|
PATHSPEC_SYMLINK_LEADING_PATH,
|
2013-07-14 16:35:46 +08:00
|
|
|
prefix, argv);
|
2006-12-05 00:13:39 +08:00
|
|
|
|
2019-12-03 22:02:13 +08:00
|
|
|
if (pathspec_from_file) {
|
|
|
|
if (pathspec.nr)
|
2022-01-06 04:02:24 +08:00
|
|
|
die(_("'%s' and pathspec arguments cannot be used together"), "--pathspec-from-file");
|
2019-12-03 22:02:13 +08:00
|
|
|
|
|
|
|
parse_pathspec_file(&pathspec, PATHSPEC_ATTR,
|
|
|
|
PATHSPEC_PREFER_FULL |
|
|
|
|
PATHSPEC_SYMLINK_LEADING_PATH,
|
|
|
|
prefix, pathspec_from_file, pathspec_file_nul);
|
|
|
|
} else if (pathspec_file_nul) {
|
2022-01-06 04:02:19 +08:00
|
|
|
die(_("the option '%s' requires '%s'"), "--pathspec-file-nul", "--pathspec-from-file");
|
2019-12-03 22:02:13 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
if (require_pathspec && pathspec.nr == 0) {
|
2019-12-03 22:02:12 +08:00
|
|
|
fprintf(stderr, _("Nothing specified, nothing added.\n"));
|
2021-08-23 18:44:00 +08:00
|
|
|
if (advice_enabled(ADVICE_ADD_EMPTY_PATHSPEC))
|
2020-02-06 18:57:30 +08:00
|
|
|
advise( _("Maybe you wanted to say 'git add .'?\n"
|
|
|
|
"Turn this message off by running\n"
|
|
|
|
"\"git config advice.addEmptyPathspec false\""));
|
2019-12-03 22:02:12 +08:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2019-12-03 22:02:13 +08:00
|
|
|
if (!take_worktree_changes && addremove_explicit < 0 && pathspec.nr)
|
2019-12-03 22:02:12 +08:00
|
|
|
/* Turn "git add pathspec..." to "git add -A pathspec..." */
|
|
|
|
addremove = 1;
|
|
|
|
|
|
|
|
flags = ((verbose ? ADD_CACHE_VERBOSE : 0) |
|
|
|
|
(show_only ? ADD_CACHE_PRETEND : 0) |
|
|
|
|
(intent_to_add ? ADD_CACHE_INTENT : 0) |
|
|
|
|
(ignore_add_errors ? ADD_CACHE_IGNORE_ERRORS : 0) |
|
|
|
|
(!(addremove || take_worktree_changes)
|
|
|
|
? ADD_CACHE_IGNORE_REMOVAL : 0));
|
|
|
|
|
2022-11-19 21:07:38 +08:00
|
|
|
if (repo_read_index_preload(the_repository, &pathspec, 0) < 0)
|
2018-11-02 21:30:50 +08:00
|
|
|
die(_("index file corrupt"));
|
|
|
|
|
|
|
|
die_in_unpopulated_submodule(&the_index, prefix);
|
2017-05-12 06:04:24 +08:00
|
|
|
die_path_inside_submodule(&the_index, &pathspec);
|
|
|
|
|
2009-05-15 04:22:36 +08:00
|
|
|
if (add_new_files) {
|
|
|
|
int baselen;
|
|
|
|
|
|
|
|
/* Set up the default git porcelain excludes */
|
|
|
|
if (!ignored_too) {
|
|
|
|
dir.flags |= DIR_COLLECT_IGNORED;
|
|
|
|
setup_standard_excludes(&dir);
|
|
|
|
}
|
|
|
|
|
builtin-add.c: optimize -A option and "git add ."
The earlier "git add -A" change was done in a quite inefficient
way (i.e. it is as unefficient as "git add -u && git add ." modulo
one fork/exec and read/write index).
When the user asks "git add .", we do not have to examine all paths
we encounter and perform the excluded() and dir_add_name()
processing, both of which are slower code and use slower data structure
by git standards, especially when the index is already populated.
Instead, we implement "git add $pathspec..." as:
- read the index;
- read_directory() to process untracked, unignored files the current
way, that is, recursively doing readdir(), filtering them by pathspec
and excluded(), queueing them via dir_add_name() and finally do
add_files(); and
- iterate over the index, filtering them by pathspec, and update only
the modified/type changed paths but not deleted ones.
And "git add -A" becomes exactly the same as above, modulo:
- missing $pathspec means "." instead of being an error; and
- "iterate over the index" part handles deleted ones as well,
i.e. exactly what the current update_callback() in builtin-add.c does.
In either case, because fill_directory() does not use read_directory() to
read everything in, we need to add an extra logic to iterate over the
index to catch mistyped pathspec.
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2008-07-23 13:30:40 +08:00
|
|
|
/* This picks up the paths that are not tracked */
|
2017-05-06 03:53:34 +08:00
|
|
|
baselen = fill_directory(&dir, &the_index, &pathspec);
|
2013-07-14 16:35:46 +08:00
|
|
|
if (pathspec.nr)
|
2014-03-08 07:14:01 +08:00
|
|
|
seen = prune_directory(&dir, &pathspec, baselen);
|
2009-05-15 04:22:36 +08:00
|
|
|
}
|
builtin-add.c: optimize -A option and "git add ."
The earlier "git add -A" change was done in a quite inefficient
way (i.e. it is as unefficient as "git add -u && git add ." modulo
one fork/exec and read/write index).
When the user asks "git add .", we do not have to examine all paths
we encounter and perform the excluded() and dir_add_name()
processing, both of which are slower code and use slower data structure
by git standards, especially when the index is already populated.
Instead, we implement "git add $pathspec..." as:
- read the index;
- read_directory() to process untracked, unignored files the current
way, that is, recursively doing readdir(), filtering them by pathspec
and excluded(), queueing them via dir_add_name() and finally do
add_files(); and
- iterate over the index, filtering them by pathspec, and update only
the modified/type changed paths but not deleted ones.
And "git add -A" becomes exactly the same as above, modulo:
- missing $pathspec means "." instead of being an error; and
- "iterate over the index" part handles deleted ones as well,
i.e. exactly what the current update_callback() in builtin-add.c does.
In either case, because fill_directory() does not use read_directory() to
read everything in, we need to add an extra logic to iterate over the
index to catch mistyped pathspec.
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2008-07-23 13:30:40 +08:00
|
|
|
|
2008-07-20 10:22:25 +08:00
|
|
|
if (refresh_only) {
|
2021-04-09 04:41:27 +08:00
|
|
|
exit_status |= refresh(verbose, &pathspec);
|
2008-07-20 10:22:25 +08:00
|
|
|
goto finish;
|
2006-12-26 09:46:38 +08:00
|
|
|
}
|
|
|
|
|
2013-07-14 16:35:46 +08:00
|
|
|
if (pathspec.nr) {
|
2010-02-10 06:30:49 +08:00
|
|
|
int i;
|
2021-04-09 04:41:27 +08:00
|
|
|
char *skip_worktree_seen = NULL;
|
|
|
|
struct string_list only_match_skip_worktree = STRING_LIST_INIT_NODUP;
|
2012-06-06 12:44:22 +08:00
|
|
|
|
2010-02-10 06:30:49 +08:00
|
|
|
if (!seen)
|
2021-04-09 04:41:25 +08:00
|
|
|
seen = find_pathspecs_matching_against_index(&pathspec,
|
2021-04-09 04:41:27 +08:00
|
|
|
&the_index, PS_IGNORE_SKIP_WORKTREE);
|
2013-07-14 16:35:46 +08:00
|
|
|
|
|
|
|
/*
|
|
|
|
* file_exists() assumes exact match
|
|
|
|
*/
|
2013-07-14 16:36:08 +08:00
|
|
|
GUARD_PATHSPEC(&pathspec,
|
|
|
|
PATHSPEC_FROMTOP |
|
|
|
|
PATHSPEC_LITERAL |
|
2013-07-14 16:36:09 +08:00
|
|
|
PATHSPEC_GLOB |
|
2013-12-06 15:30:48 +08:00
|
|
|
PATHSPEC_ICASE |
|
|
|
|
PATHSPEC_EXCLUDE);
|
2013-07-14 16:35:46 +08:00
|
|
|
|
2013-07-14 16:36:00 +08:00
|
|
|
for (i = 0; i < pathspec.nr; i++) {
|
|
|
|
const char *path = pathspec.items[i].match;
|
2021-04-09 04:41:27 +08:00
|
|
|
|
2013-12-06 15:30:48 +08:00
|
|
|
if (pathspec.items[i].magic & PATHSPEC_EXCLUDE)
|
|
|
|
continue;
|
2021-04-09 04:41:27 +08:00
|
|
|
if (seen[i])
|
|
|
|
continue;
|
|
|
|
|
2021-09-24 23:39:08 +08:00
|
|
|
if (!include_sparse &&
|
|
|
|
matches_skip_worktree(&pathspec, i, &skip_worktree_seen)) {
|
2021-04-09 04:41:27 +08:00
|
|
|
string_list_append(&only_match_skip_worktree,
|
|
|
|
pathspec.items[i].original);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Don't complain at 'git add .' on empty repo */
|
|
|
|
if (!path[0])
|
|
|
|
continue;
|
|
|
|
|
|
|
|
if ((pathspec.items[i].magic & (PATHSPEC_GLOB | PATHSPEC_ICASE)) ||
|
|
|
|
!file_exists(path)) {
|
2010-07-10 06:18:38 +08:00
|
|
|
if (ignore_missing) {
|
2010-11-11 21:03:22 +08:00
|
|
|
int dtype = DT_UNKNOWN;
|
2017-05-06 03:53:30 +08:00
|
|
|
if (is_excluded(&dir, &the_index, path, &dtype))
|
2017-05-06 03:53:25 +08:00
|
|
|
dir_add_ignored(&dir, &the_index,
|
|
|
|
path, pathspec.items[i].len);
|
2010-07-10 06:18:38 +08:00
|
|
|
} else
|
2011-02-23 07:41:31 +08:00
|
|
|
die(_("pathspec '%s' did not match any files"),
|
2013-07-14 16:36:00 +08:00
|
|
|
pathspec.items[i].original);
|
2010-07-10 06:18:38 +08:00
|
|
|
}
|
2010-02-10 06:30:49 +08:00
|
|
|
}
|
2021-04-09 04:41:27 +08:00
|
|
|
|
|
|
|
|
|
|
|
if (only_match_skip_worktree.nr) {
|
|
|
|
advise_on_updating_sparse_paths(&only_match_skip_worktree);
|
|
|
|
exit_status = 1;
|
|
|
|
}
|
|
|
|
|
2010-02-10 06:30:49 +08:00
|
|
|
free(seen);
|
2021-04-09 04:41:27 +08:00
|
|
|
free(skip_worktree_seen);
|
|
|
|
string_list_clear(&only_match_skip_worktree, 0);
|
2010-02-10 06:30:49 +08:00
|
|
|
}
|
|
|
|
|
2022-04-05 13:20:08 +08:00
|
|
|
begin_odb_transaction();
|
2011-10-29 05:48:40 +08:00
|
|
|
|
2017-11-17 00:38:28 +08:00
|
|
|
if (add_renormalize)
|
|
|
|
exit_status |= renormalize_tracked_files(&pathspec, flags);
|
|
|
|
else
|
2023-05-16 14:33:46 +08:00
|
|
|
exit_status |= add_files_to_cache(the_repository, prefix,
|
|
|
|
&pathspec, include_sparse,
|
|
|
|
flags);
|
2008-07-20 10:22:25 +08:00
|
|
|
|
|
|
|
if (add_new_files)
|
2016-09-15 05:07:47 +08:00
|
|
|
exit_status |= add_files(&dir, flags);
|
2006-05-18 00:33:32 +08:00
|
|
|
|
2016-09-15 05:07:47 +08:00
|
|
|
if (chmod_arg && pathspec.nr)
|
2021-02-23 09:10:35 +08:00
|
|
|
exit_status |= chmod_pathspec(&pathspec, chmod_arg[0], show_only);
|
2022-04-05 13:20:08 +08:00
|
|
|
end_odb_transaction();
|
2011-10-29 05:48:40 +08:00
|
|
|
|
2013-08-31 05:56:49 +08:00
|
|
|
finish:
|
2018-03-02 04:40:20 +08:00
|
|
|
if (write_locked_index(&the_index, &lock_file,
|
|
|
|
COMMIT_LOCK | SKIP_IF_UNCHANGED))
|
|
|
|
die(_("Unable to write new index file"));
|
2006-05-18 00:33:32 +08:00
|
|
|
|
dir: fix problematic API to avoid memory leaks
The dir structure seemed to have a number of leaks and problems around
it. First I noticed that parent_hashmap and recursive_hashmap were
being leaked (though Peff noticed and submitted fixes before me). Then
I noticed in the previous commit that clear_directory() was only taking
responsibility for a subset of fields within dir_struct, despite the
fact that entries[] and ignored[] we allocated internally to dir.c.
That, of course, resulted in many callers either leaking or haphazardly
trying to free these arrays and their contents.
Digging further, I found that despite the pretty clear documentation
near the top of dir.h that folks were supposed to call clear_directory()
when the user no longer needed the dir_struct, there were four callers
that didn't bother doing that at all. However, two of them clearly
thought about leaks since they had an UNLEAK(dir) directive, which to me
suggests that the method to free the data was too unclear. I suspect
the non-obviousness of the API and its holes led folks to avoid it,
which then snowballed into further problems with the entries[],
ignored[], parent_hashmap, and recursive_hashmap problems.
Rename clear_directory() to dir_clear() to be more in line with other
data structures in git, and introduce a dir_init() to handle the
suggested memsetting of dir_struct to all zeroes. I hope that a name
like "dir_clear()" is more clear, and that the presence of dir_init()
will provide a hint to those looking at the code that they need to look
for either a dir_clear() or a dir_free() and lead them to find
dir_clear().
Signed-off-by: Elijah Newren <newren@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2020-08-19 06:58:26 +08:00
|
|
|
dir_clear(&dir);
|
built-ins: use free() not UNLEAK() if trivial, rm dead code
For a lot of uses of UNLEAK() it would be quite tricky to release the
memory involved, or we're missing the relevant *_(release|clear)()
functions. But in these cases we have them already, and can just
invoke them on the variable(s) involved, instead of UNLEAK().
For "builtin/worktree.c" the UNLEAK() was also added in [1], but the
struct member it's unleaking was removed in [2]. The only non-"int"
member of that structure is "const char *keep_locked", which comes to
us via "argv" or a string literal[3].
We have good visibility via the compiler and
tooling (e.g. SANITIZE=address) on bad free()-ing, but none on
UNLEAK() we don't need anymore. So let's prefer releasing the memory
when it's easy.
For "bugreport", "worktree" and "config" we need to start using a "ret
= ..." return pattern. For "builtin/bugreport.c" these UNLEAK() were
added in [4], and for "builtin/config.c" in [1].
For "config" the code seen here was the only user of the "value"
variable. For "ACTION_{RENAME,REMOVE}_SECTION" we need to be sure to
return the right exit code in the cases where we were relying on
falling through to the top-level.
I think there's still a use-case for UNLEAK(), but hat it's changed
since then. Using it so that "we can see the real leaks" is
counter-productive in these cases.
It's more useful to have UNLEAK() be a marker of the remaining odd
cases where it's hard to free() the memory for whatever reason. With
this change less than 20 of them remain in-tree.
1. 0e5bba53af7 (add UNLEAK annotation for reducing leak false
positives, 2017-09-08)
2. d861d34a6ed (worktree: remove extra members from struct add_opts,
2018-04-24)
3. 0db4961c49b (worktree: teach `add` to accept --reason <string> with
--lock, 2021-07-15)
4. 0e5bba53af7 and 00d8c311050 (commit: fix "author_ident" leak,
2022-05-12).
Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
Signed-off-by: Taylor Blau <me@ttaylorr.com>
2022-11-09 02:17:51 +08:00
|
|
|
clear_pathspec(&pathspec);
|
2008-05-13 01:58:10 +08:00
|
|
|
return exit_status;
|
2006-05-18 00:33:32 +08:00
|
|
|
}
|