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

Reply via email to