From: Sven Verdoolaege <skimo@kotnet.org> This patch series implements a mechanism for cloning submodules. Each submodule is specified by a 'submodule.<submodule>.url' configuration option, e.g., bash-3.00$ ./git-config --remote=http://www.liacs.nl/~sverdool/isa.git --get-regexp 'submodule\..*\.url' submodule.cloog.url /home/sverdool/public_html/cloog.git submodule.cloog.url http://www.liacs.nl/~sverdool/cloog.git git-clone will use the first url that works. E.g., a git clone --submodules ssh://liacs/~/public_html/isa.git (which only works for me), will use the first url, while a git clone --submodules http://www.liacs.nl/~sverdool/isa.git will use the second. The cloning of submodules is now handled inside git-fetch. skimo -
I forgot to mention that these changes go on top of next (v1.5.2-rc3-762-g77e153b). skimo -
From: Sven Verdoolaege <skimo@kotnet.org>
---
builtin-read-tree.c | 9 ++++++---
unpack-trees.c | 3 +++
2 files changed, 9 insertions(+), 3 deletions(-)
diff --git a/builtin-read-tree.c b/builtin-read-tree.c
index 929dd95..b9fcff7 100644
--- a/builtin-read-tree.c
+++ b/builtin-read-tree.c
@@ -17,9 +17,12 @@ static struct object_list *trees;
static int list_tree(unsigned char *sha1)
{
- struct tree *tree = parse_tree_indirect(sha1);
- if (!tree)
- return -1;
+ struct tree *tree = NULL;
+ if (!is_null_sha1(sha1)) {
+ tree = parse_tree_indirect(sha1);
+ if (!tree)
+ return -1;
+ }
object_list_append(&tree->object, &trees);
return 0;
}
diff --git a/unpack-trees.c b/unpack-trees.c
index e979bc5..30c2a49 100644
--- a/unpack-trees.c
+++ b/unpack-trees.c
@@ -26,6 +26,9 @@ static struct tree_entry_list *create_tree_entry_list(struct tree *tree)
struct tree_entry_list *ret = NULL;
struct tree_entry_list **list_p = &ret;
+ if (!tree)
+ return ret;
+
if (!tree->object.parsed)
parse_tree(tree);
--
1.5.2.rc3.783.gc7476-dirty
-From: Sven Verdoolaege <skimo@kotnet.org>
Signed-off-by: Sven Verdoolaege <skimo@kotnet.org>
---
git-clone.sh | 6 +++---
git-fetch.sh | 20 ++++++++++++++++++++
2 files changed, 23 insertions(+), 3 deletions(-)
diff --git a/git-clone.sh b/git-clone.sh
index 44127c5..44387f4 100755
--- a/git-clone.sh
+++ b/git-clone.sh
@@ -262,8 +262,8 @@ yes,yes)
git-ls-remote "$repo" >"$GIT_DIR/CLONE_HEAD" || exit 1
;;
*)
- case "$repo" in
- rsync://*)
+ case "$bare,$repo" in
+ *,rsync://*)
case "$depth" in
"") ;;
*) die "shallow over rsync not supported" ;;
@@ -295,7 +295,7 @@ yes,yes)
fi
git-ls-remote "$repo" >"$GIT_DIR/CLONE_HEAD" || exit 1
;;
- https://*|http://*|ftp://*)
+ yes,https://*|yes,http://*|yes,ftp://*)
case "$depth" in
"") ;;
*) die "shallow over http or ftp not supported" ;;
diff --git a/git-fetch.sh b/git-fetch.sh
index e169848..84c2523 100755
--- a/git-fetch.sh
+++ b/git-fetch.sh
@@ -237,11 +237,31 @@ fetch_all_at_once () {
}
+http_fetch () {
+ if [ -n "$GIT_SSL_NO_VERIFY" ]; then
+ curl_extra_args="-k"
+ fi
+ if [ -n "$GIT_CURL_FTP_NO_EPSV" -o \
+ "`git-config --bool http.noEPSV`" = true ]; then
+ curl_extra_args="${curl_extra_args} --disable-epsv"
+ fi
+
+ # $1 = Remote, $2 = Local
+ curl -nsfL $curl_extra_args "$1" >"$2"
+}
+
fetch_per_ref () {
reflist="$1"
refs=
rref=
+ if test -n "$all"; then
+ reflist=$(canon_refs_list_for_fetch -d "$remote_nick" \
+ "+refs/heads/*:refs/remotes/$remote_nick/*")
+ http_fetch "$remote/HEAD" "$GIT_DIR/REMOTE_HEAD" ||
+ rm -f "$GIT_DIR/REMOTE_HEAD"
+ fi
+
for ref in $reflist
do
refs="$refs$LF$ref"
--
1.5.2.rc3.783.gc7476-dirty
-From: Sven Verdoolaege <skimo@kotnet.org> When the --submodules option is specified, git-clone 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 | 7 +++ Documentation/git-clone.txt | 6 ++- git-clone.sh | 18 +++++++- git-fetch.sh | 90 +++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 117 insertions(+), 4 deletions(-) diff --git a/Documentation/config.txt b/Documentation/config.txt index ee1c35e..cee9e40 100644 --- a/Documentation/config.txt +++ b/Documentation/config.txt @@ -256,6 +256,10 @@ You probably do not need to adjust this value. + Common unit suffixes of 'k', 'm', or 'g' are supported. +core.submodules + If true, gitlink:git-checkout[1] also checks out submodules. + False by default. + alias.*:: Command aliases for the gitlink:git[1] command wrapper - e.g. after defining "alias.last = cat-file commit HEAD", the invocation @@ -606,6 +610,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/Documentation/git-clone.txt b/Documentation/git-clone.txt index 644bf12..565155b 100644 --- a/Documentation/git-clone.txt +++ b/Documentation/git-clone.txt @@ -11,7 +11,7 @@ SYNOPSIS [verse] 'git-clone' [--template=<template_directory>] [-l [-s]] [-q] [-n] [--bare] [-o <name>] [-u <upload-pack>] [--reference <repository>] - [--depth <depth>] <repository> [<directory>] + [--depth <depth>] [--submodules] <repository>...
From: Sven Verdoolaege <skimo@kotnet.org>
We will need the full cache_entry later to figure out if we are dealing
with a submodule.
Signed-off-by: Sven Verdoolaege <skimo@kotnet.org>
---
unpack-trees.c | 32 ++++++++++++++++----------------
1 files changed, 16 insertions(+), 16 deletions(-)
diff --git a/unpack-trees.c b/unpack-trees.c
index cac2411..3dac150 100644
--- a/unpack-trees.c
+++ b/unpack-trees.c
@@ -487,7 +487,7 @@ static int verify_clean_subdirectory(const char *path, const char *action,
* We do not want to remove or overwrite a working tree file that
* is not tracked, unless it is ignored.
*/
-static void verify_absent(const char *path, const char *action,
+static void verify_absent(struct cache_entry *ce, const char *action,
struct unpack_trees_options *o)
{
struct stat st;
@@ -495,12 +495,12 @@ static void verify_absent(const char *path, const char *action,
if (o->index_only || o->reset || !o->update)
return;
- if (!lstat(path, &st)) {
+ if (!lstat(ce->name, &st)) {
int cnt;
- if (o->dir && excluded(o->dir, path))
+ if (o->dir && excluded(o->dir, ce->name))
/*
- * path is explicitly excluded, so it is Ok to
+ * ce->name is explicitly excluded, so it is Ok to
* overwrite it.
*/
return;
@@ -512,7 +512,7 @@ static void verify_absent(const char *path, const char *action,
* files that are in "foo/" we would lose
* it.
*/
- cnt = verify_clean_subdirectory(path, action, o);
+ cnt = verify_clean_subdirectory(ce->name, action, o);
/*
* If this removed entries from the index,
@@ -540,7 +540,7 @@ static void verify_absent(const char *path, const char *action,
* delete this path, which is in a subdirectory that
* is being replaced with a blob.
*/
- cnt = cache_name_pos(path, strlen(path));
+ cnt = cache_name_pos(ce->name, strlen(ce->name));
if (0 <= cnt) {
struct cache_entry ...From: Sven Verdoolaege <skimo@kotnet.org>
Signed-off-by: Sven Verdoolaege <skimo@kotnet.org>
---
entry.c | 42 ++++++++++++++++++++++++++++++++++++++++--
1 files changed, 40 insertions(+), 2 deletions(-)
diff --git a/entry.c b/entry.c
index 82bf725..96a4a60 100644
--- a/entry.c
+++ b/entry.c
@@ -1,5 +1,6 @@
#include "cache.h"
#include "blob.h"
+#include "run-command.h"
static void create_directories(const char *path, const struct checkout *state)
{
@@ -163,6 +164,44 @@ static int write_entry(struct cache_entry *ce, char *path, const struct checkout
return 0;
}
+static int checkout_submodule(const char *path, struct cache_entry *ce, const struct checkout *state)
+{
+ static char cwd[PATH_MAX];
+ const char *gitdirenv;
+ const char *args[10];
+ int argc;
+ int err;
+
+ if (!state->submodules)
+ return 0;
+
+ if (!getcwd(cwd, sizeof(cwd)) || cwd[0] != '/')
+ die("Unable to read current working directory");
+
+ if (chdir(path))
+ die("Cannot move to '%s'", path);
+
+ argc = 0;
+ args[argc++] = "checkout";
+ if (state->force)
+ args[argc++] = "-f";
+ args[argc++] = sha1_to_hex(ce->sha1);
+ args[argc] = NULL;
+
+ gitdirenv = getenv(GIT_DIR_ENVIRONMENT);
+ unsetenv(GIT_DIR_ENVIRONMENT);
+ err = run_command_v_opt(args, RUN_GIT_CMD);
+ setenv(GIT_DIR_ENVIRONMENT, gitdirenv, 1);
+
+ if (chdir(cwd))
+ die("Cannot come back to cwd");
+
+ if (err)
+ return error("failed to run git-checkout in submodule '%s'", path);
+
+ return 0;
+}
+
int checkout_entry(struct cache_entry *ce, const struct checkout *state, char *topath)
{
static char path[PATH_MAX + 1];
@@ -193,9 +232,8 @@ int checkout_entry(struct cache_entry *ce, const struct checkout *state, char *t
*/
unlink(path);
if (S_ISDIR(st.st_mode)) {
- /* If it is a gitlink, leave it alone! */
if (S_ISDIRLNK(ntohl(ce->ce_mode)))
- return 0;
+ return checkout_submodule(path, ce, state);
if (!state->force)
return error("%s is ...How about modifying run_command to chdir after fork? You'd save the hassle of save/restoring cwd and don't mess up process' context (which is always a good idea to preserve). The code'd be simplier, too. -
It can make code simplier (no need to preserve cwd) and safer
(no chance the cwd of the current process is accidentally forgotten).
Signed-off-by: Alex Riesen <raa.lkml@gmail.com>
---
something like this
run-command.c | 27 ++++++++++++++++++++++-----
run-command.h | 2 ++
2 files changed, 24 insertions(+), 5 deletions(-)
diff --git a/run-command.c b/run-command.c
index eff523e..043b570 100644
--- a/run-command.c
+++ b/run-command.c
@@ -73,6 +73,9 @@ int start_command(struct child_process *cmd)
close(cmd->out);
}
+ if (cmd->dir && chdir(cmd->dir))
+ die("exec %s: cd to %s failed (%s)", cmd->argv[0],
+ cmd->dir, strerror(errno));
if (cmd->git_cmd) {
execv_git_cmd(cmd->argv);
} else {
@@ -133,13 +136,27 @@ int run_command(struct child_process *cmd)
return finish_command(cmd);
}
+static void prepare_run_command_v_opt(struct child_process *cmd,
+ const char **argv, int opt)
+{
+ memset(cmd, 0, sizeof(*cmd));
+ cmd->argv = argv;
+ cmd->no_stdin = opt & RUN_COMMAND_NO_STDIN ? 1 : 0;
+ cmd->git_cmd = opt & RUN_GIT_CMD ? 1 : 0;
+ cmd->stdout_to_stderr = opt & RUN_COMMAND_STDOUT_TO_STDERR ? 1 : 0;
+}
+
int run_command_v_opt(const char **argv, int opt)
{
struct child_process cmd;
- memset(&cmd, 0, sizeof(cmd));
- cmd.argv = argv;
- cmd.no_stdin = opt & RUN_COMMAND_NO_STDIN ? 1 : 0;
- cmd.git_cmd = opt & RUN_GIT_CMD ? 1 : 0;
- cmd.stdout_to_stderr = opt & RUN_COMMAND_STDOUT_TO_STDERR ? 1 : 0;
+ prepare_run_command_v_opt(&cmd, argv, opt);
+ return run_command(&cmd);
+}
+
+int run_command_v_opt_cd(const char **argv, int opt, const char *dir)
+{
+ struct child_process cmd;
+ prepare_run_command_v_opt(&cmd, argv, opt);
+ cmd.dir = dir;
return run_command(&cmd);
}
diff --git a/run-command.h b/run-command.h
index 3680ef9..cbd7484 100644
--- a/run-command.h
+++ b/run-command.h
@@ -16,6 +16,7 @@ struct child_process {
p...Signed-off-by: Alex Riesen <raa.lkml@gmail.com>
---
entry.c | 12 +-----------
1 files changed, 1 insertions(+), 11 deletions(-)
diff --git a/entry.c b/entry.c
index 96a4a60..0316c74 100644
--- a/entry.c
+++ b/entry.c
@@ -166,7 +166,6 @@ static int write_entry(struct cache_entry *ce, char *path, const struct checkout
static int checkout_submodule(const char *path, struct cache_entry *ce, const struct checkout *state)
{
- static char cwd[PATH_MAX];
const char *gitdirenv;
const char *args[10];
int argc;
@@ -175,12 +174,6 @@ static int checkout_submodule(const char *path, struct cache_entry *ce, const st
if (!state->submodules)
return 0;
- if (!getcwd(cwd, sizeof(cwd)) || cwd[0] != '/')
- die("Unable to read current working directory");
-
- if (chdir(path))
- die("Cannot move to '%s'", path);
-
argc = 0;
args[argc++] = "checkout";
if (state->force)
@@ -190,12 +183,9 @@ static int checkout_submodule(const char *path, struct cache_entry *ce, const st
gitdirenv = getenv(GIT_DIR_ENVIRONMENT);
unsetenv(GIT_DIR_ENVIRONMENT);
- err = run_command_v_opt(args, RUN_GIT_CMD);
+ err = run_command_v_opt_cd(args, RUN_GIT_CMD, path);
setenv(GIT_DIR_ENVIRONMENT, gitdirenv, 1);
- if (chdir(cwd))
- die("Cannot come back to cwd");
-
if (err)
return error("failed to run git-checkout in submodule '%s'", path);
--
1.5.2.rc3.83.gbbb0
-We may need an option to ignore these failures. Maybe even active by default. Imagine a superproject with _optional_ submodules, where it is just nice to know that some submodules weren't checked out. BTW, doesn't git-checkout already prints an error? -
Probably. You probably noticed that I haven't written any tests yet... Still, the error that git-checkout prints may not give enough of a clue that something was wrong with a submodule. skimo -
Like, for example, it failed because the directory is not a git repo yet, because the previous git-checkout was called _without_ --submodule and the directories created are just empty. Anyway, just a "failed to run git-checkout" is not very helpful either. Come to think about it, there is not very much you can tell out of super-project context. git-checkout will always know better. -
From: Sven Verdoolaege <skimo@kotnet.org>
This code was killed by commit fcc387db9bc453dc7e07a262873481af2ee9e5c8.
Signed-off-by: Sven Verdoolaege <skimo@kotnet.org>
---
unpack-trees.c | 4 ----
1 files changed, 0 insertions(+), 4 deletions(-)
diff --git a/unpack-trees.c b/unpack-trees.c
index 906ce69..cac2411 100644
--- a/unpack-trees.c
+++ b/unpack-trees.c
@@ -414,10 +414,6 @@ static void verify_uptodate(struct cache_entry *ce,
return;
errno = 0;
}
- if (o->reset) {
- ce->ce_flags |= htons(CE_UPDATE);
- return;
- }
if (errno == ENOENT)
return;
die("Entry '%s' not uptodate. Cannot merge.", ce->name);
--
1.5.2.rc3.783.gc7476-dirty
-From: Sven Verdoolaege <skimo@kotnet.org>
This option currently has no effect.
Signed-off-by: Sven Verdoolaege <skimo@kotnet.org>
---
builtin-read-tree.c | 25 ++++++++++++++++++++++---
cache.h | 3 ++-
unpack-trees.c | 1 +
unpack-trees.h | 1 +
4 files changed, 26 insertions(+), 4 deletions(-)
diff --git a/builtin-read-tree.c b/builtin-read-tree.c
index 316fb0f..929dd95 100644
--- a/builtin-read-tree.c
+++ b/builtin-read-tree.c
@@ -87,14 +87,23 @@ static void prime_cache_tree(void)
static const char read_tree_usage[] = "git-read-tree (<sha> | [[-m [--aggressive] | --reset | --prefix=<prefix>] [-u | -i]] [--exclude-per-directory=<gitignore>] [--index-output=<file>] <sha1> [<sha2> [<sha3>]])";
static struct lock_file lock_file;
+static struct unpack_trees_options opts;
+
+static int git_read_tree_config(const char *var, const char *value)
+{
+ if (!strcmp(var, "core.submodules")) {
+ opts.submodules = git_config_bool(var, value);
+ return 0;
+ }
+
+ return git_default_config(var, value);
+}
int cmd_read_tree(int argc, const char **argv, const char *unused_prefix)
{
int i, newfd, stage = 0;
unsigned char sha1[20];
- struct unpack_trees_options opts;
- memset(&opts, 0, sizeof(opts));
opts.head_idx = -1;
setup_git_directory();
@@ -102,7 +111,7 @@ int cmd_read_tree(int argc, const char **argv, const char *unused_prefix)
newfd = hold_locked_index(&lock_file, 1);
- git_config(git_default_config);
+ git_config(git_read_tree_config);
for (i = 1; i < argc; i++) {
const char *arg = argv[i];
@@ -172,6 +181,16 @@ int cmd_read_tree(int argc, const char **argv, const char *unused_prefix)
continue;
}
+ if (!strcmp(arg, "--no-submodules")) {
+ opts.submodules = 0;
+ continue;
+ }
+
+ if (!strcmp(arg, "--submodules")) {
+ opts.submodules = 1;
+ continue;
+ }
+
/* "-m" stands for "merge", meaning we start in ...Nacked-by: Petr Baudis <pasky@suse.cz> Please do not add more undocumented parameters - include documentation in the patch adding the parameter. -- Petr "Pasky" Baudis Stuff: http://pasky.or.cz/ Ever try. Ever fail. No matter. // Try again. Fail again. Fail better. -- Samuel Beckett -
Can we have this option (and corresponding support in the following patches, of course) first? It is enough to have subprojects working locally, and people can start using them immediately: anyone can clone the subprojects manually if he wishes so. Cloning of subprojects is still unclear, and frankly I'm not sure it should be done at all. Not even with an option which is off by default. -
I noticed there's a whole thread about subprojects that I haven't read yet, so this may have been addressed already .... Then don't use it. The reason for not putting this in shouldn't be that someone doesn't think it is useful; the reason should be that my code is crap. skimo -
It is much more tedious. It have to be done recursively, and with right SHA and you have to cd into right direcotry first and it is git-read-tree and git-checkout-index, BTW. The code is not a problem. It can be also discarded because you implemented something no one wants. I just meant to say, that even if no one wants your subproject cloning code, _I_ support your checkout effort and I am asking for it to be put in. "First", as the cloning discussion does not seem to be finished (and, as I said, I am not interested in cloning anyway). -
More specifically, at the very high level, what you do and what people want to happen might share the description (e.g. "this allows checkout of subprojects", or "this implements clone of superproject to recurse") but with semantics that may be different from what people would want (I am not saying that is the case, as I do not think the current discussion concluded yet). The _first_ implementation that goes in the mainline pretty much sets the _semantics_ so we would need to be extra careful, all the more so as this is a feature many people seem It was partly my fault that I mentioned "clone" example in the original message, and then let the discussion drifted to a tangent of the clone topic, namely, how the URL would be determined to clone the subproject from. I would agree that checkout is a more fundamental operation, and I wanted to make that clear in my message, but checkout and clone has certain chicken-and-egg factor between them. After the clone of superproject, checking it out recursively would need cloning the subprojects. Also after a clone of superproject without the recursive behaviour, when the user explicitly asks a subproject to be checked out, somebody needs to do a clone before the subject can be checked out. Having said that, let's throw out an strawman for checkout proper and then merge. The user may or may not want to deal with subprojects, and for something truly large like the KDE case, which is where the superproject support is really needed, a large On/Off switch where an option --subproject makes everything checked out and no subproject is checked out without it is not a usable option. I've already outlined how the .git/config file can be used to define which subprojects are of interested so that the Porcelain layer can decide which ones to recurse into and which ones to leave alone. The design is NOT the only possible/sensible one, and I am sure other people will come up with much nicer organization, but I would consider that is just the m...
Does everyone agree that we should fetch (possibly after asking for confirmation from the use) _during_ the checkout ? I now only fetch submodules during a fetch of the supermodule (actually, in my current patch set, I only fetch a submodule the first time I see it, but that's a bug), but if there is a consensus on this, I can switch to fetching during checkout. As to the key to use to lookup the URL in the config, right now I simply use the directory name where it is attached (which seems like a useful default to me). I'm not all that convinced that we should store a default URL in history, so AFAICS, the only thing we need to store is a mapping between directory names and subproject names. It has been suggested to do that in .gitattributes. Is that OK for everyone, or do we really need a separate .gitmodules ? skimo -
What if the fetch is not possible? You can't checkout? What about the other subprojects, where the checkout succeeded? Will they be reset to the previuos state? To me, the fetch sounds pretty dangerous. Maybe the checkout should be two stage: first - we check all subprojects to be checked out if it is possible, second - either fail (default) or checkout what possible, warn the user, leave the incomplete subprojects changed (but not update the index with them, so that they wont be accidentally Shouldn't that depend on "-m" option given to git-checkout in superproject? Sometime the user have to be sure he can checkout everything as it were, but without breaking the local state (like what Universally agreed upon -
So I've implemented my own Git subproject support in a Java based tool we use internally. Its actually driving the Git plumbing (as JGit isn't complete enough to do the job) but applies quite a bit to this discussion as it is a working system that implements this "checkout in superproject and recurse into subproject". First I don't use the subproject support in the core plumbing, because that came along from Linus about 2 days after I wrote this implementation. Our data file looks like: use-component: subproject1 >=df8cfac815... use-component: subproject2 >=af9b543820... Or really anything that is a valid commit-ish, and often these are During our build process we scan the root project's data file, and clone by the relative URL anything we cannot find locally: $(git config remote.origin.url)/../component-links/subproject1.git to get the subproject repository. We don't require that the subproject1 directory actually be called subproject1 in the superproject, its just a recommendation. That data file is also our build-system driver and the build system driver is pretty darn smart about guessing what is going on. ;-) You'll notice however that we (more or less) have a very flat structure. The component-links directory is really just a set of symlinks pointing back up a level, as sometimes a component is not stored in a repository named the component name, but the component Yes. Except we do a few things differently: - Only update the subproject if its a strict fast-forward. - Abort on a dirty working directory in the subproject or if a merge would be required to keep the current commit and the new commit. Yes, we don't really support going "backwards". - The merge aborting thing is probably wrong for some users, but blindly switching to the target commit feels somewhat wrong in our own uses. Sometimes you need the current version of the subproject to help you debug an older version of the superproject, or sibling subproject. - You ...
From: Sven Verdoolaege <skimo@kotnet.org> Signed-off-by: Sven Verdoolaege <skimo@kotnet.org> --- git-clone.sh | 20 ++++++++++++-------- git-fetch.sh | 28 ++++++++++++++++++++++------ 2 files changed, 34 insertions(+), 14 deletions(-) diff --git a/git-clone.sh b/git-clone.sh index fdd354f..44127c5 100755 --- a/git-clone.sh +++ b/git-clone.sh @@ -159,6 +159,11 @@ then no_checkout=yes use_separate_remote= fi +if test t = "$use_separate_remote"; then + separate_remote_flag="--use-separate-remote" +else + separate_remote_flag="--no-separate-remote" +fi if test -z "$origin" then @@ -219,6 +224,10 @@ then fi fi +# Write out $origin URL +GIT_CONFIG="$GIT_DIR/config" +git-config remote."$origin".url "$repo" || exit + rm -f "$GIT_DIR/CLONE_HEAD" # We do local magic only when the user tells us to. @@ -299,11 +308,9 @@ yes,yes) fi ;; *) - case "$upload_pack" in - '') git-fetch-pack --all -k $quiet $depth $no_progress "$repo";; - *) git-fetch-pack --all -k $quiet "$upload_pack" $depth $no_progress "$repo" ;; - esac >"$GIT_DIR/CLONE_HEAD" || - die "fetch-pack from '$repo' failed." + git-fetch --all -k $quiet "$upload_pack" $depth \ + $separate_remote_flag "$origin" || + die "fetch from '$repo' failed." ;; esac ;; @@ -387,9 +394,6 @@ then origin_track="$remote_top/$head_points_at" && git-update-ref HEAD "$head_sha1" && - # Upstream URL - git-config remote."$origin".url "$repo" && - # Set up the mappings to track the remote branches. git-config remote."$origin".fetch \ "+refs/heads/*:$remote_top/*" '^$' && diff --git a/git-fetch.sh b/git-fetch.sh index dbeca14..e169848 100755 --- a/git-fetch.sh +++ b/git-fetch.sh @@ -15,6 +15,7 @@ LF=' ' IFS="$LF" +all= no_tags= tags= append= @@ -25,6 +26,7 @@ exec= keep= shallow_depth= no_progress= +use_separate_remote= test -t 1 || no_progress=--no-progress quiet= while case "$#" in 0)...
From: Sven Verdoolaege <skimo@kotnet.org>
Signed-off-by: Sven Verdoolaege <skimo@kotnet.org>
---
builtin-fetch--tool.c | 48 ++++++++++++++++++++++++++++++++++++++++++++----
1 files changed, 44 insertions(+), 4 deletions(-)
diff --git a/builtin-fetch--tool.c b/builtin-fetch--tool.c
index ed4d5de..3441a4a 100644
--- a/builtin-fetch--tool.c
+++ b/builtin-fetch--tool.c
@@ -207,6 +207,32 @@ static void remove_keep_on_signal(int signo)
raise(signo);
}
+static char *construct_local_name(const char *remote_ref, const char *remote_nick,
+ int use_separate_remote)
+{
+ static char local_ref[PATH_MAX];
+ int len = strlen(remote_ref);
+
+ if (len >= 3 && !memcmp(remote_ref+len-3, "^{}", 3))
+ return NULL;
+ if (!strcmp(remote_ref, "HEAD"))
+ return "REMOTE_HEAD";
+ if (!prefixcmp(remote_ref, "refs/heads/")) {
+ if (snprintf(local_ref, sizeof(local_ref), "refs/%s%s/%s",
+ use_separate_remote ? "remotes/" : "heads",
+ use_separate_remote ? remote_nick : "",
+ remote_ref+11) > sizeof(local_ref))
+ die("Local branchname too long");
+ } else if (!prefixcmp(remote_ref, "refs/tags/")) {
+ if (snprintf(local_ref, sizeof(local_ref), "refs/tags/%s",
+ remote_ref+10) > sizeof(local_ref))
+ die("Local branchname too long");
+ } else
+ return NULL;
+
+ return local_ref;
+}
+
static char *find_local_name(const char *remote_name, const char *refs,
int *force_p, int *not_for_merge_p)
{
@@ -261,7 +287,8 @@ static int fetch_native_store(FILE *fp,
const char *remote,
const char *remote_nick,
const char *refs,
- int verbose, int force)
+ int verbose, int force,
+ int all, int use_separate_remote)
{
char buffer[1024];
int err = 0;
@@ -294,8 +321,12 @@ static int fetch_native_store(FILE *fp,
continue;
}
- local_name = find_local_name(cp, refs,
- &single_force, &not_for_merge);
+ if (all)
+ local_name = construct...This code produces warning about possible uninitialized used of single_force and not_for_merge. I used the patch below, but didn't look into what the "all" does. --- builtin-fetch--tool.c | 4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-) diff --git a/builtin-fetch--tool.c b/builtin-fetch--tool.c index 12adb38..ebb49d9 100644 --- a/builtin-fetch--tool.c +++ b/builtin-fetch--tool.c @@ -273,7 +273,7 @@ static int fetch_native_store(FILE *fp, int len; char *cp; char *local_name; - int single_force, not_for_merge; + int single_force = force, not_for_merge = 0; for (cp = buffer; *cp && !isspace(*cp); cp++) ; @@ -301,7 +301,7 @@ static int fetch_native_store(FILE *fp, err |= append_fetch_head(fp, buffer, remote, cp, remote_nick, local_name, not_for_merge, - verbose, force || single_force); + verbose, single_force); } return err; } -- 1.5.2.rc3.83.gbbb0 -
Sorry for being sloppy. It is assumed that "all" is only used for cloning and then the other two flags don't really matter, but I should've set some defaults. Yours look fine, thanks. A fixed-up version is available in the "submodules" branch of http://www.liacs.nl/~sverdool/git.git or www.liacs.nl/~sverdool/gitweb.cgi?p=git.git;a=shortlog;h=submodules skimo -
From: Sven Verdoolaege <skimo@kotnet.org> This makes it easier for scripts to call git-fetch with options that may or may not be set. Signed-off-by: Sven Verdoolaege <skimo@kotnet.org> --- git-fetch.sh | 2 ++ 1 files changed, 2 insertions(+), 0 deletions(-) diff --git a/git-fetch.sh b/git-fetch.sh index 0e05cf1..dbeca14 100755 --- a/git-fetch.sh +++ b/git-fetch.sh @@ -76,6 +76,8 @@ do -*) usage ;; + '') + ;; *) break ;; -- 1.5.2.rc3.783.gc7476-dirty -
From: Sven Verdoolaege <skimo@kotnet.org>
If the submodules are not clean, then we will get an error
when we actally do the checkout.
Signed-off-by: Sven Verdoolaege <skimo@kotnet.org>
---
unpack-trees.c | 43 ++++++++++++++++++++++++++++++++++---------
1 files changed, 34 insertions(+), 9 deletions(-)
diff --git a/unpack-trees.c b/unpack-trees.c
index 5fa637a..e979bc5 100644
--- a/unpack-trees.c
+++ b/unpack-trees.c
@@ -5,6 +5,7 @@
#include "cache-tree.h"
#include "unpack-trees.h"
#include "progress.h"
+#include "refs.h"
#define DBRT_DEBUG 1
@@ -426,11 +427,24 @@ static void invalidate_ce_path(struct cache_entry *ce)
cache_tree_invalidate_path(active_cache_tree, ce->name);
}
-static int verify_clean_subdirectory(const char *path, const char *action,
+/* Check that checking out ce->sha1 in subdir ce->name is not
+ * going to overwrite any working files.
+ *
+ * FIXME: implement this function, so we can detect problems
+ * early, rather than waiting until we actually try to checkout
+ * the submodules.
+ */
+static int verify_clean_submodule(struct cache_entry *ce, const char *action,
+ struct unpack_trees_options *o)
+{
+ return 0;
+}
+
+static int verify_clean_subdirectory(struct cache_entry *ce, const char *action,
struct unpack_trees_options *o)
{
/*
- * we are about to extract "path"; we would not want to lose
+ * we are about to extract "ce->name"; we would not want to lose
* anything in the existing directory there.
*/
int namelen;
@@ -438,13 +452,24 @@ static int verify_clean_subdirectory(const char *path, const char *action,
struct dir_struct d;
char *pathbuf;
int cnt = 0;
+ unsigned char sha1[20];
+
+ if (S_ISDIRLNK(ntohl(ce->ce_mode)) &&
+ resolve_gitlink_ref(ce->name, "HEAD", sha1) == 0) {
+ /* If we are not going to update the submodule, then
+ * we don't care.
+ */
+ if (!o->submodules || !hashcmp(sha1, ce->sha1))
+...From: Sven Verdoolaege <skimo@kotnet.org>
Signed-off-by: Sven Verdoolaege <skimo@kotnet.org>
---
git-checkout.sh | 20 +++++++++++++++-----
1 files changed, 15 insertions(+), 5 deletions(-)
diff --git a/git-checkout.sh b/git-checkout.sh
index 6b6facf..cbb1f00 100755
--- a/git-checkout.sh
+++ b/git-checkout.sh
@@ -1,6 +1,6 @@
#!/bin/sh
-USAGE='[-q] [-f] [-b <new_branch>] [-m] [<branch>] [<paths>...]'
+USAGE='[-q] [-f] [--submodules] [--no-submodules] [-b <new_branch>] [-m] [<branch>] [<paths>...]'
SUBDIRECTORY_OK=Sometimes
. git-sh-setup
require_work_tree
@@ -16,6 +16,7 @@ track=
newbranch=
newbranch_log=
merge=
+submodules=
quiet=
v=-v
LF='
@@ -46,6 +47,15 @@ while [ "$#" != "0" ]; do
-m)
merge=1
;;
+ *,--su|*,--sub|*,--subm|*,--submo|*,--submod|*,--submodu|*,--submodul|\
+ *,--submodule|*,--submodules)
+ submodules="--submodules"
+ ;;
+ *,--no-su|*,--no-sub|*,--no-subm|*,--no-submo|*,--no-submod|\
+ *,--no-submodu|*,--no-submodul|\
+ *,--no-submodule|*,--no-submodules)
+ submodules="--no-submodules"
+ ;;
"-q")
quiet=1
v=
@@ -199,10 +209,10 @@ fi
if [ "$force" ]
then
- git-read-tree $v --reset -u $new
+ git-read-tree $v $submodules --reset -u $new
else
git-update-index --refresh >/dev/null
- merge_error=$(git-read-tree -m -u --exclude-per-directory=.gitignore $old $new 2>&1) || (
+ merge_error=$(git-read-tree $submodules -m -u --exclude-per-directory=.gitignore $old $new 2>&1) || (
case "$merge" in
'')
echo >&2 "$merge_error"
@@ -212,7 +222,7 @@ else
# Match the index to the working tree, and do a three-way.
git diff-files --name-only | git update-index --remove --stdin &&
work=`git write-tree` &&
- git read-tree $v --reset -u $new || exit
+ git read-tree $v $submodules --reset -u $new || exit
eval GITHEAD_$new='${new_name:-${branch:-$new}}' &&
eval GITHEAD_$work=local &&...Thus Documentation/git-checkout.txt needs to be updated as well. -- Petr "Pasky" Baudis Stuff: http://pasky.or.cz/ Ever try. Ever fail. No matter. // Try again. Fail again. Fail better. -- Samuel Beckett -
From: Sven Verdoolaege <skimo@kotnet.org>
Signed-off-by: Sven Verdoolaege <skimo@kotnet.org>
---
Makefile | 7 ++++++-
builtin-config.c | 8 ++++++--
config.c | 16 +++++++++++++++-
http.c | 10 ++++++----
http.h | 2 +-
http_config.h | 1 +
http_config_curl.c | 52 ++++++++++++++++++++++++++++++++++++++++++++++++++++
http_config_none.c | 6 ++++++
8 files changed, 93 insertions(+), 9 deletions(-)
create mode 100644 http_config.h
create mode 100644 http_config_curl.c
create mode 100644 http_config_none.c
diff --git a/Makefile b/Makefile
index 37eb861..bce8514 100644
--- a/Makefile
+++ b/Makefile
@@ -319,7 +319,8 @@ LIB_OBJS = \
write_or_die.o trace.o list-objects.o grep.o match-trees.o \
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
+ convert.o attr.o decorate.o progress.o mailmap.o symlinks.o \
+ $(HTTP_CONFIG_OBJ)
BUILTIN_OBJS = \
builtin-add.o \
@@ -526,6 +527,10 @@ ifndef NO_CURL
ifndef NO_EXPAT
EXPAT_LIBEXPAT = -lexpat
endif
+ HTTP_CONFIG_OBJ = http_config_curl.o http.o
+ EXTLIBS += $(CURL_LIBCURL)
+else
+ HTTP_CONFIG_OBJ = http_config_none.o
endif
ifndef NO_OPENSSL
diff --git a/builtin-config.c b/builtin-config.c
index 3a1e86c..7e18f73 100644
--- a/builtin-config.c
+++ b/builtin-config.c
@@ -147,8 +147,12 @@ int cmd_config(int argc, const char **argv, const char *prefix)
type = T_INT;
else if (!strcmp(argv[1], "--bool"))
type = T_BOOL;
- else if (!strcmp(argv[1], "--list") || !strcmp(argv[1], "-l"))
- return git_config(show_all_config);
+ else if (!strcmp(argv[1], "--list") || !strcmp(argv[1], "-l")) {
+ if (dest)
+ return git_config_from_remote(show_all_config, dest);
+ else
+ return git_config(show_all_config);
+ }
else if (!strcmp(argv[1], "--global")) {
...From: Sven Verdoolaege <skimo@kotnet.org> Signed-off-by: Sven Verdoolaege <skimo@kotnet.org> --- Documentation/git-config.txt | 33 +++++++++++++++++++++--------- builtin-config.c | 44 ++++++++++++++++++++++++++++++++--------- cache.h | 1 + config.c | 26 ++++++++++++++++++++++++ 4 files changed, 84 insertions(+), 20 deletions(-) diff --git a/Documentation/git-config.txt b/Documentation/git-config.txt index 280ef20..76398ab 100644 --- a/Documentation/git-config.txt +++ b/Documentation/git-config.txt @@ -9,16 +9,25 @@ git-config - Get and set repository or global options SYNOPSIS -------- [verse] -'git-config' [--system | --global] [type] name [value [value_regex]] -'git-config' [--system | --global] [type] --add name value -'git-config' [--system | --global] [type] --replace-all name [value [value_regex]] -'git-config' [--system | --global] [type] --get name [value_regex] -'git-config' [--system | --global] [type] --get-all name [value_regex] -'git-config' [--system | --global] [type] --unset name [value_regex] -'git-config' [--system | --global] [type] --unset-all name [value_regex] -'git-config' [--system | --global] [type] --rename-section old_name new_name -'git-config' [--system | --global] [type] --remove-section name -'git-config' [--system | --global] -l | --list +'git-config' [--system | --global | --remote=[<host>:]<directory ] + [type] name [value [value_regex]] +'git-config' [--system | --global | --remote=[<host>:]<directory ] + [type] --add name value +'git-config' [--system | --global | --remote=[<host>:]<directory ] + [type] --replace-all name [value [value_regex]] +'git-config' [--system | --global | --remote=[<host>:]<directory ] + [type] --get name [value_regex] +'git-config' [--system | --global | --remote=[<host>:]<directory ] + [type] --get-all name [value_regex] +'git-config' [--system | --global | --rem...
From: Sven Verdoolaege <skimo@kotnet.org>
This allows us to use the methods provided by http.c
from within libgit, in particular config.c.
Signed-off-by: Sven Verdoolaege <skimo@kotnet.org>
---
http-fetch.c | 5 ++++-
http-push.c | 5 ++++-
http.h | 2 +-
3 files changed, 9 insertions(+), 3 deletions(-)
diff --git a/http-fetch.c b/http-fetch.c
index 09baedc..53fb2a9 100644
--- a/http-fetch.c
+++ b/http-fetch.c
@@ -317,7 +317,7 @@ static void release_object_request(struct object_request *obj_req)
}
#ifdef USE_CURL_MULTI
-void fill_active_slots(void)
+static void fetch_fill_active_slots(void)
{
struct object_request *obj_req = object_queue_head;
struct active_request_slot *slot = active_queue_head;
@@ -1031,6 +1031,9 @@ int main(int argc, const char **argv)
}
url = argv[arg];
+#ifdef USE_CURL_MULTI
+ fill_active_slots = fetch_fill_active_slots;
+#endif
http_init();
no_pragma_header = curl_slist_append(no_pragma_header, "Pragma:");
diff --git a/http-push.c b/http-push.c
index e3f7675..d4c850b 100644
--- a/http-push.c
+++ b/http-push.c
@@ -794,7 +794,7 @@ static void finish_request(struct transfer_request *request)
}
#ifdef USE_CURL_MULTI
-void fill_active_slots(void)
+static void push_fill_active_slots(void)
{
struct transfer_request *request = request_queue_head;
struct transfer_request *next;
@@ -2355,6 +2355,9 @@ int main(int argc, char **argv)
memset(remote_dir_exists, -1, 256);
+#ifdef USE_CURL_MULTI
+ fill_active_slots = push_fill_active_slots;
+#endif
http_init();
no_pragma_header = curl_slist_append(no_pragma_header, "Pragma:");
diff --git a/http.h b/http.h
index 69b6b66..7a41cde 100644
--- a/http.h
+++ b/http.h
@@ -69,7 +69,7 @@ extern void finish_all_active_slots(void);
extern void release_active_slot(struct active_request_slot *slot);
#ifdef USE_CURL_MULTI
-extern void fill_active_slots(void);
+extern void (*fill_active_slots)(void);
extern void step_active_slo...From: Sven Verdoolaege <skimo@kotnet.org> This command dumps the config of a repository and will be used to read config options from a remote site. Signed-off-by: Sven Verdoolaege <skimo@kotnet.org> --- .gitignore | 1 + Documentation/cmd-list.perl | 1 + Documentation/git-dump-config.txt | 37 +++++++++++++++++++++++++++++++++++++ Makefile | 1 + daemon.c | 7 +++++++ dump-config.c | 29 +++++++++++++++++++++++++++++ 6 files changed, 76 insertions(+), 0 deletions(-) create mode 100644 Documentation/git-dump-config.txt create mode 100644 dump-config.c diff --git a/.gitignore b/.gitignore index 4dc0c39..d4e5492 100644 --- a/.gitignore +++ b/.gitignore @@ -38,6 +38,7 @@ git-diff-files git-diff-index git-diff-tree git-describe +git-dump-config git-fast-import git-fetch git-fetch--tool diff --git a/Documentation/cmd-list.perl b/Documentation/cmd-list.perl index 443802a..fa04615 100755 --- a/Documentation/cmd-list.perl +++ b/Documentation/cmd-list.perl @@ -103,6 +103,7 @@ git-diff-files plumbinginterrogators git-diff-index plumbinginterrogators git-diff mainporcelain git-diff-tree plumbinginterrogators +git-dump-config synchelpers git-fast-import ancillarymanipulators git-fetch mainporcelain git-fetch-pack synchingrepositories diff --git a/Documentation/git-dump-config.txt b/Documentation/git-dump-config.txt new file mode 100644 index 0000000..370781c --- /dev/null +++ b/Documentation/git-dump-config.txt @@ -0,0 +1,37 @@ +git-dump-config(1) +==================== + +NAME +---- +git-dump-config - Dump config options + + +SYNOPSIS +-------- +'git-dump-config' <directory> + +DESCRIPTION +----------- +Invoked by 'git-config --rem...
| David Miller | Slow DOWN, please!!! |
| Florian Schmidt | blacklist kernel boot option |
| Ryan Hope | reiser4 for 2.6.27-rc1 |
| Nick Piggin | [rfc] x86: optimise page fault path a little |
git: | |
| Ken Pratt | pack operation is thrashing my server |
| Karl | Re: Git checkout preserve timestamp? |
| Greg KH | Re: [ANNOUNCE] pg - A patch porcelain for GIT |
| Johannes Schindelin | Re: [PATCH] RFC: git lazy clone proof-of-concept |
| Richard Stallman | Real men don't attack straw men |
| new_guy | Longest Uptime? |
| GVG GVG | ssh_exchange_identification: Connection closed by remote host |
| Steve B | Intel Atom and D945GCLF2 |
| Sam Fourman Jr. | amd64 NVIDIA support in FreeBSD 7 |
| Peter Schuller | Re: When will ZFS become stable? |
| Justin Hibbits | Re: [ANNOUNCEMENT] Wiki for discussing P35/IHC9(R)/SATA issues set up |
| Kostik Belousov | Re: sbrk(2) broken |
| VPN's on NetBSD | 3 hours ago | NetBSD |
| Why does uClinux 2.6.18 bootup block SuperIO UART IRQs that BIOS configured | 4 hours ago | Linux kernel |
| USB statistics | 5 hours ago | Linux kernel |
| Block Sub System query | 9 hours ago | Linux kernel |
| kernel module to intercept socket creation | 10 hours ago | Linux kernel |
| Image size changing during each build | 11 hours ago | Linux kernel |
| Soft lock bug | 16 hours ago | Linux kernel |
| sysctl - dynamic registration problem | 22 hours ago | Linux kernel |
| Question on swap as ramdisk partition | 1 day ago | Linux kernel |
| serial driver xmit problem | 1 day ago | Linux kernel |
