diff options
Diffstat (limited to 'wt-status.c')
-rw-r--r-- | wt-status.c | 187 |
1 files changed, 117 insertions, 70 deletions
diff --git a/wt-status.c b/wt-status.c index 867e3e4..bdfc23e 100644 --- a/wt-status.c +++ b/wt-status.c @@ -1,9 +1,16 @@ -#include "cache.h" +#include "git-compat-util.h" +#include "advice.h" #include "wt-status.h" #include "object.h" #include "dir.h" #include "commit.h" #include "diff.h" +#include "environment.h" +#include "gettext.h" +#include "hash.h" +#include "hex.h" +#include "object-name.h" +#include "path.h" #include "revision.h" #include "diffcore.h" #include "quote.h" @@ -13,13 +20,20 @@ #include "refs.h" #include "submodule.h" #include "column.h" +#include "read-cache.h" +#include "setup.h" #include "strbuf.h" +#include "trace.h" +#include "trace2.h" +#include "tree.h" #include "utf8.h" #include "worktree.h" #include "lockfile.h" #include "sequencer.h" +#include "fsmonitor-settings.h" #define AB_DELAY_WARNING_IN_MS (2 * 1000) +#define UF_DELAY_WARNING_IN_MS (2 * 1000) static const char cut_line[] = "------------------------ >8 ------------------------\n"; @@ -56,7 +70,7 @@ static void status_vprintf(struct wt_status *s, int at_bol, const char *color, strbuf_vaddf(&sb, fmt, ap); if (!sb.len) { if (s->display_comment_prefix) { - strbuf_addch(&sb, comment_line_char); + strbuf_addstr(&sb, comment_line_str); if (!trail) strbuf_addch(&sb, ' '); } @@ -71,7 +85,7 @@ static void status_vprintf(struct wt_status *s, int at_bol, const char *color, strbuf_reset(&linebuf); if (at_bol && s->display_comment_prefix) { - strbuf_addch(&linebuf, comment_line_char); + strbuf_addstr(&linebuf, comment_line_str); if (*line != '\n' && *line != '\t') strbuf_addch(&linebuf, ' '); } @@ -438,7 +452,7 @@ static char short_submodule_status(struct wt_status_change_data *d) } static void wt_status_collect_changed_cb(struct diff_queue_struct *q, - struct diff_options *options, + struct diff_options *options UNUSED, void *data) { struct wt_status *s = data; @@ -525,7 +539,7 @@ static int unmerged_mask(struct index_state *istate, const char *path) } static void wt_status_collect_updated_cb(struct diff_queue_struct *q, - struct diff_options *options, + struct diff_options *options UNUSED, void *data) { struct wt_status *s = data; @@ -661,7 +675,7 @@ static void wt_status_collect_changes_index(struct wt_status *s) rev.diffopt.flags.recursive = 1; copy_pathspec(&rev.prune_data, &s->pathspec); - run_diff_index(&rev, 1); + run_diff_index(&rev, DIFF_INDEX_CACHED); release_revisions(&rev); } @@ -725,7 +739,7 @@ static void wt_status_collect_changes_initial(struct wt_status *s) ps.max_depth = -1; strbuf_add(&base, ce->name, ce->ce_namelen); - read_tree_at(istate->repo, tree, &base, &ps, + read_tree_at(istate->repo, tree, &base, 0, &ps, add_file_to_list, s); continue; } @@ -847,6 +861,7 @@ void wt_status_state_free_buffers(struct wt_status_state *state) FREE_AND_NULL(state->branch); FREE_AND_NULL(state->onto); FREE_AND_NULL(state->detached_from); + FREE_AND_NULL(state->bisecting_from); } static void wt_longstatus_print_unmerged(struct wt_status *s) @@ -947,9 +962,11 @@ static void wt_longstatus_print_changed(struct wt_status *s) wt_longstatus_print_trailer(s); } -static int stash_count_refs(struct object_id *ooid, struct object_id *noid, - const char *email, timestamp_t timestamp, int tz, - const char *message, void *cb_data) +static int stash_count_refs(struct object_id *ooid UNUSED, + struct object_id *noid UNUSED, + const char *email UNUSED, + timestamp_t timestamp UNUSED, int tz UNUSED, + const char *message UNUSED, void *cb_data) { int *c = cb_data; (*c)++; @@ -1011,7 +1028,7 @@ static void wt_longstatus_print_submodule_summary(struct wt_status *s, int uncom if (s->display_comment_prefix) { size_t len; summary_content = strbuf_detach(&summary, &len); - strbuf_add_commented_lines(&summary, summary_content, len); + strbuf_add_commented_lines(&summary, summary_content, len, comment_line_str); free(summary_content); } @@ -1073,11 +1090,14 @@ size_t wt_status_locate_end(const char *s, size_t len) const char *p; struct strbuf pattern = STRBUF_INIT; - strbuf_addf(&pattern, "\n%c %s", comment_line_char, cut_line); + strbuf_addf(&pattern, "\n%s %s", comment_line_str, cut_line); if (starts_with(s, pattern.buf + 1)) len = 0; - else if ((p = strstr(s, pattern.buf))) - len = p - s + 1; + else if ((p = strstr(s, pattern.buf))) { + size_t newlen = p - s + 1; + if (newlen < len) + len = newlen; + } strbuf_release(&pattern); return len; } @@ -1086,16 +1106,19 @@ void wt_status_append_cut_line(struct strbuf *buf) { const char *explanation = _("Do not modify or remove the line above.\nEverything below it will be ignored."); - strbuf_commented_addf(buf, "%s", cut_line); - strbuf_add_commented_lines(buf, explanation, strlen(explanation)); + strbuf_commented_addf(buf, comment_line_str, "%s", cut_line); + strbuf_add_commented_lines(buf, explanation, strlen(explanation), comment_line_str); } -void wt_status_add_cut_line(FILE *fp) +void wt_status_add_cut_line(struct wt_status *s) { struct strbuf buf = STRBUF_INIT; + if (s->added_cut_line) + return; + s->added_cut_line = 1; wt_status_append_cut_line(&buf); - fputs(buf.buf, fp); + fputs(buf.buf, s->fp); strbuf_release(&buf); } @@ -1126,11 +1149,12 @@ static void wt_longstatus_print_verbose(struct wt_status *s) * file (and even the "auto" setting won't work, since it * will have checked isatty on stdout). But we then do want * to insert the scissor line here to reliably remove the - * diff before committing. + * diff before committing, if we didn't already include one + * before. */ if (s->fp != stdout) { rev.diffopt.use_color = 0; - wt_status_add_cut_line(s->fp); + wt_status_add_cut_line(s); } if (s->verbose > 1 && s->committable) { /* print_updated() printed a header, so do we */ @@ -1140,7 +1164,7 @@ static void wt_longstatus_print_verbose(struct wt_status *s) rev.diffopt.a_prefix = "c/"; rev.diffopt.b_prefix = "i/"; } /* else use prefix as per user config */ - run_diff_index(&rev, 1); + run_diff_index(&rev, DIFF_INDEX_CACHED); if (s->verbose > 1 && wt_status_check_worktree_changes(s, &dirty_submodules)) { status_printf_ln(s, c, @@ -1159,8 +1183,6 @@ static void wt_longstatus_print_tracking(struct wt_status *s) struct strbuf sb = STRBUF_INIT; const char *cp, *ep, *branch_name; struct branch *branch; - char comment_line_string[3]; - int i; uint64_t t_begin = 0; assert(s->branch && !s->is_initial); @@ -1170,7 +1192,8 @@ static void wt_longstatus_print_tracking(struct wt_status *s) t_begin = getnanotime(); - if (!format_tracking_info(branch, &sb, s->ahead_behind_flags)) + if (!format_tracking_info(branch, &sb, s->ahead_behind_flags, + !s->commit_template)) return; if (advice_enabled(ADVICE_STATUS_AHEAD_BEHIND_WARNING) && @@ -1184,25 +1207,27 @@ static void wt_longstatus_print_tracking(struct wt_status *s) } } - i = 0; - if (s->display_comment_prefix) { - comment_line_string[i++] = comment_line_char; - comment_line_string[i++] = ' '; - } - comment_line_string[i] = '\0'; - for (cp = sb.buf; (ep = strchr(cp, '\n')) != NULL; cp = ep + 1) color_fprintf_ln(s->fp, color(WT_STATUS_HEADER, s), - "%s%.*s", comment_line_string, + "%s%s%.*s", + s->display_comment_prefix ? comment_line_str : "", + s->display_comment_prefix ? " " : "", (int)(ep - cp), cp); if (s->display_comment_prefix) - color_fprintf_ln(s->fp, color(WT_STATUS_HEADER, s), "%c", - comment_line_char); + color_fprintf_ln(s->fp, color(WT_STATUS_HEADER, s), "%s", + comment_line_str); else fputs("\n", s->fp); strbuf_release(&sb); } +static int uf_was_slow(struct wt_status *s) +{ + if (getenv("GIT_TEST_UF_DELAY_WARNING")) + s->untracked_in_ms = 3250; + return UF_DELAY_WARNING_IN_MS < s->untracked_in_ms; +} + static void show_merge_in_progress(struct wt_status *s, const char *color) { @@ -1271,26 +1296,32 @@ static char *read_line_from_git_path(const char *filename) static int split_commit_in_progress(struct wt_status *s) { int split_in_progress = 0; - char *head, *orig_head, *rebase_amend, *rebase_orig_head; + struct object_id head_oid, orig_head_oid; + char *rebase_amend, *rebase_orig_head; + int head_flags, orig_head_flags; if ((!s->amend && !s->nowarn && !s->workdir_dirty) || !s->branch || strcmp(s->branch, "HEAD")) return 0; - head = read_line_from_git_path("HEAD"); - orig_head = read_line_from_git_path("ORIG_HEAD"); + if (read_ref_full("HEAD", RESOLVE_REF_READING | RESOLVE_REF_NO_RECURSE, + &head_oid, &head_flags) || + read_ref_full("ORIG_HEAD", RESOLVE_REF_READING | RESOLVE_REF_NO_RECURSE, + &orig_head_oid, &orig_head_flags)) + return 0; + if (head_flags & REF_ISSYMREF || orig_head_flags & REF_ISSYMREF) + return 0; + rebase_amend = read_line_from_git_path("rebase-merge/amend"); rebase_orig_head = read_line_from_git_path("rebase-merge/orig-head"); - if (!head || !orig_head || !rebase_amend || !rebase_orig_head) + if (!rebase_amend || !rebase_orig_head) ; /* fall through, no split in progress */ else if (!strcmp(rebase_amend, rebase_orig_head)) - split_in_progress = !!strcmp(head, rebase_amend); - else if (strcmp(orig_head, rebase_orig_head)) + split_in_progress = !!strcmp(oid_to_hex(&head_oid), rebase_amend); + else if (strcmp(oid_to_hex(&orig_head_oid), rebase_orig_head)) split_in_progress = 1; - free(head); - free(orig_head); free(rebase_amend); free(rebase_orig_head); @@ -1326,7 +1357,7 @@ static void abbrev_oid_in_line(struct strbuf *line) * it after abbreviation. */ strbuf_trim(split[1]); - if (!get_oid(split[1]->buf, &oid)) { + if (!repo_get_oid(the_repository, split[1]->buf, &oid)) { strbuf_reset(split[1]); strbuf_add_unique_abbrev(split[1], &oid, DEFAULT_ABBREV); @@ -1351,7 +1382,7 @@ static int read_rebase_todolist(const char *fname, struct string_list *lines) git_path("%s", fname)); } while (!strbuf_getline_lf(&line, f)) { - if (line.len && line.buf[0] == comment_line_char) + if (starts_with(line.buf, comment_line_str)) continue; strbuf_trim(&line); if (!line.len) @@ -1492,8 +1523,8 @@ static void show_cherry_pick_in_progress(struct wt_status *s, else status_printf_ln(s, color, _("You are currently cherry-picking commit %s."), - find_unique_abbrev(&s->state.cherry_pick_head_oid, - DEFAULT_ABBREV)); + repo_find_unique_abbrev(the_repository, &s->state.cherry_pick_head_oid, + DEFAULT_ABBREV)); if (s->hints) { if (has_unmerged(s)) @@ -1522,8 +1553,8 @@ static void show_revert_in_progress(struct wt_status *s, else status_printf_ln(s, color, _("You are currently reverting commit %s."), - find_unique_abbrev(&s->state.revert_head_oid, - DEFAULT_ABBREV)); + repo_find_unique_abbrev(the_repository, &s->state.revert_head_oid, + DEFAULT_ABBREV)); if (s->hints) { if (has_unmerged(s)) status_printf_ln(s, color, @@ -1545,10 +1576,10 @@ static void show_revert_in_progress(struct wt_status *s, static void show_bisect_in_progress(struct wt_status *s, const char *color) { - if (s->state.branch) + if (s->state.bisecting_from) status_printf_ln(s, color, _("You are currently bisecting, started from branch '%s'."), - s->state.branch); + s->state.bisecting_from); else status_printf_ln(s, color, _("You are currently bisecting.")); @@ -1612,8 +1643,10 @@ struct grab_1st_switch_cbdata { struct object_id noid; }; -static int grab_1st_switch(struct object_id *ooid, struct object_id *noid, - const char *email, timestamp_t timestamp, int tz, +static int grab_1st_switch(struct object_id *ooid UNUSED, + struct object_id *noid, + const char *email UNUSED, + timestamp_t timestamp UNUSED, int tz UNUSED, const char *message, void *cb_data) { struct grab_1st_switch_cbdata *cb = cb_data; @@ -1651,7 +1684,8 @@ static void wt_status_get_detached_from(struct repository *r, return; } - if (dwim_ref(cb.buf.buf, cb.buf.len, &oid, &ref, 1) == 1 && + if (repo_dwim_ref(r, cb.buf.buf, cb.buf.len, &oid, &ref, + 1) == 1 && /* oid is a commit? match without further lookup */ (oideq(&cb.noid, &oid) || /* perhaps oid is a tag, try to dereference to a commit */ @@ -1663,9 +1697,9 @@ static void wt_status_get_detached_from(struct repository *r, state->detached_from = xstrdup(from); } else state->detached_from = - xstrdup(find_unique_abbrev(&cb.noid, DEFAULT_ABBREV)); + xstrdup(repo_find_unique_abbrev(r, &cb.noid, DEFAULT_ABBREV)); oidcpy(&state->detached_oid, &cb.noid); - state->detached_at = !get_oid("HEAD", &oid) && + state->detached_at = !repo_get_oid(r, "HEAD", &oid) && oideq(&oid, &state->detached_oid); free(ref); @@ -1706,7 +1740,7 @@ int wt_status_check_bisect(const struct worktree *wt, if (!stat(worktree_git_path(wt, "BISECT_LOG"), &st)) { state->bisect_in_progress = 1; - state->branch = get_branch(wt, "BISECT_START"); + state->bisecting_from = get_branch(wt, "BISECT_START"); return 1; } return 0; @@ -1756,21 +1790,21 @@ void wt_status_get_state(struct repository *r, } else if (wt_status_check_rebase(NULL, state)) { ; /* all set */ } else if (refs_ref_exists(get_main_ref_store(r), "CHERRY_PICK_HEAD") && - !get_oid("CHERRY_PICK_HEAD", &oid)) { + !repo_get_oid(r, "CHERRY_PICK_HEAD", &oid)) { state->cherry_pick_in_progress = 1; oidcpy(&state->cherry_pick_head_oid, &oid); } wt_status_check_bisect(NULL, state); if (refs_ref_exists(get_main_ref_store(r), "REVERT_HEAD") && - !get_oid("REVERT_HEAD", &oid)) { + !repo_get_oid(r, "REVERT_HEAD", &oid)) { state->revert_in_progress = 1; oidcpy(&state->revert_head_oid, &oid); } if (!sequencer_get_last_command(r, &action)) { - if (action == REPLAY_PICK) { + if (action == REPLAY_PICK && !state->cherry_pick_in_progress) { state->cherry_pick_in_progress = 1; oidcpy(&state->cherry_pick_head_oid, null_oid()); - } else { + } else if (action == REPLAY_REVERT && !state->revert_in_progress) { state->revert_in_progress = 1; oidcpy(&state->revert_head_oid, null_oid()); } @@ -1810,6 +1844,7 @@ static void wt_longstatus_print(struct wt_status *s) { const char *branch_color = color(WT_STATUS_ONBRANCH, s); const char *branch_status_color = color(WT_STATUS_HEADER, s); + enum fsmonitor_mode fsm_mode = fsm_settings__get_mode(s->repo); if (s->branch) { const char *on_what = _("On branch "); @@ -1866,13 +1901,21 @@ static void wt_longstatus_print(struct wt_status *s) wt_longstatus_print_other(s, &s->untracked, _("Untracked files"), "add"); if (s->show_ignored_mode) wt_longstatus_print_other(s, &s->ignored, _("Ignored files"), "add -f"); - if (advice_enabled(ADVICE_STATUS_U_OPTION) && 2000 < s->untracked_in_ms) { + if (advice_enabled(ADVICE_STATUS_U_OPTION) && uf_was_slow(s)) { status_printf_ln(s, GIT_COLOR_NORMAL, "%s", ""); + if (fsm_mode > FSMONITOR_MODE_DISABLED) { + status_printf_ln(s, GIT_COLOR_NORMAL, + _("It took %.2f seconds to enumerate untracked files,\n" + "but the results were cached, and subsequent runs may be faster."), + s->untracked_in_ms / 1000.0); + } else { + status_printf_ln(s, GIT_COLOR_NORMAL, + _("It took %.2f seconds to enumerate untracked files."), + s->untracked_in_ms / 1000.0); + } status_printf_ln(s, GIT_COLOR_NORMAL, - _("It took %.2f seconds to enumerate untracked files. 'status -uno'\n" - "may speed it up, but you have to be careful not to forget to add\n" - "new files yourself (see 'git help status')."), - s->untracked_in_ms / 1000.0); + _("See 'git help status' for information on how to improve this.")); + status_printf_ln(s, GIT_COLOR_NORMAL, "%s", ""); } } else if (s->committable) status_printf_ln(s, GIT_COLOR_NORMAL, _("Untracked files not listed%s"), @@ -2544,8 +2587,8 @@ int has_unstaged_changes(struct repository *r, int ignore_submodules) } rev_info.diffopt.flags.quick = 1; diff_setup_done(&rev_info.diffopt); - result = run_diff_files(&rev_info, 0); - result = diff_result_code(&rev_info.diffopt, result); + run_diff_files(&rev_info, 0); + result = diff_result_code(&rev_info.diffopt); release_revisions(&rev_info); return result; } @@ -2578,8 +2621,8 @@ int has_uncommitted_changes(struct repository *r, } diff_setup_done(&rev_info.diffopt); - result = run_diff_index(&rev_info, 1); - result = diff_result_code(&rev_info.diffopt, result); + run_diff_index(&rev_info, DIFF_INDEX_CACHED); + result = diff_result_code(&rev_info.diffopt); release_revisions(&rev_info); return result; } @@ -2619,8 +2662,12 @@ int require_clean_work_tree(struct repository *r, } if (err) { - if (hint) + if (hint) { + if (!*hint) + BUG("empty hint passed to require_clean_work_tree();" + " use NULL instead"); error("%s", hint); + } if (!gently) exit(128); } |