summaryrefslogtreecommitdiff
path: root/builtin/add.c
diff options
context:
space:
mode:
Diffstat (limited to 'builtin/add.c')
-rw-r--r--builtin/add.c60
1 files changed, 44 insertions, 16 deletions
diff --git a/builtin/add.c b/builtin/add.c
index b773b5a499..ef6b619c45 100644
--- a/builtin/add.c
+++ b/builtin/add.c
@@ -30,6 +30,7 @@ static int patch_interactive, add_interactive, edit_interactive;
static int take_worktree_changes;
static int add_renormalize;
static int pathspec_file_nul;
+static int include_sparse;
static const char *pathspec_from_file;
static int legacy_stash_p; /* support for the scripted `git stash` */
@@ -46,7 +47,9 @@ static int chmod_pathspec(struct pathspec *pathspec, char flip, int show_only)
struct cache_entry *ce = active_cache[i];
int err;
- if (ce_skip_worktree(ce))
+ if (!include_sparse &&
+ (ce_skip_worktree(ce) ||
+ !path_in_sparse_checkout(ce->name, &the_index)))
continue;
if (pathspec && !ce_path_match(&the_index, ce, pathspec, NULL))
@@ -94,6 +97,10 @@ static void update_callback(struct diff_queue_struct *q,
for (i = 0; i < q->nr; i++) {
struct diff_filepair *p = q->queue[i];
const char *path = p->one->path;
+
+ if (!include_sparse && !path_in_sparse_checkout(path, &the_index))
+ continue;
+
switch (fix_unmerged_status(p, data)) {
default:
die(_("unexpected diff status %c"), p->status);
@@ -144,12 +151,12 @@ static int renormalize_tracked_files(const struct pathspec *pathspec, int flags)
{
int i, retval = 0;
- /* TODO: audit for interaction with sparse-index. */
- ensure_full_index(&the_index);
for (i = 0; i < active_nr; i++) {
struct cache_entry *ce = active_cache[i];
- if (ce_skip_worktree(ce))
+ if (!include_sparse &&
+ (ce_skip_worktree(ce) ||
+ !path_in_sparse_checkout(ce->name, &the_index)))
continue;
if (ce_stage(ce))
continue; /* do not touch unmerged paths */
@@ -198,7 +205,10 @@ static int refresh(int verbose, const struct pathspec *pathspec)
_("Unstaged changes after refreshing the index:"));
for (i = 0; i < pathspec->nr; i++) {
if (!seen[i]) {
- if (matches_skip_worktree(pathspec, i, &skip_worktree_seen)) {
+ const char *path = pathspec->items[i].original;
+
+ if (matches_skip_worktree(pathspec, i, &skip_worktree_seen) ||
+ !path_in_sparse_checkout(path, &the_index)) {
string_list_append(&only_match_skip_worktree,
pathspec->items[i].original);
} else {
@@ -313,9 +323,7 @@ static int edit_patch(int argc, const char **argv, const char *prefix)
rev.diffopt.output_format = DIFF_FORMAT_PATCH;
rev.diffopt.use_color = 0;
rev.diffopt.flags.ignore_dirty_submodules = 1;
- out = open(file, O_CREAT | O_WRONLY | O_TRUNC, 0666);
- if (out < 0)
- die(_("Could not open '%s' for writing."), file);
+ out = xopen(file, O_CREAT | O_WRONLY | O_TRUNC, 0666);
rev.diffopt.file = xfdopen(out, "w");
rev.diffopt.close_file = 1;
if (run_diff_files(&rev, 0))
@@ -378,6 +386,7 @@ static struct option builtin_add_options[] = {
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")),
+ OPT_BOOL(0, "sparse", &include_sparse, N_("allow updating entries outside of the sparse-checkout cone")),
OPT_STRING(0, "chmod", &chmod_arg, "(+|-)x",
N_("override the executable bit of the listed files")),
OPT_HIDDEN_BOOL(0, "warn-embedded-repo", &warn_on_embedded_repo,
@@ -419,6 +428,7 @@ static const char embedded_advice[] = N_(
static void check_embedded_repo(const char *path)
{
struct strbuf name = STRBUF_INIT;
+ static int adviced_on_embedded_repo = 0;
if (!warn_on_embedded_repo)
return;
@@ -430,10 +440,10 @@ static void check_embedded_repo(const char *path)
strbuf_strip_suffix(&name, "/");
warning(_("adding embedded git repository: %s"), name.buf);
- if (advice_add_embedded_repo) {
+ if (!adviced_on_embedded_repo &&
+ advice_enabled(ADVICE_ADD_EMBEDDED_REPO)) {
advise(embedded_advice, name.buf, name.buf);
- /* there may be multiple entries; advise only once */
- advice_add_embedded_repo = 0;
+ adviced_on_embedded_repo = 1;
}
strbuf_release(&name);
@@ -442,12 +452,13 @@ static void check_embedded_repo(const char *path)
static int add_files(struct dir_struct *dir, int flags)
{
int i, exit_status = 0;
+ struct string_list matched_sparse_paths = STRING_LIST_INIT_NODUP;
if (dir->ignored_nr) {
fprintf(stderr, _(ignore_error));
for (i = 0; i < dir->ignored_nr; i++)
fprintf(stderr, "%s\n", dir->ignored[i]->name);
- if (advice_add_ignored_file)
+ if (advice_enabled(ADVICE_ADD_IGNORED_FILE))
advise(_("Use -f if you really want to add them.\n"
"Turn this message off by running\n"
"\"git config advice.addIgnoredFile false\""));
@@ -455,6 +466,12 @@ static int add_files(struct dir_struct *dir, int flags)
}
for (i = 0; i < dir->nr; i++) {
+ if (!include_sparse &&
+ !path_in_sparse_checkout(dir->entries[i]->name, &the_index)) {
+ string_list_append(&matched_sparse_paths,
+ dir->entries[i]->name);
+ continue;
+ }
if (add_file_to_index(&the_index, dir->entries[i]->name, flags)) {
if (!ignore_add_errors)
die(_("adding files failed"));
@@ -463,6 +480,14 @@ static int add_files(struct dir_struct *dir, int flags)
check_embedded_repo(dir->entries[i]->name);
}
}
+
+ if (matched_sparse_paths.nr) {
+ advise_on_updating_sparse_paths(&matched_sparse_paths);
+ exit_status = 1;
+ }
+
+ string_list_clear(&matched_sparse_paths, 0);
+
return exit_status;
}
@@ -470,7 +495,7 @@ int cmd_add(int argc, const char **argv, const char *prefix)
{
int exit_status = 0;
struct pathspec pathspec;
- struct dir_struct dir;
+ struct dir_struct dir = DIR_INIT;
int flags;
int add_new_files;
int require_pathspec;
@@ -528,6 +553,9 @@ int cmd_add(int argc, const char **argv, const char *prefix)
add_new_files = !take_worktree_changes && !refresh_only && !add_renormalize;
require_pathspec = !(take_worktree_changes || (0 < addremove_explicit));
+ prepare_repo_settings(the_repository);
+ the_repository->settings.command_requires_full_index = 0;
+
hold_locked_index(&lock_file, LOCK_DIE_ON_ERROR);
/*
@@ -553,7 +581,7 @@ int cmd_add(int argc, const char **argv, const char *prefix)
if (require_pathspec && pathspec.nr == 0) {
fprintf(stderr, _("Nothing specified, nothing added.\n"));
- if (advice_add_empty_pathspec)
+ if (advice_enabled(ADVICE_ADD_EMPTY_PATHSPEC))
advise( _("Maybe you wanted to say 'git add .'?\n"
"Turn this message off by running\n"
"\"git config advice.addEmptyPathspec false\""));
@@ -577,7 +605,6 @@ int cmd_add(int argc, const char **argv, const char *prefix)
die_in_unpopulated_submodule(&the_index, prefix);
die_path_inside_submodule(&the_index, &pathspec);
- dir_init(&dir);
if (add_new_files) {
int baselen;
@@ -625,7 +652,8 @@ int cmd_add(int argc, const char **argv, const char *prefix)
if (seen[i])
continue;
- if (matches_skip_worktree(&pathspec, i, &skip_worktree_seen)) {
+ if (!include_sparse &&
+ matches_skip_worktree(&pathspec, i, &skip_worktree_seen)) {
string_list_append(&only_match_skip_worktree,
pathspec.items[i].original);
continue;