git.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Lars Hjemli <hjemli@gmail.com>
To: Junio C Hamano <gitster@pobox.com>
Cc: git@vger.kernel.org
Subject: [PATCH 2/3] Teach read_tree_recursive() how to traverse into submodules
Date: Sun, 18 Jan 2009 11:53:18 +0100	[thread overview]
Message-ID: <1232275999-14852-3-git-send-email-hjemli@gmail.com> (raw)
In-Reply-To: <1232275999-14852-2-git-send-email-hjemli@gmail.com>

The traversal of submodules is only triggered if the current submodule
HEAD commit object is accessible. To this end, read_tree_recursive()
will try to insert the submodule odb as an alternate odb but the lack
of such an odb is not treated as an error since it is then assumed that
the user is not interested in the submodule content. However, if the
submodule odb is found it is treated as an error if the HEAD commit
object is missing.

Signed-off-by: Lars Hjemli <hjemli@gmail.com>
---
 cache.h       |    2 +
 environment.c |   12 ++++++++
 tree.c        |   80 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 94 insertions(+), 0 deletions(-)

diff --git a/cache.h b/cache.h
index daa2d4e..6728467 100644
--- a/cache.h
+++ b/cache.h
@@ -382,6 +382,8 @@ extern int set_git_dir(const char *path);
 extern const char *get_git_work_tree(void);
 extern const char *read_gitfile_gently(const char *path);
 extern void set_git_work_tree(const char *tree);
+extern int get_traverse_gitlinks();
+extern void set_traverse_gitlinks(int traverse);
 
 #define ALTERNATE_DB_ENVIRONMENT "GIT_ALTERNATE_OBJECT_DIRECTORIES"
 
diff --git a/environment.c b/environment.c
index e278bce..35cc557 100644
--- a/environment.c
+++ b/environment.c
@@ -53,6 +53,8 @@ static char *work_tree;
 static const char *git_dir;
 static char *git_object_dir, *git_index_file, *git_refs_dir, *git_graft_file;
 
+static int traverse_gitlinks = 0;
+
 static void setup_git_env(void)
 {
 	git_dir = getenv(GIT_DIR_ENVIRONMENT);
@@ -159,3 +161,13 @@ int set_git_dir(const char *path)
 	setup_git_env();
 	return 0;
 }
+
+int get_traverse_gitlinks()
+{
+	return traverse_gitlinks;
+}
+
+void set_traverse_gitlinks(int traverse)
+{
+	traverse_gitlinks = traverse;
+}
diff --git a/tree.c b/tree.c
index 03e782a..87cf309 100644
--- a/tree.c
+++ b/tree.c
@@ -5,6 +5,7 @@
 #include "commit.h"
 #include "tag.h"
 #include "tree-walk.h"
+#include "refs.h"
 
 const char *tree_type = "tree";
 
@@ -89,6 +90,61 @@ static int match_tree_entry(const char *base, int baselen, const char *path, uns
 	return 0;
 }
 
