#include "cache.h"
+#include "alloc.h"
#include "dir.h"
+#include "environment.h"
+#include "gettext.h"
+#include "hex.h"
#include "repository.h"
#include "config.h"
#include "submodule-config.h"
#include "submodule.h"
#include "strbuf.h"
+#include "object-name.h"
#include "object-store.h"
#include "parse-options.h"
+#include "tree-walk.h"
/*
* submodule cache lookup structure
lookup_path
};
-static int config_path_cmp(const void *unused_cmp_data,
+static int config_path_cmp(const void *cmp_data UNUSED,
const struct hashmap_entry *eptr,
const struct hashmap_entry *entry_or_key,
- const void *unused_keydata)
+ const void *keydata UNUSED)
{
const struct submodule_entry *a, *b;
!oideq(&a->config->gitmodules_oid, &b->config->gitmodules_oid);
}
-static int config_name_cmp(const void *unused_cmp_data,
+static int config_name_cmp(const void *cmp_data UNUSED,
const struct hashmap_entry *eptr,
const struct hashmap_entry *entry_or_key,
- const void *unused_keydata)
+ const void *keydata UNUSED)
{
const struct submodule_entry *a, *b;
return -1;
/*
- * Look for '..' as a path component. Check both '/' and '\\' as
+ * Look for '..' as a path component. Check is_xplatform_dir_sep() as
* separators rather than is_dir_sep(), because we want the name rules
* to be consistent across platforms.
*/
goto in_component; /* always start inside component */
while (*name) {
char c = *name++;
- if (c == '/' || c == '\\') {
+ if (is_xplatform_dir_sep(c)) {
in_component:
if (name[0] == '.' && name[1] == '.' &&
- (!name[2] || name[2] == '/' || name[2] == '\\'))
+ (!name[2] || is_xplatform_dir_sep(name[2])))
return -1;
}
}
{
int fetchjobs = git_config_int(var, value);
if (fetchjobs < 0)
- die(_("negative values not allowed for submodule.fetchjobs"));
+ die(_("negative values not allowed for submodule.fetchJobs"));
+ if (!fetchjobs)
+ fetchjobs = online_cpus();
return fetchjobs;
}
else if (parse_submodule_update_strategy(value,
&submodule->update_strategy) < 0 ||
submodule->update_strategy.type == SM_UPDATE_COMMAND)
- die(_("invalid value for %s"), var);
+ die(_("invalid value for '%s'"), var);
} else if (!strcmp(item.buf, "shallow")) {
if (!me->overwrite && submodule->recommend_shallow != -1)
warn_multiple_config(me->treeish_name, submodule->name,
}
strbuf_addf(rev, "%s:.gitmodules", oid_to_hex(treeish_name));
- if (get_oid(rev->buf, gitmodules_oid) >= 0)
+ if (repo_get_oid(the_repository, rev->buf, gitmodules_oid) >= 0)
ret = 1;
return ret;
if (submodule)
goto out;
- config = read_object_file(&oid, &type, &config_size);
+ config = repo_read_object_file(the_repository, &oid, &type,
+ &config_size);
if (!config || type != OBJ_BLOB)
goto out;
return config_from(r->submodule_cache, treeish_name, path, lookup_path);
}
+/**
+ * Used internally by submodules_of_tree(). Recurses into 'treeish_name'
+ * and appends submodule entries to 'out'. The submodule_cache expects
+ * a root-level treeish_name and paths, so keep track of these values
+ * with 'root_tree' and 'prefix'.
+ */
+static void traverse_tree_submodules(struct repository *r,
+ const struct object_id *root_tree,
+ char *prefix,
+ const struct object_id *treeish_name,
+ struct submodule_entry_list *out)
+{
+ struct tree_desc tree;
+ struct submodule_tree_entry *st_entry;
+ struct name_entry *name_entry;
+ char *tree_path = NULL;
+
+ name_entry = xmalloc(sizeof(*name_entry));
+
+ fill_tree_descriptor(r, &tree, treeish_name);
+ while (tree_entry(&tree, name_entry)) {
+ if (prefix)
+ tree_path =
+ mkpathdup("%s/%s", prefix, name_entry->path);
+ else
+ tree_path = xstrdup(name_entry->path);
+
+ if (S_ISGITLINK(name_entry->mode) &&
+ is_tree_submodule_active(r, root_tree, tree_path)) {
+ ALLOC_GROW(out->entries, out->entry_nr + 1,
+ out->entry_alloc);
+ st_entry = &out->entries[out->entry_nr++];
+
+ st_entry->name_entry = xmalloc(sizeof(*st_entry->name_entry));
+ *st_entry->name_entry = *name_entry;
+ st_entry->submodule =
+ submodule_from_path(r, root_tree, tree_path);
+ st_entry->repo = xmalloc(sizeof(*st_entry->repo));
+ if (repo_submodule_init(st_entry->repo, r, tree_path,
+ root_tree))
+ FREE_AND_NULL(st_entry->repo);
+
+ } else if (S_ISDIR(name_entry->mode))
+ traverse_tree_submodules(r, root_tree, tree_path,
+ &name_entry->oid, out);
+ free(tree_path);
+ }
+}
+
+void submodules_of_tree(struct repository *r,
+ const struct object_id *treeish_name,
+ struct submodule_entry_list *out)
+{
+ CALLOC_ARRAY(out->entries, 0);
+ out->entry_nr = 0;
+ out->entry_alloc = 0;
+
+ traverse_tree_submodules(r, treeish_name, NULL, treeish_name, out);
+}
+
void submodule_free(struct repository *r)
{
if (r->submodule_cache)