On Tue, Feb 18, 2014 at 8:40 AM, Nguyễn Thái Ngọc Duy <[email protected]> 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 <[email protected]>
> ---
> 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 [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html