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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.