[PATCH 075/194] fetch, push: do not use submodule as alternate in has_commits check

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Both fetch and push still use alternates to access submodules in some
other code paths, but this is progress towards eliminating the alternates
hack that conflates access to the_repository and other repositories.

Signed-off-by: Jonathan Nieder <jrnieder@xxxxxxxxx>
Signed-off-by: Stefan Beller <sbeller@xxxxxxxxxx>
---
 submodule.c | 52 ++++++++++++++++++++++++++++++++++++++--------------
 1 file changed, 38 insertions(+), 14 deletions(-)

diff --git a/submodule.c b/submodule.c
index dc57c176e8..1504812842 100644
--- a/submodule.c
+++ b/submodule.c
@@ -811,14 +811,15 @@ static int append_oid_to_argv(const struct object_id *oid, void *data)
 
 struct has_commit_data {
 	int result;
-	const char *path;
+	struct repository *repo;
 };
 
 static int check_has_commit(const struct object_id *oid, void *data)
 {
 	struct has_commit_data *cb = data;
+	struct repository *r = cb->repo;
 
-	enum object_type type = sha1_object_info(the_repository, oid->hash, NULL);
+	enum object_type type = sha1_object_info(r, oid->hash, NULL);
 
 	switch (type) {
 	case OBJ_COMMIT:
@@ -832,24 +833,43 @@ static int check_has_commit(const struct object_id *oid, void *data)
 		return 0;
 	default:
 		die(_("submodule entry '%s' (%s) is a %s, not a commit"),
-		    cb->path, oid_to_hex(oid), typename(type));
+		    r->submodule_prefix, oid_to_hex(oid), typename(type));
 	}
 }
 
+/*
+ * Initialize 'out' based on the provided submodule path.
+ *
+ * Unlike repo_submodule_init, this tolerates submodules not present
+ * in .gitmodules. NEEDSWORK: The repo_submodule_init behavior is
+ * preferrable. This function exists only to preserve historical behavior.
+ *
+ * Returns 0 on success, -1 when the submodule is not present.
+ */
+static int open_submodule(struct repository *out, const char *path)
+{
+	struct strbuf sb = STRBUF_INIT;
+
+	if (submodule_to_gitdir(&sb, path))
+		return -1;
+
+	if (repo_init(out, sb.buf, NULL)) {
+		strbuf_release(&sb);
+		return -1;
+	}
+
+	out->submodule_prefix = xstrdup(path);
+
+	strbuf_release(&sb);
+	return 0;
+}
+
 static int submodule_has_commits(const char *path, struct oid_array *commits)
 {
-	struct has_commit_data has_commit = { 1, path };
+	struct repository sub;
+	struct has_commit_data has_commit = { 1, &sub };
 
-	/*
-	 * Perform a cheap, but incorrect check for the existence of 'commits'.
-	 * This is done by adding the submodule's object store to the in-core
-	 * object store, and then querying for each commit's existence.  If we
-	 * do not have the commit object anywhere, there is no chance we have
-	 * it in the object store of the correct submodule and have it
-	 * reachable from a ref, so we can fail early without spawning rev-list
-	 * which is expensive.
-	 */
-	if (add_submodule_odb(path))
+	if (open_submodule(&sub, path))
 		return 0;
 
 	oid_array_for_each_unique(commits, check_has_commit, &has_commit);
@@ -878,6 +898,7 @@ static int submodule_has_commits(const char *path, struct oid_array *commits)
 		strbuf_release(&out);
 	}
 
+	repo_clear(&sub);
 	return has_commit.result;
 }
 
@@ -897,6 +918,9 @@ static int submodule_needs_pushing(const char *path, struct oid_array *commits)
 		 */
 		return 0;
 
+	/* The submodule odb is needed for access to its refs. */
+	if (add_submodule_odb(path))
+		BUG("submodule '%s' is both present and absent", path);
 	if (for_each_remote_ref_submodule(path, has_remote, NULL) > 0) {
 		struct child_process cp = CHILD_PROCESS_INIT;
 		struct strbuf buf = STRBUF_INIT;
-- 
2.15.1.433.g936d1b9894.dirty




[Index of Archives]     [Linux Kernel Development]     [Gcc Help]     [IETF Annouce]     [DCCP]     [Netdev]     [Networking]     [Security]     [V4L]     [Bugtraq]     [Yosemite]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux SCSI]     [Fedora Users]

  Powered by Linux