#include "csum-file.h"
#include "promisor-remote.h"
#include "hook.h"
+#include "submodule.h"
+#include "submodule-config.h"
+#include "advice.h"
/* Mask for the name length in ce_flags in the on-disk index */
return DIFF_STATUS_MODIFIED;
}
+static int skip_submodule(const char *path,
+ struct repository *repo,
+ struct pathspec *pathspec,
+ int ignored_too)
+{
+ struct stat st;
+ const struct submodule *sub;
+ int pathspec_matches = 0;
+ int ps_i;
+ char *norm_pathspec = NULL;
+
+ /* Only consider if path is a directory */
+ if (lstat(path, &st) || !S_ISDIR(st.st_mode))
+ return 0;
+
+ /* Check if it's a submodule with ignore=all */
+ sub = submodule_from_path(repo, null_oid(the_hash_algo), path);
+ if (!sub || !sub->name || !sub->ignore || strcmp(sub->ignore, "all"))
+ return 0;
+
+ trace_printf("ignore=all: %s\n", path);
+ trace_printf("pathspec %s\n", (pathspec && pathspec->nr)
+ ? "has pathspec"
+ : "no pathspec");
+
+ /* Check if submodule path is explicitly mentioned in pathspec */
+ if (pathspec) {
+ for (ps_i = 0; ps_i < pathspec->nr; ps_i++) {
+ const char *m = pathspec->items[ps_i].match;
+ if (!m)
+ continue;
+ norm_pathspec = xstrdup(m);
+ strip_dir_trailing_slashes(norm_pathspec);
+ if (!strcmp(path, norm_pathspec)) {
+ pathspec_matches = 1;
+ FREE_AND_NULL(norm_pathspec);
+ break;
+ }
+ FREE_AND_NULL(norm_pathspec);
+ }
+ }
+
+ /* If explicitly matched and forced, allow adding */
+ if (pathspec_matches) {
+ if (ignored_too && ignored_too > 0) {
+ trace_printf("Add submodule due to --force: %s\n", path);
+ return 0;
+ } else {
+ advise_if_enabled(ADVICE_ADD_IGNORED_FILE,
+ _("Skipping submodule due to ignore=all: %s\n"
+ "Use --force if you really want to add the submodule."), path);
+ return 1;
+ }
+ }
+
+ /* No explicit pathspec match -> skip silently */
+ trace_printf("Pathspec to submodule does not match explicitly: %s\n", path);
+ return 1;
+}
+
static void update_callback(struct diff_queue_struct *q,
- struct diff_options *opt UNUSED, void *cbdata)
+ struct diff_options *opt UNUSED, void *cbdata)
{
int i;
struct update_callback_data *data = cbdata;
const char *path = p->one->path;
if (!data->include_sparse &&
- !path_in_sparse_checkout(path, data->index))
+ !path_in_sparse_checkout(path, data->index))
continue;
switch (fix_unmerged_status(p, data)) {
default:
die(_("unexpected diff status %c"), p->status);
case DIFF_STATUS_MODIFIED:
- case DIFF_STATUS_TYPE_CHANGED: {
+ case DIFF_STATUS_TYPE_CHANGED:
+ if (skip_submodule(path, data->repo,
+ data->pathspec,
+ data->ignored_too))
+ continue;
+
if (add_file_to_index(data->index, path, data->flags)) {
if (!(data->flags & ADD_CACHE_IGNORE_ERRORS))
die(_("updating files failed"));