va_end(ap);
}
-void wt_status_prepare(struct wt_status *s)
+void wt_status_prepare(struct repository *r, struct wt_status *s)
{
memset(s, 0, sizeof(*s));
+ s->repo = r;
memcpy(s->color_palette, default_wt_status_colors,
sizeof(default_wt_status_colors));
s->show_untracked_files = SHOW_NORMAL_UNTRACKED_FILES;
d->worktree_status = p->status;
if (S_ISGITLINK(p->two->mode)) {
d->dirty_submodule = p->two->dirty_submodule;
- d->new_submodule_commits = !!oidcmp(&p->one->oid,
- &p->two->oid);
+ d->new_submodule_commits = !oideq(&p->one->oid,
+ &p->two->oid);
if (s->status_format == STATUS_FORMAT_SHORT)
d->worktree_status = short_submodule_status(d);
}
}
}
-static int unmerged_mask(const char *path)
+static int unmerged_mask(struct index_state *istate, const char *path)
{
int pos, mask;
const struct cache_entry *ce;
- pos = cache_name_pos(path, strlen(path));
+ pos = index_name_pos(istate, path, strlen(path));
if (0 <= pos)
return 0;
mask = 0;
pos = -pos-1;
- while (pos < active_nr) {
- ce = active_cache[pos++];
+ while (pos < istate->cache_nr) {
+ ce = istate->cache[pos++];
if (strcmp(ce->name, path) || !ce_stage(ce))
break;
mask |= (1 << (ce_stage(ce) - 1));
/* Leave {mode,oid}_head zero for an add. */
d->mode_index = p->two->mode;
oidcpy(&d->oid_index, &p->two->oid);
+ s->committable = 1;
break;
case DIFF_STATUS_DELETED:
d->mode_head = p->one->mode;
oidcpy(&d->oid_head, &p->one->oid);
+ s->committable = 1;
/* Leave {mode,oid}_index zero for a delete. */
break;
d->mode_index = p->two->mode;
oidcpy(&d->oid_head, &p->one->oid);
oidcpy(&d->oid_index, &p->two->oid);
+ s->committable = 1;
break;
case DIFF_STATUS_UNMERGED:
- d->stagemask = unmerged_mask(p->two->path);
+ d->stagemask = unmerged_mask(s->repo->index,
+ p->two->path);
/*
* Don't bother setting {mode,oid}_{head,index} since the print
* code will output the stage values directly and not use the
{
struct rev_info rev;
- init_revisions(&rev, NULL);
+ repo_init_revisions(s->repo, &rev, NULL);
setup_revisions(0, NULL, &rev, NULL);
rev.diffopt.output_format |= DIFF_FORMAT_CALLBACK;
rev.diffopt.flags.dirty_submodules = 1;
struct rev_info rev;
struct setup_revision_opt opt;
- init_revisions(&rev, NULL);
+ repo_init_revisions(s->repo, &rev, NULL);
memset(&opt, 0, sizeof(opt));
opt.def = s->is_initial ? empty_tree_oid_hex() : s->reference;
setup_revisions(0, NULL, &rev, &opt);
static void wt_status_collect_changes_initial(struct wt_status *s)
{
+ struct index_state *istate = s->repo->index;
int i;
- for (i = 0; i < active_nr; i++) {
+ for (i = 0; i < istate->cache_nr; i++) {
struct string_list_item *it;
struct wt_status_change_data *d;
- const struct cache_entry *ce = active_cache[i];
+ const struct cache_entry *ce = istate->cache[i];
- if (!ce_path_match(&the_index, ce, &s->pathspec, NULL))
+ if (!ce_path_match(istate, ce, &s->pathspec, NULL))
continue;
if (ce_intent_to_add(ce))
continue;
* code will output the stage values directly and not use the
* values in these fields.
*/
+ s->committable = 1;
} else {
d->index_status = DIFF_STATUS_ADDED;
/* Leave {mode,oid}_head zero for adds. */
d->mode_index = ce->ce_mode;
oidcpy(&d->oid_index, &ce->oid);
+ s->committable = 1;
}
}
}
int i;
struct dir_struct dir;
uint64_t t_begin = getnanotime();
+ struct index_state *istate = s->repo->index;
if (!s->show_untracked_files)
return;
if (s->show_ignored_mode == SHOW_MATCHING_IGNORED)
dir.flags |= DIR_SHOW_IGNORED_TOO_MODE_MATCHING;
} else {
- dir.untracked = the_index.untracked;
+ dir.untracked = istate->untracked;
}
setup_standard_excludes(&dir);
- fill_directory(&dir, &the_index, &s->pathspec);
+ fill_directory(&dir, istate, &s->pathspec);
for (i = 0; i < dir.nr; i++) {
struct dir_entry *ent = dir.entries[i];
- if (cache_name_is_other(ent->name, ent->len) &&
- dir_path_match(&the_index, ent, &s->pathspec, 0, NULL))
+ if (index_name_is_other(istate, ent->name, ent->len) &&
+ dir_path_match(istate, ent, &s->pathspec, 0, NULL))
string_list_insert(&s->untracked, ent->name);
free(ent);
}
for (i = 0; i < dir.ignored_nr; i++) {
struct dir_entry *ent = dir.ignored[i];
- if (cache_name_is_other(ent->name, ent->len) &&
- dir_path_match(&the_index, ent, &s->pathspec, 0, NULL))
+ if (index_name_is_other(istate, ent->name, ent->len) &&
+ dir_path_match(istate, ent, &s->pathspec, 0, NULL))
string_list_insert(&s->ignored, ent->name);
free(ent);
}
s->untracked_in_ms = (getnanotime() - t_begin) / 1000000;
}
+static int has_unmerged(struct wt_status *s)
+{
+ int i;
+
+ for (i = 0; i < s->change.nr; i++) {
+ struct wt_status_change_data *d;
+ d = s->change.items[i].util;
+ if (d->stagemask)
+ return 1;
+ }
+ return 0;
+}
+
void wt_status_collect(struct wt_status *s)
{
wt_status_collect_changes_worktree(s);
-
if (s->is_initial)
wt_status_collect_changes_initial(s);
else
wt_status_collect_changes_index(s);
wt_status_collect_untracked(s);
+
+ wt_status_get_state(s->repo, &s->state, s->branch && !strcmp(s->branch, "HEAD"));
+ if (s->state.merge_in_progress && !has_unmerged(s))
+ s->committable = 1;
+}
+
+void wt_status_collect_free_buffers(struct wt_status *s)
+{
+ free(s->state.branch);
+ free(s->state.onto);
+ free(s->state.detached_from);
}
static void wt_longstatus_print_unmerged(struct wt_status *s)
continue;
if (!shown_header) {
wt_longstatus_print_cached_header(s);
- s->commitable = 1;
shown_header = 1;
}
wt_longstatus_print_change_data(s, WT_STATUS_UPDATED, it);
int dirty_submodules;
const char *c = color(WT_STATUS_HEADER, s);
- init_revisions(&rev, NULL);
+ repo_init_revisions(s->repo, &rev, NULL);
rev.diffopt.flags.allow_textconv = 1;
rev.diffopt.ita_invisible_in_index = 1;
rev.diffopt.use_color = 0;
wt_status_add_cut_line(s->fp);
}
- if (s->verbose > 1 && s->commitable) {
+ if (s->verbose > 1 && s->committable) {
/* print_updated() printed a header, so do we */
if (s->fp != stdout)
wt_longstatus_print_trailer(s);
strbuf_release(&sb);
}
-static int has_unmerged(struct wt_status *s)
-{
- int i;
-
- for (i = 0; i < s->change.nr; i++) {
- struct wt_status_change_data *d;
- d = s->change.items[i].util;
- if (d->stagemask)
- return 1;
- }
- return 0;
-}
-
static void show_merge_in_progress(struct wt_status *s,
- struct wt_status_state *state,
- const char *color)
+ const char *color)
{
if (has_unmerged(s)) {
status_printf_ln(s, color, _("You have unmerged paths."));
_(" (use \"git merge --abort\" to abort the merge)"));
}
} else {
- s-> commitable = 1;
status_printf_ln(s, color,
_("All conflicts fixed but you are still merging."));
if (s->hints)
}
static void show_am_in_progress(struct wt_status *s,
- struct wt_status_state *state,
const char *color)
{
status_printf_ln(s, color,
_("You are in the middle of an am session."));
- if (state->am_empty_patch)
+ if (s->state.am_empty_patch)
status_printf_ln(s, color,
_("The current patch is empty."));
if (s->hints) {
- if (!state->am_empty_patch)
+ if (!s->state.am_empty_patch)
status_printf_ln(s, color,
_(" (fix conflicts and then run \"git am --continue\")"));
status_printf_ln(s, color,
}
static void show_rebase_information(struct wt_status *s,
- struct wt_status_state *state,
- const char *color)
+ const char *color)
{
- if (state->rebase_interactive_in_progress) {
+ if (s->state.rebase_interactive_in_progress) {
int i;
int nr_lines_to_show = 2;
}
static void print_rebase_state(struct wt_status *s,
- struct wt_status_state *state,
- const char *color)
+ const char *color)
{
- if (state->branch)
+ if (s->state.branch)
status_printf_ln(s, color,
_("You are currently rebasing branch '%s' on '%s'."),
- state->branch,
- state->onto);
+ s->state.branch,
+ s->state.onto);
else
status_printf_ln(s, color,
_("You are currently rebasing."));
}
static void show_rebase_in_progress(struct wt_status *s,
- struct wt_status_state *state,
- const char *color)
+ const char *color)
{
struct stat st;
- show_rebase_information(s, state, color);
+ show_rebase_information(s, color);
if (has_unmerged(s)) {
- print_rebase_state(s, state, color);
+ print_rebase_state(s, color);
if (s->hints) {
status_printf_ln(s, color,
_(" (fix conflicts and then run \"git rebase --continue\")"));
status_printf_ln(s, color,
_(" (use \"git rebase --abort\" to check out the original branch)"));
}
- } else if (state->rebase_in_progress || !stat(git_path_merge_msg(the_repository), &st)) {
- print_rebase_state(s, state, color);
+ } else if (s->state.rebase_in_progress ||
+ !stat(git_path_merge_msg(s->repo), &st)) {
+ print_rebase_state(s, color);
if (s->hints)
status_printf_ln(s, color,
_(" (all conflicts fixed: run \"git rebase --continue\")"));
} else if (split_commit_in_progress(s)) {
- if (state->branch)
+ if (s->state.branch)
status_printf_ln(s, color,
_("You are currently splitting a commit while rebasing branch '%s' on '%s'."),
- state->branch,
- state->onto);
+ s->state.branch,
+ s->state.onto);
else
status_printf_ln(s, color,
_("You are currently splitting a commit during a rebase."));
status_printf_ln(s, color,
_(" (Once your working directory is clean, run \"git rebase --continue\")"));
} else {
- if (state->branch)
+ if (s->state.branch)
status_printf_ln(s, color,
_("You are currently editing a commit while rebasing branch '%s' on '%s'."),
- state->branch,
- state->onto);
+ s->state.branch,
+ s->state.onto);
else
status_printf_ln(s, color,
_("You are currently editing a commit during a rebase."));
}
static void show_cherry_pick_in_progress(struct wt_status *s,
- struct wt_status_state *state,
- const char *color)
+ const char *color)
{
status_printf_ln(s, color, _("You are currently cherry-picking commit %s."),
- find_unique_abbrev(&state->cherry_pick_head_oid, DEFAULT_ABBREV));
+ find_unique_abbrev(&s->state.cherry_pick_head_oid, DEFAULT_ABBREV));
if (s->hints) {
if (has_unmerged(s))
status_printf_ln(s, color,
}
static void show_revert_in_progress(struct wt_status *s,
- struct wt_status_state *state,
- const char *color)
+ const char *color)
{
status_printf_ln(s, color, _("You are currently reverting commit %s."),
- find_unique_abbrev(&state->revert_head_oid, DEFAULT_ABBREV));
+ find_unique_abbrev(&s->state.revert_head_oid, DEFAULT_ABBREV));
if (s->hints) {
if (has_unmerged(s))
status_printf_ln(s, color,
}
static void show_bisect_in_progress(struct wt_status *s,
- struct wt_status_state *state,
- const char *color)
+ const char *color)
{
- if (state->branch)
+ if (s->state.branch)
status_printf_ln(s, color,
_("You are currently bisecting, started from branch '%s'."),
- state->branch);
+ s->state.branch);
else
status_printf_ln(s, color,
_("You are currently bisecting."));
return 1;
}
-static void wt_status_get_detached_from(struct wt_status_state *state)
+static void wt_status_get_detached_from(struct repository *r,
+ struct wt_status_state *state)
{
struct grab_1st_switch_cbdata cb;
struct commit *commit;
if (dwim_ref(cb.buf.buf, cb.buf.len, &oid, &ref) == 1 &&
/* sha1 is a commit? match without further lookup */
- (!oidcmp(&cb.noid, &oid) ||
+ (oideq(&cb.noid, &oid) ||
/* perhaps sha1 is a tag, try to dereference to a commit */
- ((commit = lookup_commit_reference_gently(the_repository, &oid, 1)) != NULL &&
- !oidcmp(&cb.noid, &commit->object.oid)))) {
+ ((commit = lookup_commit_reference_gently(r, &oid, 1)) != NULL &&
+ oideq(&cb.noid, &commit->object.oid)))) {
const char *from = ref;
if (!skip_prefix(from, "refs/tags/", &from))
skip_prefix(from, "refs/remotes/", &from);
xstrdup(find_unique_abbrev(&cb.noid, DEFAULT_ABBREV));
oidcpy(&state->detached_oid, &cb.noid);
state->detached_at = !get_oid("HEAD", &oid) &&
- !oidcmp(&oid, &state->detached_oid);
+ oideq(&oid, &state->detached_oid);
free(ref);
strbuf_release(&cb.buf);
return 0;
}
-void wt_status_get_state(struct wt_status_state *state,
+void wt_status_get_state(struct repository *r,
+ struct wt_status_state *state,
int get_detached_from)
{
struct stat st;
struct object_id oid;
- if (!stat(git_path_merge_head(the_repository), &st)) {
+ if (!stat(git_path_merge_head(r), &st)) {
+ wt_status_check_rebase(NULL, state);
state->merge_in_progress = 1;
} else if (wt_status_check_rebase(NULL, state)) {
; /* all set */
- } else if (!stat(git_path_cherry_pick_head(the_repository), &st) &&
+ } else if (!stat(git_path_cherry_pick_head(r), &st) &&
!get_oid("CHERRY_PICK_HEAD", &oid)) {
state->cherry_pick_in_progress = 1;
oidcpy(&state->cherry_pick_head_oid, &oid);
}
wt_status_check_bisect(NULL, state);
- if (!stat(git_path_revert_head(the_repository), &st) &&
+ if (!stat(git_path_revert_head(r), &st) &&
!get_oid("REVERT_HEAD", &oid)) {
state->revert_in_progress = 1;
oidcpy(&state->revert_head_oid, &oid);
}
if (get_detached_from)
- wt_status_get_detached_from(state);
+ wt_status_get_detached_from(r, state);
}
-static void wt_longstatus_print_state(struct wt_status *s,
- struct wt_status_state *state)
+static void wt_longstatus_print_state(struct wt_status *s)
{
const char *state_color = color(WT_STATUS_HEADER, s);
- if (state->merge_in_progress)
- show_merge_in_progress(s, state, state_color);
- else if (state->am_in_progress)
- show_am_in_progress(s, state, state_color);
+ struct wt_status_state *state = &s->state;
+
+ if (state->merge_in_progress) {
+ if (state->rebase_interactive_in_progress) {
+ show_rebase_information(s, state_color);
+ fputs("\n", s->fp);
+ }
+ show_merge_in_progress(s, state_color);
+ } else if (state->am_in_progress)
+ show_am_in_progress(s, state_color);
else if (state->rebase_in_progress || state->rebase_interactive_in_progress)
- show_rebase_in_progress(s, state, state_color);
+ show_rebase_in_progress(s, state_color);
else if (state->cherry_pick_in_progress)
- show_cherry_pick_in_progress(s, state, state_color);
+ show_cherry_pick_in_progress(s, state_color);
else if (state->revert_in_progress)
- show_revert_in_progress(s, state, state_color);
+ show_revert_in_progress(s, state_color);
if (state->bisect_in_progress)
- show_bisect_in_progress(s, state, state_color);
+ show_bisect_in_progress(s, state_color);
}
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);
- struct wt_status_state state;
-
- memset(&state, 0, sizeof(state));
- wt_status_get_state(&state,
- s->branch && !strcmp(s->branch, "HEAD"));
if (s->branch) {
const char *on_what = _("On branch ");
const char *branch_name = s->branch;
if (!strcmp(branch_name, "HEAD")) {
branch_status_color = color(WT_STATUS_NOBRANCH, s);
- if (state.rebase_in_progress || state.rebase_interactive_in_progress) {
- if (state.rebase_interactive_in_progress)
+ if (s->state.rebase_in_progress ||
+ s->state.rebase_interactive_in_progress) {
+ if (s->state.rebase_interactive_in_progress)
on_what = _("interactive rebase in progress; onto ");
else
on_what = _("rebase in progress; onto ");
- branch_name = state.onto;
- } else if (state.detached_from) {
- branch_name = state.detached_from;
- if (state.detached_at)
+ branch_name = s->state.onto;
+ } else if (s->state.detached_from) {
+ branch_name = s->state.detached_from;
+ if (s->state.detached_at)
on_what = _("HEAD detached at ");
else
on_what = _("HEAD detached from ");
wt_longstatus_print_tracking(s);
}
- wt_longstatus_print_state(s, &state);
- free(state.branch);
- free(state.onto);
- free(state.detached_from);
+ wt_longstatus_print_state(s);
if (s->is_initial) {
status_printf_ln(s, color(WT_STATUS_HEADER, s), "%s", "");
"new files yourself (see 'git help status')."),
s->untracked_in_ms / 1000.0);
}
- } else if (s->commitable)
+ } else if (s->committable)
status_printf_ln(s, GIT_COLOR_NORMAL, _("Untracked files not listed%s"),
s->hints
? _(" (use -u option to show untracked files)") : "");
if (s->verbose)
wt_longstatus_print_verbose(s);
- if (!s->commitable) {
+ if (!s->committable) {
if (s->amend)
status_printf_ln(s, GIT_COLOR_NORMAL, _("No changes"));
else if (s->nowarn)
struct branch *branch;
const char *base;
const char *branch_name;
- struct wt_status_state state;
int ab_info, nr_ahead, nr_behind;
char eol = s->null_termination ? '\0' : '\n';
- memset(&state, 0, sizeof(state));
- wt_status_get_state(&state, s->branch && !strcmp(s->branch, "HEAD"));
-
fprintf(s->fp, "# branch.oid %s%c",
(s->is_initial ? "(initial)" : sha1_to_hex(s->sha1_commit)),
eol);
if (!strcmp(s->branch, "HEAD")) {
fprintf(s->fp, "# branch.head %s%c", "(detached)", eol);
- if (state.rebase_in_progress || state.rebase_interactive_in_progress)
- branch_name = state.onto;
- else if (state.detached_from)
- branch_name = state.detached_from;
+ if (s->state.rebase_in_progress ||
+ s->state.rebase_interactive_in_progress)
+ branch_name = s->state.onto;
+ else if (s->state.detached_from)
+ branch_name = s->state.detached_from;
else
branch_name = "";
} else {
}
}
}
-
- free(state.branch);
- free(state.onto);
- free(state.detached_from);
}
/*
struct wt_status *s)
{
struct wt_status_change_data *d = it->util;
+ struct index_state *istate = s->repo->index;
const struct cache_entry *ce;
struct strbuf buf_index = STRBUF_INIT;
const char *path_index = NULL;
*/
memset(stages, 0, sizeof(stages));
sum = 0;
- pos = cache_name_pos(it->string, strlen(it->string));
+ pos = index_name_pos(istate, it->string, strlen(it->string));
assert(pos < 0);
pos = -pos-1;
- while (pos < active_nr) {
- ce = active_cache[pos++];
+ while (pos < istate->cache_nr) {
+ ce = istate->cache[pos++];
stage = ce_stage(ce);
if (strcmp(ce->name, it->string) || !stage)
break;
/**
* Returns 1 if there are unstaged changes, 0 otherwise.
*/
-int has_unstaged_changes(int ignore_submodules)
+int has_unstaged_changes(struct repository *r, int ignore_submodules)
{
struct rev_info rev_info;
int result;
- init_revisions(&rev_info, NULL);
+ repo_init_revisions(r, &rev_info, NULL);
if (ignore_submodules) {
rev_info.diffopt.flags.ignore_submodules = 1;
rev_info.diffopt.flags.override_submodule_config = 1;
/**
* Returns 1 if there are uncommitted changes, 0 otherwise.
*/
-int has_uncommitted_changes(int ignore_submodules)
+int has_uncommitted_changes(struct repository *r,
+ int ignore_submodules)
{
struct rev_info rev_info;
int result;
- if (is_cache_unborn())
+ if (is_index_unborn(r->index))
return 0;
- init_revisions(&rev_info, NULL);
+ repo_init_revisions(r, &rev_info, NULL);
if (ignore_submodules)
rev_info.diffopt.flags.ignore_submodules = 1;
rev_info.diffopt.flags.quick = 1;
* We have no head (or it's corrupt); use the empty tree,
* which will complain if the index is non-empty.
*/
- struct tree *tree = lookup_tree(the_repository, the_hash_algo->empty_tree);
+ struct tree *tree = lookup_tree(r, the_hash_algo->empty_tree);
add_pending_object(&rev_info, &tree->object, "");
}
* If the work tree has unstaged or uncommitted changes, dies with the
* appropriate message.
*/
-int require_clean_work_tree(const char *action, const char *hint, int ignore_submodules, int gently)
+int require_clean_work_tree(struct repository *r,
+ const char *action,
+ const char *hint,
+ int ignore_submodules,
+ int gently)
{
struct lock_file lock_file = LOCK_INIT;
int err = 0, fd;
fd = hold_locked_index(&lock_file, 0);
- refresh_cache(REFRESH_QUIET);
+ refresh_index(r->index, REFRESH_QUIET, NULL, NULL, NULL);
if (0 <= fd)
- update_index_if_able(&the_index, &lock_file);
+ update_index_if_able(r->index, &lock_file);
rollback_lock_file(&lock_file);
- if (has_unstaged_changes(ignore_submodules)) {
+ if (has_unstaged_changes(r, ignore_submodules)) {
/* TRANSLATORS: the action is e.g. "pull with rebase" */
error(_("cannot %s: You have unstaged changes."), _(action));
err = 1;
}
- if (has_uncommitted_changes(ignore_submodules)) {
+ if (has_uncommitted_changes(r, ignore_submodules)) {
if (err)
error(_("additionally, your index contains uncommitted changes."));
else