summaryrefslogtreecommitdiff
path: root/wt-status.c
diff options
context:
space:
mode:
Diffstat (limited to 'wt-status.c')
-rw-r--r--wt-status.c187
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);
}