diff options
Diffstat (limited to 'builtin/worktree.c')
| -rw-r--r-- | builtin/worktree.c | 115 |
1 files changed, 73 insertions, 42 deletions
diff --git a/builtin/worktree.c b/builtin/worktree.c index 812774a5ca..4fd6f7575f 100644 --- a/builtin/worktree.c +++ b/builtin/worktree.c @@ -252,7 +252,7 @@ static int prune(int ac, const char **av, const char *prefix, OPT__DRY_RUN(&show_only, N_("do not remove, show only")), OPT__VERBOSE(&verbose, N_("report pruned working trees")), OPT_EXPIRY_DATE(0, "expire", &expire, - N_("expire working trees older than <time>")), + N_("prune missing working trees older than <time>")), OPT_END() }; @@ -425,6 +425,39 @@ static int make_worktree_orphan(const char * ref, const struct add_opts *opts, return run_command(&cp); } +/* + * References for worktrees are generally stored in '$GIT_DIR/worktrees/<wt_id>'. + * But when using alternate reference directories, we want to store the worktree + * references in '$ALTERNATE_REFERENCE_DIR/worktrees/<wt_id>'. + * + * Create the necessary folder structure to facilitate the same. But to ensure + * that the former path is still considered a Git directory, add stubs. + */ +static void setup_alternate_ref_dir(struct worktree *wt, const char *wt_git_path) +{ + struct strbuf sb = STRBUF_INIT; + char *path; + + path = wt->repo->ref_storage_payload; + if (!path) + return; + + if (!is_absolute_path(path)) + strbuf_addf(&sb, "%s/", wt->repo->commondir); + + strbuf_addf(&sb, "%s/worktrees", path); + safe_create_dir(wt->repo, sb.buf, 1); + strbuf_addf(&sb, "/%s", wt->id); + safe_create_dir(wt->repo, sb.buf, 1); + strbuf_reset(&sb); + + strbuf_addf(&sb, "this worktree stores references in %s/worktrees/%s", + path, wt->id); + refs_create_refdir_stubs(wt->repo, wt_git_path, sb.buf); + + strbuf_release(&sb); +} + static int add_worktree(const char *path, const char *refname, const struct add_opts *opts) { @@ -440,6 +473,7 @@ static int add_worktree(const char *path, const char *refname, struct strbuf sb_name = STRBUF_INIT; struct worktree **worktrees, *wt = NULL; struct ref_store *wt_refs; + struct repo_config_values *cfg = repo_config_values(the_repository); worktrees = get_worktrees(); check_candidate_path(path, opts->force, worktrees, "add"); @@ -505,7 +539,7 @@ static int add_worktree(const char *path, const char *refname, strbuf_reset(&sb); strbuf_addf(&sb, "%s/gitdir", sb_repo.buf); - write_worktree_linking_files(sb_git, sb, opts->relative_paths); + write_worktree_linking_files(sb_git.buf, sb.buf, opts->relative_paths); strbuf_reset(&sb); strbuf_addf(&sb, "%s/commondir", sb_repo.buf); write_file(sb.buf, "../.."); @@ -518,6 +552,7 @@ static int add_worktree(const char *path, const char *refname, ret = error(_("could not find created worktree '%s'"), name); goto done; } + setup_alternate_ref_dir(wt, sb_repo.buf); wt_refs = get_worktree_ref_store(wt); ret = ref_store_create_on_disk(wt_refs, REF_STORE_CREATE_ON_DISK_IS_WORKTREE, &sb); @@ -536,7 +571,7 @@ static int add_worktree(const char *path, const char *refname, * If the current worktree has sparse-checkout enabled, then copy * the sparse-checkout patterns from the current worktree. */ - if (core_apply_sparse_checkout) + if (cfg->apply_sparse_checkout) copy_sparse_checkout(sb_repo.buf); /* @@ -635,11 +670,7 @@ static void print_preparing_worktree_line(int detach, * * Returns 0 on failure and non-zero on success. */ -static int first_valid_ref(const char *refname UNUSED, - const char *referent UNUSED, - const struct object_id *oid UNUSED, - int flags UNUSED, - void *cb_data UNUSED) +static int first_valid_ref(const struct reference *ref UNUSED, void *cb_data UNUSED) { return 1; } @@ -661,25 +692,8 @@ static int can_use_local_refs(const struct add_opts *opts) if (refs_head_ref(get_main_ref_store(the_repository), first_valid_ref, NULL)) { return 1; } else if (refs_for_each_branch_ref(get_main_ref_store(the_repository), first_valid_ref, NULL)) { - if (!opts->quiet) { - struct strbuf path = STRBUF_INIT; - struct strbuf contents = STRBUF_INIT; - char *wt_gitdir = get_worktree_git_dir(NULL); - - strbuf_add_real_path(&path, wt_gitdir); - strbuf_addstr(&path, "/HEAD"); - strbuf_read_file(&contents, path.buf, 64); - strbuf_stripspace(&contents, NULL); - strbuf_strip_suffix(&contents, "\n"); - - warning(_("HEAD points to an invalid (or orphaned) reference.\n" - "HEAD path: '%s'\n" - "HEAD contents: '%s'"), - path.buf, contents.buf); - strbuf_release(&path); - strbuf_release(&contents); - free(wt_gitdir); - } + if (!opts->quiet) + warning(_("HEAD points to an invalid (or orphaned) reference.\n")); return 1; } return 0; @@ -979,14 +993,18 @@ static void show_worktree_porcelain(struct worktree *wt, int line_terminator) fputc(line_terminator, stdout); } -static void show_worktree(struct worktree *wt, int path_maxlen, int abbrev_len) +struct worktree_display { + char *path; + int width; +}; + +static void show_worktree(struct worktree *wt, struct worktree_display *display, + int path_maxwidth, int abbrev_len) { struct strbuf sb = STRBUF_INIT; - int cur_path_len = strlen(wt->path); - int path_adj = cur_path_len - utf8_strwidth(wt->path); const char *reason; - strbuf_addf(&sb, "%-*s ", 1 + path_maxlen + path_adj, wt->path); + strbuf_addf(&sb, "%s%*s", display->path, 1 + path_maxwidth - display->width, ""); if (wt->is_bare) strbuf_addstr(&sb, "(bare)"); else { @@ -1020,20 +1038,27 @@ static void show_worktree(struct worktree *wt, int path_maxlen, int abbrev_len) strbuf_release(&sb); } -static void measure_widths(struct worktree **wt, int *abbrev, int *maxlen) +static void measure_widths(struct worktree **wt, int *abbrev, + struct worktree_display **d, int *maxwidth) { - int i; + int i, display_alloc = 0; + struct worktree_display *display = NULL; + struct strbuf buf = STRBUF_INIT; for (i = 0; wt[i]; i++) { int sha1_len; - int path_len = strlen(wt[i]->path); + ALLOC_GROW(display, i + 1, display_alloc); + quote_path(wt[i]->path, NULL, &buf, 0); + display[i].width = utf8_strwidth(buf.buf); + display[i].path = strbuf_detach(&buf, NULL); - if (path_len > *maxlen) - *maxlen = path_len; + if (display[i].width > *maxwidth) + *maxwidth = display[i].width; sha1_len = strlen(repo_find_unique_abbrev(the_repository, &wt[i]->head_oid, *abbrev)); if (sha1_len > *abbrev) *abbrev = sha1_len; } + *d = display; } static int pathcmp(const void *a_, const void *b_) @@ -1063,7 +1088,7 @@ static int list(int ac, const char **av, const char *prefix, OPT_BOOL(0, "porcelain", &porcelain, N_("machine-readable output")), OPT__VERBOSE(&verbose, N_("show extended annotations and reasons, if available")), OPT_EXPIRY_DATE(0, "expire", &expire, - N_("add 'prunable' annotation to worktrees older than <time>")), + N_("add 'prunable' annotation to missing worktrees older than <time>")), OPT_SET_INT('z', NULL, &line_terminator, N_("terminate records with a NUL character"), '\0'), OPT_END() @@ -1079,21 +1104,27 @@ static int list(int ac, const char **av, const char *prefix, die(_("the option '%s' requires '%s'"), "-z", "--porcelain"); else { struct worktree **worktrees = get_worktrees(); - int path_maxlen = 0, abbrev = DEFAULT_ABBREV, i; + int path_maxwidth = 0, abbrev = DEFAULT_ABBREV, i; + struct worktree_display *display = NULL; /* sort worktrees by path but keep main worktree at top */ pathsort(worktrees + 1); if (!porcelain) - measure_widths(worktrees, &abbrev, &path_maxlen); + measure_widths(worktrees, &abbrev, + &display, &path_maxwidth); for (i = 0; worktrees[i]; i++) { if (porcelain) show_worktree_porcelain(worktrees[i], line_terminator); else - show_worktree(worktrees[i], path_maxlen, abbrev); + show_worktree(worktrees[i], + &display[i], path_maxwidth, abbrev); } + for (i = 0; display && worktrees[i]; i++) + free(display[i].path); + free(display); free_worktrees(worktrees); } return 0; @@ -1178,14 +1209,14 @@ static void validate_no_submodules(const struct worktree *wt) wt_gitdir = get_worktree_git_dir(wt); - if (is_directory(worktree_git_path(the_repository, wt, "modules"))) { + if (is_directory(worktree_git_path(wt, "modules"))) { /* * There could be false positives, e.g. the "modules" * directory exists but is empty. But it's a rare case and * this simpler check is probably good enough for now. */ found_submodules = 1; - } else if (read_index_from(&istate, worktree_git_path(the_repository, wt, "index"), + } else if (read_index_from(&istate, worktree_git_path(wt, "index"), wt_gitdir) > 0) { for (i = 0; i < istate.cache_nr; i++) { struct cache_entry *ce = istate.cache[i]; |
