Hi, On Sun, 9 Mar 2008, Daniel Barkalow wrote: > This is in the core so that, if the alternates file has already been > read, the addition can be parsed and put into effect for the current > process. Yes, I like your two patches. BTW so to avoid clashing, I just send what my cumulative "clean-up" patch for builtin-clone is: -- snipsnap -- [PATCH] builtin-clone: misc clean-ups Signed-off-by: Johannes Schindelin <johannes.schindelin@xxxxxx> --- Obviously to be squashed into 10/11 (now 11/12 ;-) Oh, BTW I did not start to look into falling back to copying when hard-linking fails, but it should be as easy as switching the order of if (option_no_hardlinks) { if (copy_file(dest, src, 0666)) die("failed to copy file to %s\n", dest); } else { if (link(src, dest)) die("failed to create link %s\n", dest); } around, issue a "warning (...)" instead of die()ing, setting option_no_hardlinks = 1, and replace the else with if (!option_no_hardlinks). But first I have to sleep (and maybe the fairies were at work when I wake up...) builtin-clone.c | 101 ++++++++++++++++++++++++------------------------------- 1 files changed, 44 insertions(+), 57 deletions(-) diff --git a/builtin-clone.c b/builtin-clone.c index 3890e12..ac5a7d0 100644 --- a/builtin-clone.c +++ b/builtin-clone.c @@ -128,9 +128,15 @@ static char *guess_dir_name(const char *repo, int is_bundle) return xstrndup(start, end - start); } -void setup_reference(const char *repo) +static int is_directory(const char *path) { struct stat buf; + + return !stat(path, &buf) && S_ISDIR(buf.st_mode); +} + +static void setup_reference(const char *repo) +{ const char *ref_git; char *ref_git_copy; @@ -138,16 +144,11 @@ void setup_reference(const char *repo) struct transport *transport; const struct ref *extra; - if (!option_reference) - return; - ref_git = make_absolute_path(option_reference); - if (!stat(mkpath("%s/.git/objects", ref_git), &buf) && - S_ISDIR(buf.st_mode)) + if (is_directory(mkpath("%s/.git/objects", ref_git))) ref_git = mkpath("%s/.git", ref_git); - else if (stat(mkpath("%s/objects", ref_git), &buf) || - !S_ISDIR(buf.st_mode)) + else if (!is_directory(mkpath("%s/objects", ref_git))) die("reference repository '%s' is not a local directory.", option_reference); @@ -166,8 +167,7 @@ void setup_reference(const char *repo) free(ref_git_copy); } -static void -walk_objects(char *src, char *dest) +static void copy_or_link_directory(char *src, char *dest) { struct dirent *de; struct stat buf; @@ -196,12 +196,12 @@ walk_objects(char *src, char *dest) strcpy(src + src_len + 1, de->d_name); strcpy(dest + dest_len + 1, de->d_name); if (stat(src, &buf)) { - fprintf(stderr, "failed to stat %s, ignoring\n", src); + warning ("failed to stat %s\n", src); continue; } if (S_ISDIR(buf.st_mode)) { if (de->d_name[0] != '.') - walk_objects(src, dest); + copy_or_link_directory(src, dest); continue; } @@ -217,8 +217,8 @@ walk_objects(char *src, char *dest) } } -static const struct ref * -clone_local(const char *src_repo, const char *dest_repo) +static const struct ref * clone_local(const char *src_repo, + const char *dest_repo) { const struct ref *ret; char src[PATH_MAX]; @@ -226,15 +226,14 @@ clone_local(const char *src_repo, const char *dest_repo) struct remote *remote; struct transport *transport; - if (option_shared) { + if (option_shared) add_to_alternates_file(src_repo); - } else { + else { snprintf(src, PATH_MAX, "%s/objects", src_repo); snprintf(dest, PATH_MAX, "%s/objects", dest_repo); - walk_objects(src, dest); + copy_or_link_directory(src, dest); } - fprintf(stderr, "Get for %s\n", src_repo); remote = remote_get(src_repo); transport = transport_get(remote, src_repo); ret = transport_get_remote_refs(transport); @@ -244,22 +243,20 @@ clone_local(const char *src_repo, const char *dest_repo) static const char *junk_work_tree; static const char *junk_git_dir; -pid_t clone_pid; +pid_t junk_pid; static void remove_junk(void) { struct strbuf sb; - if (getpid() != clone_pid) + if (getpid() != junk_pid) return; strbuf_init(&sb, 0); if (junk_git_dir) { - fprintf(stderr, "Remove junk %s\n", junk_git_dir); strbuf_addstr(&sb, junk_git_dir); remove_dir_recursively(&sb, 0); strbuf_reset(&sb); } if (junk_work_tree) { - fprintf(stderr, "Remove junk %s\n", junk_work_tree); strbuf_addstr(&sb, junk_work_tree); remove_dir_recursively(&sb, 0); strbuf_reset(&sb); @@ -303,7 +300,8 @@ static const struct ref *locate_head(const struct ref *refs, return NULL; } -static struct ref *write_remote_refs(const struct ref *refs, struct refspec *refspec, const char *reflog) +static struct ref *write_remote_refs(const struct ref *refs, + struct refspec *refspec, const char *reflog) { struct ref *local_refs = NULL; struct ref **tail = &local_refs; @@ -332,7 +330,7 @@ int cmd_clone(int argc, const char **argv, const char *prefix) struct refspec refspec; - clone_pid = getpid(); + junk_pid = getpid(); argc = parse_options(argc, argv, builtin_clone_options, builtin_clone_usage, 0); @@ -357,20 +355,17 @@ int cmd_clone(int argc, const char **argv, const char *prefix) repo_name = argv[0]; path = get_repo_path(repo_name, &is_bundle); - if (path != NULL) - repo = xstrdup(make_absolute_path(path)); + if (path) + repo = path; else if (!strchr(repo_name, ':')) repo = xstrdup(make_absolute_path(repo_name)); else repo = repo_name; - fprintf(stderr, "repo is %s\n", repo); - if (argc == 2) { + if (argc == 2) dir = xstrdup(argv[1]); - } else { + else dir = guess_dir_name(repo_name, is_bundle); - } - fprintf(stderr, "dir is %s\n", dir); if (!stat(dir, &buf)) die("destination directory '%s' already exists.", dir); @@ -386,8 +381,6 @@ int cmd_clone(int argc, const char **argv, const char *prefix) die("working tree '%s' already exists.", work_tree); } - atexit(remove_junk); - if (option_bare || work_tree) git_dir = xstrdup(dir); else { @@ -401,17 +394,18 @@ int cmd_clone(int argc, const char **argv, const char *prefix) die("could not create work tree dir '%s'.", work_tree); set_git_work_tree(work_tree); } + junk_git_dir = git_dir; + atexit(remove_junk); setenv(CONFIG_ENVIRONMENT, xstrdup(mkpath("%s/config", git_dir)), 1); set_git_dir(make_absolute_path(git_dir)); fprintf(stderr, "Initialize %s\n", git_dir); - junk_git_dir = git_dir; init_db(option_template, option_quiet ? INIT_DB_QUIET : 0); - fprintf(stderr, "Okay\n"); - setup_reference(git_dir); + if (option_reference) + setup_reference(git_dir); git_config(git_default_config); @@ -420,15 +414,16 @@ int cmd_clone(int argc, const char **argv, const char *prefix) git_config_set("core.bare", "true"); } else { - snprintf(branch_top, sizeof branch_top, + snprintf(branch_top, sizeof(branch_top), "refs/remotes/%s/", option_origin); /* Configure the remote */ - snprintf(key, sizeof key, "remote.%s.url", option_origin); + snprintf(key, sizeof(key), "remote.%s.url", option_origin); git_config_set(key, repo); - snprintf(key, sizeof key, "remote.%s.fetch", option_origin); - snprintf(value, sizeof value, "+refs/heads/*:%s*", branch_top); + snprintf(key, sizeof(key), "remote.%s.fetch", option_origin); + snprintf(value, sizeof(value), + "+refs/heads/*:%s*", branch_top); git_config_set_multivar(key, value, "^$", 0); } @@ -437,7 +432,7 @@ int cmd_clone(int argc, const char **argv, const char *prefix) refspec.src = "refs/heads/"; refspec.dst = branch_top; - if (path != NULL && !is_bundle) + if (path && !is_bundle) refs = clone_local(path, git_dir); else { struct remote *remote = remote_get(argv[0]); @@ -452,18 +447,10 @@ int cmd_clone(int argc, const char **argv, const char *prefix) if (option_quiet) transport->verbose = -1; - //args.no_progress = 1; - - fprintf(stderr, "Get refs for %s\n", argv[0]); refs = transport_get_remote_refs(transport); - transport_fetch_refs(transport, refs); } - // FFFF transport_get_remote_refs() ought to be able to tell - // us about HEAD being a symref, and what it's to, if it - // actually knows. - clear_extra_refs(); mapped_refs = write_remote_refs(refs, &refspec, reflog_msg.buf); @@ -497,21 +484,24 @@ int cmd_clone(int argc, const char **argv, const char *prefix) head_points_at->peer_ref->name, reflog_msg.buf); - snprintf(key, sizeof key, "branch.%s.remote", head); + snprintf(key, sizeof(key), "branch.%s.remote", head); git_config_set(key, option_origin); - snprintf(key, sizeof key, "branch.%s.merge", head); + snprintf(key, sizeof(key), "branch.%s.merge", head); git_config_set(key, head_points_at->name); } } else if (remote_head) { /* Source had detached HEAD pointing somewhere. */ - if (!option_bare) + if (option_bare) + option_no_checkout = 1; + else update_ref(reflog_msg.buf, "HEAD", remote_head->old_sha1, NULL, REF_NODEREF, DIE_ON_ERR); } else { /* Nothing to checkout out */ if (!option_no_checkout) - fprintf(stderr, "Warning: Remote HEAD refers to nonexistent ref, unable to checkout.\n"); + warning ("remote HEAD refers to nonexistent ref, " + "unable to checkout.\n"); option_no_checkout = 1; } @@ -525,8 +515,6 @@ int cmd_clone(int argc, const char **argv, const char *prefix) /* We need to be in the new work tree for the checkout */ setup_work_tree(); - fprintf(stderr, "work tree now %s\n", get_git_work_tree()); - fd = hold_locked_index(lock_file, 1); memset(&opts, 0, sizeof opts); @@ -549,7 +537,6 @@ int cmd_clone(int argc, const char **argv, const char *prefix) } strbuf_release(&reflog_msg); - junk_work_tree = NULL; - junk_git_dir = NULL; + junk_pid = 0; return 0; } -- 1.5.4.4.642.g1343.dirty -- To unsubscribe from this list: send the line "unsubscribe git" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html