if ((pos >= 0) && (pos < istate->cache_nr)) {
struct stat st;
if (lstat(GITMODULES_FILE, &st) == 0 &&
- ie_match_stat(istate, istate->cache[pos], &st,
- CE_MATCH_IGNORE_FSMONITOR) & DATA_CHANGED)
+ ie_match_stat(istate, istate->cache[pos], &st, 0) & DATA_CHANGED)
return 0;
}
{
struct commit_list *list;
- init_revisions(rev, NULL);
+ repo_init_revisions(the_repository, rev, NULL);
setup_revisions(0, NULL, rev, NULL);
rev->left_right = 1;
rev->first_parent_only = 1;
return prepare_revision_walk(rev);
}
-static void print_submodule_summary(struct rev_info *rev, struct diff_options *o)
+static void print_submodule_summary(struct repository *r, struct rev_info *rev, struct diff_options *o)
{
static const char format[] = " %m %s";
struct strbuf sb = STRBUF_INIT;
ctx.date_mode = rev->date_mode;
ctx.output_encoding = get_log_output_encoding();
strbuf_setlen(&sb, 0);
- format_commit_message(commit, format, &sb, &ctx);
+ repo_format_commit_message(r, commit, format, &sb,
+ &ctx);
strbuf_addch(&sb, '\n');
if (commit->object.flags & SYMMETRIC_LEFT)
diff_emit_submodule_del(o, sb.buf);
DEFAULT_GIT_DIR_ENVIRONMENT);
}
-/* Helper function to display the submodule header line prior to the full
- * summary output. If it can locate the submodule objects directory it will
- * attempt to lookup both the left and right commits and put them into the
- * left and right pointers.
+/*
+ * Initialize a repository struct for a submodule based on the provided 'path'.
+ *
+ * Unlike repo_submodule_init, this tolerates submodules not present
+ * in .gitmodules. This function exists only to preserve historical behavior,
+ *
+ * Returns the repository struct on success,
+ * NULL when the submodule is not present.
+ */
+static struct repository *open_submodule(const char *path)
+{
+ struct strbuf sb = STRBUF_INIT;
+ struct repository *out = xmalloc(sizeof(*out));
+
+ if (submodule_to_gitdir(&sb, path) || repo_init(out, sb.buf, NULL)) {
+ strbuf_release(&sb);
+ free(out);
+ return NULL;
+ }
+
+ /* Mark it as a submodule */
+ out->submodule_prefix = xstrdup(path);
+
+ strbuf_release(&sb);
+ return out;
+}
+
+/*
+ * Helper function to display the submodule header line prior to the full
+ * summary output.
+ *
+ * If it can locate the submodule git directory it will create a repository
+ * handle for the submodule and lookup both the left and right commits and
+ * put them into the left and right pointers.
*/
-static void show_submodule_header(struct diff_options *o, const char *path,
+static void show_submodule_header(struct diff_options *o,
+ const char *path,
struct object_id *one, struct object_id *two,
unsigned dirty_submodule,
+ struct repository *sub,
struct commit **left, struct commit **right,
struct commit_list **merge_bases)
{
else if (is_null_oid(two))
message = "(submodule deleted)";
- if (add_submodule_odb(path)) {
+ if (!sub) {
if (!message)
message = "(commits not present)";
goto output_header;
* Attempt to lookup the commit references, and determine if this is
* a fast forward or fast backwards update.
*/
- *left = lookup_commit_reference(the_repository, one);
- *right = lookup_commit_reference(the_repository, two);
+ *left = lookup_commit_reference(sub, one);
+ *right = lookup_commit_reference(sub, two);
/*
* Warn about missing commits in the submodule project, but only if
(!is_null_oid(two) && !*right))
message = "(commits not present)";
- *merge_bases = get_merge_bases(*left, *right);
+ *merge_bases = repo_get_merge_bases(sub, *left, *right);
if (*merge_bases) {
if ((*merge_bases)->item == *left)
fast_forward = 1;
fast_backward = 1;
}
- if (!oidcmp(one, two)) {
+ if (oideq(one, two)) {
strbuf_release(&sb);
return;
}
struct rev_info rev;
struct commit *left = NULL, *right = NULL;
struct commit_list *merge_bases = NULL;
+ struct repository *sub;
+ sub = open_submodule(path);
show_submodule_header(o, path, one, two, dirty_submodule,
- &left, &right, &merge_bases);
+ sub, &left, &right, &merge_bases);
/*
* If we don't have both a left and a right pointer, there is no
* reason to try and display a summary. The header line should contain
* all the information the user needs.
*/
- if (!left || !right)
+ if (!left || !right || !sub)
goto out;
/* Treat revision walker failure the same as missing commits */
goto out;
}
- print_submodule_summary(&rev, o);
+ print_submodule_summary(sub, &rev, o);
out:
if (merge_bases)
free_commit_list(merge_bases);
clear_commit_marks(left, ~0);
clear_commit_marks(right, ~0);
+ if (sub) {
+ repo_clear(sub);
+ free(sub);
+ }
}
void show_submodule_inline_diff(struct diff_options *o, const char *path,
struct commit_list *merge_bases = NULL;
struct child_process cp = CHILD_PROCESS_INIT;
struct strbuf sb = STRBUF_INIT;
+ struct repository *sub;
+ sub = open_submodule(path);
show_submodule_header(o, path, one, two, dirty_submodule,
- &left, &right, &merge_bases);
+ sub, &left, &right, &merge_bases);
/* We need a valid left and right commit to display a difference */
if (!(left || is_null_oid(one)) ||
clear_commit_marks(left, ~0);
if (right)
clear_commit_marks(right, ~0);
+ if (sub) {
+ repo_clear(sub);
+ free(sub);
+ }
}
int should_update_submodules(void)
* have a corresponding 'struct oid_array' (in the 'util' field) which lists
* what the submodule pointers were updated to during the change.
*/
-static void collect_changed_submodules(struct string_list *changed,
+static void collect_changed_submodules(struct index_state *istate,
+ struct string_list *changed,
struct argv_array *argv)
{
struct rev_info rev;
const struct commit *commit;
- init_revisions(&rev, NULL);
+ repo_init_revisions(the_repository, &rev, NULL);
setup_revisions(argv->argc, argv->argv, &rev, NULL);
if (prepare_revision_walk(&rev))
die("revision walk setup failed");
data.changed = changed;
data.commit_oid = &commit->object.oid;
- init_revisions(&diff_rev, NULL);
+ repo_init_revisions(the_repository, &diff_rev, NULL);
diff_rev.diffopt.output_format |= DIFF_FORMAT_CALLBACK;
diff_rev.diffopt.format_callback = collect_changed_submodules_cb;
diff_rev.diffopt.format_callback_data = &data;
return 0;
}
-int find_unpushed_submodules(struct oid_array *commits,
- const char *remotes_name, struct string_list *needs_pushing)
+int find_unpushed_submodules(struct index_state *istate,
+ struct oid_array *commits,
+ const char *remotes_name,
+ struct string_list *needs_pushing)
{
struct string_list submodules = STRING_LIST_INIT_DUP;
struct string_list_item *name;
argv_array_push(&argv, "--not");
argv_array_pushf(&argv, "--remotes=%s", remotes_name);
- collect_changed_submodules(&submodules, &argv);
+ collect_changed_submodules(istate, &submodules, &argv);
for_each_string_list_item(name, &submodules) {
struct oid_array *commits = name->util;
const struct string_list *push_options,
int dry_run)
{
- if (add_submodule_odb(path))
- return 1;
-
if (for_each_remote_ref_submodule(path, has_remote, NULL) > 0) {
struct child_process cp = CHILD_PROCESS_INIT;
argv_array_push(&cp.args, "push");
die("process for submodule '%s' failed", path);
}
-int push_unpushed_submodules(struct oid_array *commits,
+int push_unpushed_submodules(struct index_state *istate,
+ struct oid_array *commits,
const struct remote *remote,
const struct refspec *rs,
const struct string_list *push_options,
int i, ret = 1;
struct string_list needs_pushing = STRING_LIST_INIT_DUP;
- if (!find_unpushed_submodules(commits, remote->name, &needs_pushing))
+ if (!find_unpushed_submodules(istate, commits,
+ remote->name, &needs_pushing))
return 1;
/*
oid_array_append(&ref_tips_after_fetch, oid);
}
-static void calculate_changed_submodule_paths(void)
+static void calculate_changed_submodule_paths(struct index_state *istate)
{
struct argv_array argv = ARGV_ARRAY_INIT;
struct string_list changed_submodules = STRING_LIST_INIT_DUP;
* Collect all submodules (whether checked out or not) for which new
* commits have been recorded upstream in "changed_submodule_names".
*/
- collect_changed_submodules(&changed_submodules, &argv);
+ collect_changed_submodules(istate, &changed_submodules, &argv);
for_each_string_list_item(name, &changed_submodules) {
struct oid_array *commits = name->util;
initialized_fetch_ref_tips = 0;
}
-int submodule_touches_in_range(struct object_id *excl_oid,
+int submodule_touches_in_range(struct index_state *istate,
+ struct object_id *excl_oid,
struct object_id *incl_oid)
{
struct string_list subs = STRING_LIST_INIT_DUP;
argv_array_push(&args, oid_to_hex(excl_oid));
}
- collect_changed_submodules(&subs, &args);
+ collect_changed_submodules(istate, &subs, &args);
ret = subs.nr;
argv_array_clear(&args);
argv_array_push(&spf.args, "--recurse-submodules-default");
/* default value, "--submodule-prefix" and its value are added later */
- calculate_changed_submodule_paths();
+ calculate_changed_submodule_paths(r->index);
run_processes_parallel(max_parallel_jobs,
get_next_submodule,
fetch_start_failure,
* We're only interested in the name after the tab.
*/
super_sub = strchr(sb.buf, '\t') + 1;
- super_sub_len = sb.buf + sb.len - super_sub - 1;
+ super_sub_len = strlen(super_sub);
if (super_sub_len > cwd_len ||
strcmp(&cwd[cwd_len - super_sub_len], super_sub))