From: Junio C Hamano Date: Thu, 5 Nov 2015 20:18:07 +0000 (-0800) Subject: Merge branch 'nd/clone-linked-checkout' into maint X-Git-Tag: v2.6.3~9 X-Git-Url: https://git.lorimer.id.au/gitweb.git/diff_plain/4349f597f08b6dc50fc6198b8e1b96e19df37c65?hp=-c Merge branch 'nd/clone-linked-checkout' into maint It was not possible to use a repository-lookalike created by "git worktree add" as a local source of "git clone". * nd/clone-linked-checkout: clone: better error when --reference is a linked checkout clone: allow --local from a linked checkout enter_repo: allow .git files in strict mode enter_repo: avoid duplicating logic, use is_git_directory() instead t0002: add test for enter_repo(), non-strict mode path.c: delete an extra space --- 4349f597f08b6dc50fc6198b8e1b96e19df37c65 diff --combined builtin/clone.c index cc896e22d1,3e14491a34..9eaecd9a7c --- a/builtin/clone.c +++ b/builtin/clone.c @@@ -294,9 -294,14 +294,14 @@@ static int add_one_reference(struct str char *ref_git_git = mkpathdup("%s/.git", ref_git); free(ref_git); ref_git = ref_git_git; - } else if (!is_directory(mkpath("%s/objects", ref_git))) + } else if (!is_directory(mkpath("%s/objects", ref_git))) { + struct strbuf sb = STRBUF_INIT; + if (get_common_dir(&sb, ref_git)) + die(_("reference repository '%s' as a linked checkout is not supported yet."), + item->string); die(_("reference repository '%s' is not a local repository."), item->string); + } if (!access(mkpath("%s/shallow", ref_git), F_OK)) die(_("reference repository '%s' is shallow"), item->string); @@@ -424,8 -429,10 +429,10 @@@ static void clone_local(const char *src } else { struct strbuf src = STRBUF_INIT; struct strbuf dest = STRBUF_INIT; - strbuf_addf(&src, "%s/objects", src_repo); - strbuf_addf(&dest, "%s/objects", dest_repo); + get_common_dir(&src, src_repo); + get_common_dir(&dest, dest_repo); + strbuf_addstr(&src, "/objects"); + strbuf_addstr(&dest, "/objects"); copy_or_link_directory(&src, &dest, src_repo, src.len); strbuf_release(&src); strbuf_release(&dest); @@@ -1064,10 -1071,8 +1071,10 @@@ int cmd_clone(int argc, const char **ar transport_unlock_pack(transport); transport_disconnect(transport); - if (option_dissociate) + if (option_dissociate) { + close_all_packs(); dissociate_from_references(); + } junk_mode = JUNK_LEAVE_REPO; err = checkout(); diff --combined path.c index 69265f42ce,a346134462..56317a66be --- a/path.c +++ b/path.c @@@ -98,7 -98,7 +98,7 @@@ static const char *common_list[] = NULL }; -static void update_common_dir(struct strbuf *buf, int git_dir_len) +static void update_common_dir(struct strbuf *buf, int git_dir_len, const char *common_dir) { char *base = buf->buf + git_dir_len; const char **p; @@@ -115,16 -115,12 +115,16 @@@ path++; is_dir = 1; } + + if (!common_dir) + common_dir = get_git_common_dir(); + if (is_dir && dir_prefix(base, path)) { - replace_dir(buf, git_dir_len, get_git_common_dir()); + replace_dir(buf, git_dir_len, common_dir); return; } if (!is_dir && !strcmp(base, path)) { - replace_dir(buf, git_dir_len, get_git_common_dir()); + replace_dir(buf, git_dir_len, common_dir); return; } } @@@ -164,7 -160,7 +164,7 @@@ static void adjust_git_path(struct strb else if (git_db_env && dir_prefix(base, "objects")) replace_dir(buf, git_dir_len + 7, get_object_directory()); else if (git_common_dir_env) - update_common_dir(buf, git_dir_len); + update_common_dir(buf, git_dir_len, NULL); } static void do_git_path(struct strbuf *buf, const char *fmt, va_list args) @@@ -232,8 -228,6 +232,8 @@@ static void do_submodule_path(struct st const char *fmt, va_list args) { const char *git_dir; + struct strbuf git_submodule_common_dir = STRBUF_INIT; + struct strbuf git_submodule_dir = STRBUF_INIT; strbuf_addstr(buf, path); if (buf->len && buf->buf[buf->len - 1] != '/') @@@ -246,17 -240,9 +246,17 @@@ strbuf_addstr(buf, git_dir); } strbuf_addch(buf, '/'); + strbuf_addstr(&git_submodule_dir, buf->buf); strbuf_vaddf(buf, fmt, args); + + if (get_common_dir_noenv(&git_submodule_common_dir, git_submodule_dir.buf)) + update_common_dir(buf, git_submodule_dir.len, git_submodule_common_dir.buf); + strbuf_cleanup_path(buf); + + strbuf_release(&git_submodule_dir); + strbuf_release(&git_submodule_common_dir); } char *git_pathdup_submodule(const char *path, const char *fmt, ...) @@@ -445,18 -431,22 +445,22 @@@ const char *enter_repo(const char *path } if (!suffix[i]) return NULL; - gitfile = read_gitfile(used_path) ; + gitfile = read_gitfile(used_path); if (gitfile) strcpy(used_path, gitfile); if (chdir(used_path)) return NULL; path = validated_path; } - else if (chdir(path)) - return NULL; + else { + const char *gitfile = read_gitfile(path); + if (gitfile) + path = gitfile; + if (chdir(path)) + return NULL; + } - if (access("objects", X_OK) == 0 && access("refs", X_OK) == 0 && - validate_headref("HEAD") == 0) { + if (is_git_directory(".")) { set_git_dir("."); check_repository_format(); return path; @@@ -690,11 -680,6 +694,11 @@@ const char *remove_leading_path(const c * normalized, any time "../" eats up to the prefix_len part, * prefix_len is reduced. In the end prefix_len is the remaining * prefix that has not been overridden by user pathspec. + * + * NEEDSWORK: This function doesn't perform normalization w.r.t. trailing '/'. + * For everything but the root folder itself, the normalized path should not + * end with a '/', then the callers need to be fixed up accordingly. + * */ int normalize_path_copy_len(char *dst, const char *src, int *prefix_len) {