On Tue, Feb 18, 2014 at 8:40 AM, Nguyễn Thái Ngọc Duy <pclouds@xxxxxxxxx> wrote: > "git checkout --to" sets up a new working directory with a .git file > pointing to $GIT_DIR/repos/<id>. It then executes "git checkout" again > on the new worktree with the same arguments except "--to" is taken > out. The second checkout execution, which is not contaminated with any > info from the current repository, will actually check out and > everything that normal "git checkout" does. > > Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@xxxxxxxxx> > --- > diff --git a/builtin/checkout.c b/builtin/checkout.c > index 0570e41..2b856a6 100644 > --- a/builtin/checkout.c > +++ b/builtin/checkout.c > @@ -806,6 +814,74 @@ static int switch_branches(const struct checkout_opts *opts, > return ret || writeout_error; > } > > +static int prepare_linked_checkout(const struct checkout_opts *opts, > + struct branch_info *new) > +{ > + struct strbuf sb_git = STRBUF_INIT, sb_repo = STRBUF_INIT; > + struct strbuf sb = STRBUF_INIT; > + const char *path = opts->new_worktree; > + struct stat st; > + const char *name; > + struct child_process cp; > + int counter = 0, len; > + > + if (!new->commit) > + die(_("no branch specified")); > + > + len = strlen(path); > + if (!len || is_dir_sep(path[len - 1])) > + die(_("'--to' argument '%s' cannot end with a slash"), path); What is the purpose of this restriction? > + for (name = path + len - 1; name > path; name--) > + if (is_dir_sep(*name)) { > + name++; > + break; > + } > + strbuf_addstr(&sb_repo, git_path("repos/%s", name)); > + len = sb_repo.len; > + if (safe_create_leading_directories_const(sb_repo.buf)) > + die_errno(_("could not create leading directories of '%s'"), > + sb_repo.buf); > + while (!stat(sb_repo.buf, &st)) { > + counter++; > + strbuf_setlen(&sb_repo, len); > + strbuf_addf(&sb_repo, "%d", counter); > + } > + name = sb_repo.buf + len - strlen(name); > + if (mkdir(sb_repo.buf, 0777)) > + die_errno(_("could not create directory of '%s'"), sb_repo.buf); > + > + strbuf_addf(&sb_git, "%s/.git", path); > + if (safe_create_leading_directories_const(sb_git.buf)) > + die_errno(_("could not create leading directories of '%s'"), > + sb_git.buf); > + > + write_file(sb_git.buf, 1, "gitdir: %s/repos/%s\n", > + real_path(get_git_dir()), name); > + /* > + * This is to keep resolve_ref() happy. We need a valid HEAD > + * or is_git_directory() will reject the directory. Any valid > + * value would do because this value will be ignored and > + * replaced at the next (real) checkout. > + */ > + strbuf_addf(&sb, "%s/HEAD", sb_repo.buf); > + write_file(sb.buf, 1, "%s\n", sha1_to_hex(new->commit->object.sha1)); > + strbuf_reset(&sb); > + strbuf_addf(&sb, "%s/commondir", sb_repo.buf); > + write_file(sb.buf, 1, "../..\n"); > + > + if (!opts->quiet) > + fprintf_ln(stderr, _("Enter %s (identifier %s)"), path, name); > + > + setenv("GIT_CHECKOUT_NEW_WORKTREE", "1", 1); > + setenv(GIT_DIR_ENVIRONMENT, sb_git.buf, 1); > + setenv(GIT_WORK_TREE_ENVIRONMENT, path, 1); > + memset(&cp, 0, sizeof(cp)); > + cp.git_cmd = 1; > + cp.argv = opts->saved_argv; > + return run_command(&cp); > +} > + -- 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