+/* Try to add the objectdb of a submodule */
+int add_gitlink_odb(char *relpath)
+{
+	const char *odbpath;
+	struct stat st;
+
+	odbpath = read_gitfile_gently(mkpath("%s/.git", relpath));
+	if (!odbpath)
+		odbpath = mkpath("%s/.git/objects", relpath);
+
+	if (stat(odbpath, &st))
+		return 1;
+
+	return add_alt_odb(odbpath);
+}
+
+/* Check if we should recurse into the specified submodule */
+int traverse_gitlink(char *path, const unsigned char *commit_sha1,
+		     struct tree **subtree)
+{
+	unsigned char sha1[20];
+	int linked_odb = 0;
+	struct commit *commit;
+	void *buffer;
+	enum object_type type;
+	unsigned long size;
+
+	hashcpy(sha1, commit_sha1);
+	if (!add_gitlink_odb(path)) {
+		linked_odb = 1;
+		if (resolve_gitlink_ref(path, "HEAD", sha1))
+			die("Unable to lookup HEAD in %s", path);
+	}
+
+	buffer = read_sha1_file(sha1, &type, &size);
+	if (!buffer) {
+		if (linked_odb)
+			die("Unable to read object %s in submodule %s",
+			    sha1_to_hex(sha1), path);
+		else
+			return 0;
+	}
+
+	commit = lookup_commit(sha1);
+	if (!commit)
+		die("traverse_gitlink(): internal error");
+
+	if (parse_commit_buffer(commit, buffer, size))
+		die("Failed to parse commit %s in submodule %s",
+		    sha1_to_hex(sha1), path);
+
+	*subtree = commit->tree;
+	return 1;
+}
+
 int read_tree_recursive(struct tree *tree,
 			const char *base, int baselen,
 			int stage, const char **match,
@@ -132,6 +188,30 @@ int read_tree_recursive(struct tree *tree,
 				return -1;
 			continue;
 		}
+		if (S_ISGITLINK(entry.mode) && get_traverse_gitlinks()) {
+			int retval;
+			char *newbase;
+			struct tree *subtree;
+			unsigned int pathlen = tree_entry_len(entry.path, entry.sha1);
+
+			newbase = xmalloc(baselen + 1 + pathlen);
+			memcpy(newbase, base, baselen);
+			memcpy(newbase + baselen, entry.path, pathlen);
+			newbase[baselen + pathlen] = 0;
+			if (!traverse_gitlink(newbase, entry.sha1, &subtree)) {
+				free(newbase);
+				continue;
+			}
+			newbase[baselen + pathlen] = '/';
+			retval = read_tree_recursive(subtree,
+						     newbase,
+						     baselen + pathlen + 1,
+						     stage, match, fn, context);
+			free(newbase);
+			if (retval)
+				return -1;
+			continue;
+		}
 	}
 	return 0;
 }
-- 
1.6.1.150.g5e733b

  reply	other threads:[~2009-01-18 10:55 UTC|newest]

Thread overview: 26+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2009-01-18 10:53 [PATCH 0/3] Implement 'git archive --submodules' Lars Hjemli
2009-01-18 10:53 ` [PATCH 1/3] sha1_file: add function to insert alternate object db Lars Hjemli
2009-01-18 10:53   ` Lars Hjemli [this message]
2009-01-18 10:53     ` [PATCH 3/3] git-archive: add support for --submodules Lars Hjemli
2009-01-18 15:51       ` Johannes Schindelin
2009-01-18 15:48     ` [PATCH 2/3] Teach read_tree_recursive() how to traverse into submodules Johannes Schindelin
2009-01-18 17:45       ` Lars Hjemli
2009-01-18 18:33         ` Johannes Schindelin
2009-01-18 19:45           ` Lars Hjemli
2009-01-18 21:02             ` Johannes Schindelin
2009-01-18 21:31               ` Lars Hjemli
2009-01-18 21:55                 ` Johannes Schindelin
2009-01-18 22:46                   ` Lars Hjemli
2009-01-19  1:24                     ` Johannes Schindelin
2009-01-19  2:01                       ` [PATCH/RFC v1 1/1] bug fix, diff whitespace ignore options Keith Cascio
2009-01-19  3:53                         ` Johannes Schindelin
2009-01-19 18:03                           ` [PATCH/RFC v2 " Keith Cascio
2009-01-19 18:36                             ` Johannes Schindelin
2009-01-20  7:04                             ` Junio C Hamano
2009-01-19  3:02         ` [PATCH 2/3] Teach read_tree_recursive() how to traverse into submodules Junio C Hamano
2009-01-18 16:13     ` René Scharfe
2009-01-18 16:37       ` Lars Hjemli
2009-01-18 19:00         ` Junio C Hamano
2009-01-18 19:50           ` Lars Hjemli
2009-01-18 15:32   ` [PATCH 1/3] sha1_file: add function to insert alternate object db Johannes Schindelin
2009-01-18 15:55     ` [PATCH] " Lars Hjemli

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1232275999-14852-3-git-send-email-hjemli@gmail.com \
    --to=hjemli@gmail.com \
    --cc=git@vger.kernel.org \
    --cc=gitster@pobox.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).