From: skimo@liacs.nl
To: git@vger.kernel.org, Junio C Hamano <junkio@cox.net>
Cc: Martin Waitz <tali@admingilde.org>, Alex Riesen <raa.lkml@gmail.com>
Subject: [PATCH 16/22] unpack-trees.c: optionally clone submodules for later checkout
Date: Thu, 24 May 2007 00:23:05 +0200 [thread overview]
Message-ID: <11799589931789-git-send-email-skimo@liacs.nl> (raw)
In-Reply-To: <11799589913153-git-send-email-skimo@liacs.nl>
From: Sven Verdoolaege <skimo@kotnet.org>
When the --submodules option is specified and a submodule
to be checked out is not available locally, git-checkout will
search for submodule.<submodule>.url options in the remote
configuration and clone each submodule using the first url that
it can use from the local site.
Signed-off-by: Sven Verdoolaege <skimo@kotnet.org>
---
Documentation/config.txt | 3 +
Makefile | 4 +-
submodules.c | 211 ++++++++++++++++++++++++++++++++++++++++++++++
submodules.h | 7 ++
unpack-trees.c | 50 +++++++++++
5 files changed, 273 insertions(+), 2 deletions(-)
create mode 100644 submodules.c
create mode 100644 submodules.h
diff --git a/Documentation/config.txt b/Documentation/config.txt
index 5045443..2a2e142 100644
--- a/Documentation/config.txt
+++ b/Documentation/config.txt
@@ -615,6 +615,9 @@ showbranch.default::
The default set of branches for gitlink:git-show-branch[1].
See gitlink:git-show-branch[1].
+submodule.<submodule>.url
+ The URL of a submodule. See gitlink:git-clone[1].
+
tar.umask::
By default, gitlink:git-tar-tree[1] sets file and directories modes
to 0666 or 0777. While this is both useful and acceptable for projects
diff --git a/Makefile b/Makefile
index 1fa1896..39bf2d4 100644
--- a/Makefile
+++ b/Makefile
@@ -298,7 +298,7 @@ LIB_H = \
run-command.h strbuf.h tag.h tree.h git-compat-util.h revision.h \
tree-walk.h log-tree.h dir.h path-list.h unpack-trees.h builtin.h \
utf8.h reflog-walk.h patch-ids.h attr.h decorate.h progress.h \
- mailmap.h remote.h
+ mailmap.h remote.h submodules.h
DIFF_OBJS = \
diff.o diff-lib.o diffcore-break.o diffcore-order.o \
@@ -321,7 +321,7 @@ LIB_OBJS = \
alloc.o merge-file.o path-list.o help.o unpack-trees.o $(DIFF_OBJS) \
color.o wt-status.o archive-zip.o archive-tar.o shallow.o utf8.o \
convert.o attr.o decorate.o progress.o mailmap.o symlinks.o remote.o \
- $(HTTP_CONFIG_OBJ)
+ $(HTTP_CONFIG_OBJ) submodules.o
BUILTIN_OBJS = \
builtin-add.o \
diff --git a/submodules.c b/submodules.c
new file mode 100644
index 0000000..44c0f2c
--- /dev/null
+++ b/submodules.c
@@ -0,0 +1,211 @@
+#include "cache.h"
+#include "refs.h"
+#include "submodules.h"
+#include "run-command.h"
+
+int is_checkedout_submodule(const char *path)
+{
+ unsigned char sha1[20];
+ return resolve_gitlink_ref(path, "HEAD", sha1) == 0;
+}
+
+struct key_val_list {
+ struct key_val_list *next;
+ char *key;
+ char *val;
+};
+
+static void free_key_val_list(struct key_val_list *list)
+{
+ struct key_val_list *next;
+ for (; list; list = next) {
+ next = list->next;
+ free(list->key);
+ free(list->val);
+ free(list);
+ }
+}
+
+static struct key_val_list *find_key_val_list(struct key_val_list *list,
+ const char *key)
+{
+ while (list && strcmp(list->key, key))
+ list = list->next;
+ return list;
+}
+
+struct collect_urls_data {
+ struct key_val_list **next;
+
+ const char *type;
+};
+
+static int collect_urls(const char *var, const char *value, void *cb_data)
+{
+ struct collect_urls_data *cb = (struct collect_urls_data*)cb_data;
+ int typelen = strlen(cb->type);
+ int len;
+ char *doturl;
+ struct key_val_list *item;
+
+ if (prefixcmp(var, cb->type))
+ return 0;
+
+ if (var[typelen] != '.')
+ return 0;
+
+ var += typelen+1;
+
+ doturl = strrchr(var, '.');
+ if (!doturl || strcmp(doturl, ".url"))
+ return 0;
+
+ len = doturl-var;
+ if (len <= 0)
+ return 0;
+
+ item = xmalloc(sizeof(struct key_val_list));
+ item->key = xmalloc(len+1);
+ memcpy(item->key, var, len);
+ item->key[len] = 0;
+ item->val = xstrdup(value);
+ item->next = NULL;
+ *cb->next = item;
+ cb->next = &item->next;
+
+ return 0;
+}
+
+static const char *local_URL(const char *remote, const char *url)
+{
+ static char local_url[PATH_MAX];
+
+ if (!prefixcmp(url, "https://"))
+ return url;
+
+ if (!prefixcmp(url, "http://"))
+ return url;
+
+ if (!prefixcmp(url, "ftp://"))
+ return url;
+
+ if (!prefixcmp(remote, "/"))
+ return url;
+
+ if (!prefixcmp(remote, "ssh://") && !prefixcmp(url, "/")) {
+ char *slash;
+ int len = strlen(url);
+
+ slash = strchr(remote+6, '/');
+ if (!slash || (slash-remote)+len+1 > sizeof(local_url))
+ return NULL;
+ memcpy(local_url, remote, slash-remote);
+ memcpy(local_url+(slash-remote), url, len+1);
+ return local_url;
+ }
+
+ return NULL;
+}
+
+static int fetch_submodule_urls(struct key_val_list **next_url)
+{
+ struct key_val_list *remotes = NULL;
+ struct collect_urls_data remotes_data = { &remotes, "remote" };
+ struct key_val_list *remote;
+ static char key[1024];
+
+ git_config(collect_urls, &remotes_data);
+ for (remote = remotes; remote; remote = remote->next) {
+ struct key_val_list *submodules = NULL;
+ struct collect_urls_data submodules_data =
+ { &submodules, "submodule" };
+ struct key_val_list *submodule;
+ char *dest;
+
+ dest = xstrdup(remote->val);
+ git_config_from_remote(collect_urls, dest, &submodules_data);
+ free(dest);
+ for (submodule = submodules; submodule; submodule = submodule->next) {
+ const char *local_url;
+ struct key_val_list *item;
+
+ local_url = local_URL(remote->val, submodule->val);
+ if (!local_url)
+ continue;
+
+ if (snprintf(key, sizeof(key),
+ "submodule.%s.url", submodule->key) > sizeof(key))
+ return error("submodule name too long");
+
+ git_config_set(key, local_url);
+
+ item = xmalloc(sizeof(struct key_val_list));
+ item->key = xstrdup(submodule->key);
+ item->val = xstrdup(local_url);
+ item->next = NULL;
+ *next_url = item;
+ next_url = &item->next;
+ }
+
+ free_key_val_list(submodules);
+ }
+
+ free_key_val_list(remotes);
+
+ return 0;
+}
+
+int clone_submodule(const char *submodule)
+{
+ struct key_val_list *submodules = NULL;
+ struct collect_urls_data submodules_data = { &submodules, "submodule" };
+ struct key_val_list *item;
+ char *path;
+ int err;
+ const char *args[10];
+ int argc;
+
+ git_config(collect_urls, &submodules_data);
+ item = find_key_val_list(submodules, submodule);
+ if (!item) {
+ err = fetch_submodule_urls(submodules_data.next);
+ if (err)
+ return err;
+ item = find_key_val_list(*submodules_data.next, submodule);
+ if (!item)
+ return error("don't know where to get submodule '%s'",
+ submodule);
+ }
+
+ path = git_path("submodules/%s", submodule);
+
+ argc = 0;
+ args[argc++] = "clone";
+ args[argc++] = "--submodules";
+ args[argc++] = "-n";
+ args[argc++] = item->val;
+ args[argc++] = path;
+ args[argc] = NULL;
+
+ err = run_command_v_opt(args, RUN_GIT_CMD|RUN_COMMAND_CLEAR_GIT_ENV);
+
+ path = git_path("submodules/%s/.git", submodule);
+
+ argc = 0;
+ args[argc++] = "update-ref";
+ args[argc++] = "--no-deref";
+ args[argc++] = "HEAD";
+ args[argc++] = "0000000000000000000000000000000000000000";
+ args[argc] = NULL;
+
+ if (!err)
+ err = run_command_v_opt_cd(args,
+ RUN_GIT_CMD|RUN_COMMAND_CLEAR_GIT_ENV, path);
+
+ if (err)
+ return error("failed to clone submodule '%s'", submodule);
+
+ free_key_val_list(submodules);
+
+ return 0;
+}
diff --git a/submodules.h b/submodules.h
new file mode 100644
index 0000000..bf3f118
--- /dev/null
+++ b/submodules.h
@@ -0,0 +1,7 @@
+#ifndef SUBMODULES_H
+#define SUBMODULES_H
+
+int is_checkedout_submodule(const char *path);
+int clone_submodule(const char *submodule);
+
+#endif
diff --git a/unpack-trees.c b/unpack-trees.c
index d5e458d..ddefb51 100644
--- a/unpack-trees.c
+++ b/unpack-trees.c
@@ -6,6 +6,7 @@
#include "unpack-trees.h"
#include "progress.h"
#include "refs.h"
+#include "submodules.h"
#define DBRT_DEBUG 1
@@ -804,6 +805,35 @@ int threeway_merge(struct cache_entry **stages,
return count;
}
+static int ensure_submodule(struct cache_entry *ce,
+ struct unpack_trees_options *o)
+{
+ struct stat st;
+ char *path;
+
+ if (!ce)
+ return 0;
+
+ if (!S_ISGITLINK(ntohl(ce->ce_mode)))
+ return 0;
+
+ if (!is_checkedout_submodule(ce->name) && !o->submodules)
+ return 0;
+
+ path = mkpath("%s/.git", ce->name);
+ if (lstat(path, &st)) {
+ path = git_path("submodules/%s/.git", ce->name);
+ if (lstat(path, &st)) {
+ if (clone_submodule(ce->name))
+ return -1;
+ }
+ }
+
+ /* Now check that the commit is available and fetch if needed */
+
+ return 0;
+}
+
/*
* Two-way merge.
*
@@ -829,6 +859,17 @@ int twoway_merge(struct cache_entry **src,
if (newtree == o->df_conflict_entry)
newtree = NULL;
+ if (o->update) {
+ int err;
+ err = ensure_submodule(current, o);
+ if (!err)
+ err = ensure_submodule(oldtree, o);
+ if (!err)
+ err = ensure_submodule(newtree, o);
+ if (err)
+ return err;
+ }
+
if (current) {
if ((!oldtree && !newtree) || /* 4 and 5 */
(!oldtree && newtree &&
@@ -905,6 +946,15 @@ int oneway_merge(struct cache_entry **src,
return error("Cannot do a oneway merge of %d trees",
o->merge_size);
+ if (o->update) {
+ int err;
+ err = ensure_submodule(old, o);
+ if (!err)
+ err = ensure_submodule(a, o);
+ if (err)
+ return err;
+ }
+
if (!a)
return deleted_entry(old, old, o);
if (old && same(old, a)) {
--
1.5.2.784.g5532e
next prev parent reply other threads:[~2007-05-23 22:23 UTC|newest]
Thread overview: 94+ messages / expand[flat|nested] mbox.gz Atom feed top
2007-05-23 22:22 [RFC] Fourth round of support for cloning submodules skimo
2007-05-23 22:22 ` [PATCH 01/22] git_connect: unset CONFIG_ENVIRONMENT in child skimo
2007-05-23 22:22 ` [PATCH 02/22] Add dump-config skimo
2007-05-23 22:22 ` [PATCH 03/22] git-config: add --remote option for reading config from remote repo skimo
2007-05-23 22:22 ` [PATCH 04/22] http.h: make fill_active_slots a function pointer skimo
2007-05-23 22:22 ` [PATCH 05/22] git-config: read remote config files over HTTP skimo
2007-05-23 22:22 ` [PATCH 06/22] unpack-trees.c: pass cache_entry * to verify_absent rather than just the name skimo
2007-05-23 22:22 ` [PATCH 07/22] git-read-tree: take --submodules option skimo
2007-05-23 22:22 ` [PATCH 08/22] unpack-trees.c: assume submodules are clean skimo
2007-05-23 22:22 ` [PATCH 09/22] Add run_command_v_opt_cd: chdir into a directory before exec skimo
2007-05-23 22:22 ` [PATCH 10/22] run-command: optionally clear git environment skimo
2007-05-24 6:57 ` Alex Riesen
2007-05-24 7:15 ` Shawn O. Pearce
2007-05-24 7:19 ` Alex Riesen
2007-05-23 22:23 ` [PATCH 11/22] entry.c: optionally checkout submodules skimo
2007-05-24 6:59 ` Alex Riesen
2007-05-24 7:18 ` Shawn O. Pearce
2007-05-24 7:27 ` Sven Verdoolaege
2007-05-24 7:29 ` Alex Riesen
2007-05-24 16:21 ` Martin Waitz
2007-05-25 0:49 ` Shawn O. Pearce
2007-05-23 22:23 ` [PATCH 12/22] git-checkout: pass --submodules option to git-read-tree skimo
2007-05-23 22:23 ` [PATCH 13/22] git-read-tree: treat null commit as empty tree skimo
2007-05-23 22:23 ` [PATCH 14/22] git_config: add void * for callback data skimo
2007-05-23 22:23 ` [PATCH 15/22] make redirecting stdout to /dev/null available via run_command_v_opt skimo
2007-05-23 22:23 ` skimo [this message]
2007-05-23 22:23 ` [PATCH 17/22] entry.c: optionally checkout newly cloned submodules skimo
2007-05-24 13:28 ` Johannes Sixt
2007-05-23 22:23 ` [PATCH 18/22] git-clone: add --submodules for cloning submodules skimo
2007-05-23 22:23 ` [PATCH 19/22] test for simple submodule checkout support skimo
2007-05-23 22:23 ` [PATCH 20/22] checkout_submodule: checkout submodule on forced checkout of submodule dir skimo
2007-05-23 22:23 ` [PATCH 21/22] run-command: optionally redirect stderr to /dev/null skimo
2007-05-23 22:23 ` [PATCH 22/22] ensure_submodule: fetch missing revisions skimo
2007-05-23 23:40 ` [RFC] Fourth round of support for cloning submodules Johannes Schindelin
2007-05-24 0:50 ` Junio C Hamano
2007-05-24 7:22 ` Sven Verdoolaege
2007-05-24 7:29 ` Shawn O. Pearce
2007-05-24 7:36 ` Sven Verdoolaege
2007-05-24 9:41 ` Johannes Schindelin
2007-05-24 10:51 ` Sven Verdoolaege
2007-05-24 11:02 ` Johannes Schindelin
2007-05-24 11:16 ` Sven Verdoolaege
2007-05-24 11:31 ` Johannes Schindelin
2007-05-24 11:43 ` Sven Verdoolaege
2007-05-24 12:16 ` Johannes Schindelin
2007-05-24 12:23 ` Johannes Sixt
2007-05-24 13:14 ` Johannes Schindelin
2007-05-24 12:39 ` Sven Verdoolaege
2007-05-24 13:17 ` Johannes Schindelin
2007-05-24 13:24 ` Sven Verdoolaege
2007-05-24 13:52 ` Johannes Schindelin
2007-05-24 17:42 ` Sven Verdoolaege
2007-05-24 18:07 ` Johannes Schindelin
2007-05-24 12:41 ` Lars Hjemli
2007-05-24 13:11 ` Sven Verdoolaege
2007-05-24 13:32 ` Lars Hjemli
2007-05-24 17:13 ` Junio C Hamano
2007-05-24 17:33 ` Lars Hjemli
2007-05-24 17:38 ` Sven Verdoolaege
2007-05-24 17:40 ` Linus Torvalds
2007-05-24 17:55 ` Sven Verdoolaege
2007-05-24 18:09 ` Linus Torvalds
2007-05-24 18:45 ` Junio C Hamano
2007-05-24 19:13 ` Lars Hjemli
2007-05-24 19:25 ` Johannes Schindelin
2007-05-24 18:11 ` Johannes Schindelin
2007-05-25 10:00 ` Sven Verdoolaege
2007-05-25 16:16 ` Junio C Hamano
2007-05-25 16:28 ` Sven Verdoolaege
2007-05-25 16:43 ` Johannes Schindelin
2007-05-24 18:38 ` Junio C Hamano
2007-05-25 12:27 ` Josef Weidendorfer
2007-05-25 12:44 ` Johannes Schindelin
2007-05-25 13:59 ` Josef Weidendorfer
2007-05-25 14:16 ` Johannes Schindelin
2007-05-25 14:38 ` Sven Verdoolaege
2007-05-25 14:51 ` Johannes Schindelin
2007-05-25 14:51 ` Josef Weidendorfer
2007-05-25 14:54 ` Johannes Schindelin
2007-05-25 15:35 ` Linus Torvalds
2007-05-25 16:23 ` Josef Weidendorfer
2007-05-25 16:37 ` Johannes Schindelin
2007-05-25 17:09 ` Josef Weidendorfer
2007-05-25 12:22 ` Jakub Narebski
2007-05-25 12:32 ` Johannes Schindelin
2007-05-24 12:23 ` Santi Béjar
2007-05-27 20:34 ` Martin Waitz
2007-05-27 20:40 ` Sven Verdoolaege
2007-05-24 13:35 ` Martin Waitz
2007-05-24 7:24 ` Sven Verdoolaege
2007-05-24 9:35 ` Johannes Schindelin
2007-05-24 10:54 ` Sven Verdoolaege
2007-05-24 12:38 ` Petr Baudis
2007-05-24 13:13 ` Johannes Schindelin
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=11799589931789-git-send-email-skimo@liacs.nl \
--to=skimo@liacs.nl \
--cc=git@vger.kernel.org \
--cc=junkio@cox.net \
--cc=raa.lkml@gmail.com \
--cc=tali@admingilde.org \
/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).