Skip to content

Commit

Permalink
git status: Show detailed dirty status of submodules in long format
Browse files Browse the repository at this point in the history
Since 1.7.0 there are three reasons a submodule is considered modified
against the work tree: It contains new commits, modified content or
untracked content. Lets show all reasons in the long format of git status,
so the user can better asses the nature of the modification. This change
does not affect the short and porcelain formats.

Two new members are added to "struct wt_status_change_data" to store the
information gathered by run_diff_files(). wt-status.c uses the new flag
DIFF_OPT_DIRTY_SUBMODULES to tell diff-lib.c it wants to get detailed
dirty information about submodules.

A hint line for submodules is printed in the dirty header when dirty
submodules are present.

Signed-off-by: Jens Lehmann <Jens.Lehmann@web.de>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
  • Loading branch information
Jens Lehmann authored and Junio C Hamano committed Mar 8, 2010
1 parent c7e1a73 commit 9297f77
Show file tree
Hide file tree
Showing 5 changed files with 46 additions and 12 deletions.
6 changes: 4 additions & 2 deletions diff-lib.c
Original file line number Diff line number Diff line change
Expand Up @@ -180,7 +180,8 @@ int run_diff_files(struct rev_info *revs, unsigned int option)
changed = ce_match_stat(ce, &st, ce_option);
if (S_ISGITLINK(ce->ce_mode)
&& !DIFF_OPT_TST(&revs->diffopt, IGNORE_SUBMODULES)
&& (!changed || (revs->diffopt.output_format & DIFF_FORMAT_PATCH))) {
&& (!changed || (revs->diffopt.output_format & DIFF_FORMAT_PATCH)
|| DIFF_OPT_TST(&revs->diffopt, DIRTY_SUBMODULES))) {
dirty_submodule = is_submodule_modified(ce->name);
if (dirty_submodule)
changed = 1;
Expand Down Expand Up @@ -243,7 +244,8 @@ static int get_stat_data(struct cache_entry *ce,
changed = ce_match_stat(ce, &st, 0);
if (S_ISGITLINK(ce->ce_mode)
&& !DIFF_OPT_TST(diffopt, IGNORE_SUBMODULES)
&& (!changed || (diffopt->output_format & DIFF_FORMAT_PATCH))) {
&& (!changed || (diffopt->output_format & DIFF_FORMAT_PATCH)
|| DIFF_OPT_TST(diffopt, DIRTY_SUBMODULES))) {
*dirty_submodule = is_submodule_modified(ce->name);
if (*dirty_submodule)
changed = 1;
Expand Down
1 change: 1 addition & 0 deletions diff.h
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ typedef void (*diff_format_fn_t)(struct diff_queue_struct *q,
#define DIFF_OPT_ALLOW_TEXTCONV (1 << 21)
#define DIFF_OPT_DIFF_FROM_CONTENTS (1 << 22)
#define DIFF_OPT_SUBMODULE_LOG (1 << 23)
#define DIFF_OPT_DIRTY_SUBMODULES (1 << 24)

#define DIFF_OPT_TST(opts, flag) ((opts)->flags & DIFF_OPT_##flag)
#define DIFF_OPT_SET(opts, flag) ((opts)->flags |= DIFF_OPT_##flag)
Expand Down
6 changes: 3 additions & 3 deletions t/t7506-status-submodule.sh
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ test_expect_success 'status with modified file in submodule' '
(cd sub && git reset --hard) &&
echo "changed" >sub/foo &&
git status >output &&
grep "modified: sub" output
grep "modified: sub (new commits, modified content)" output
'

test_expect_success 'status with modified file in submodule (porcelain)' '
Expand All @@ -49,7 +49,7 @@ test_expect_success 'status with modified file in submodule (porcelain)' '
test_expect_success 'status with added file in submodule' '
(cd sub && git reset --hard && echo >foo && git add foo) &&
git status >output &&
grep "modified: sub" output
grep "modified: sub (new commits, modified content)" output
'

test_expect_success 'status with added file in submodule (porcelain)' '
Expand All @@ -64,7 +64,7 @@ test_expect_success 'status with untracked file in submodule' '
(cd sub && git reset --hard) &&
echo "content" >sub/new-file &&
git status >output &&
grep "modified: sub" output
grep "modified: sub (new commits, untracked content)" output
'

test_expect_success 'status with untracked file in submodule (porcelain)' '
Expand Down
43 changes: 36 additions & 7 deletions wt-status.c
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,8 @@ static void wt_status_print_cached_header(struct wt_status *s)
}

static void wt_status_print_dirty_header(struct wt_status *s,
int has_deleted)
int has_deleted,
int has_dirty_submodules)
{
const char *c = color(WT_STATUS_HEADER, s);

Expand All @@ -90,6 +91,8 @@ static void wt_status_print_dirty_header(struct wt_status *s,
else
color_fprintf_ln(s->fp, c, "# (use \"git add/rm <file>...\" to update what will be committed)");
color_fprintf_ln(s->fp, c, "# (use \"git checkout -- <file>...\" to discard changes in working directory)");
if (has_dirty_submodules)
color_fprintf_ln(s->fp, c, "# (commit or discard the untracked or modified content in submodules)");
color_fprintf_ln(s->fp, c, "#");
}

Expand Down Expand Up @@ -144,6 +147,7 @@ static void wt_status_print_change_data(struct wt_status *s,
char *two_name;
const char *one, *two;
struct strbuf onebuf = STRBUF_INIT, twobuf = STRBUF_INIT;
struct strbuf extra = STRBUF_INIT;

one_name = two_name = it->string;
switch (change_type) {
Expand All @@ -153,6 +157,17 @@ static void wt_status_print_change_data(struct wt_status *s,
one_name = d->head_path;
break;
case WT_STATUS_CHANGED:
if (d->new_submodule_commits || d->dirty_submodule) {
strbuf_addstr(&extra, " (");
if (d->new_submodule_commits)
strbuf_addf(&extra, "new commits, ");
if (d->dirty_submodule & DIRTY_SUBMODULE_MODIFIED)
strbuf_addf(&extra, "modified content, ");
if (d->dirty_submodule & DIRTY_SUBMODULE_UNTRACKED)
strbuf_addf(&extra, "untracked content, ");
strbuf_setlen(&extra, extra.len - 2);
strbuf_addch(&extra, ')');
}
status = d->worktree_status;
break;
}
Expand Down Expand Up @@ -189,6 +204,10 @@ static void wt_status_print_change_data(struct wt_status *s,
default:
die("bug: unhandled diff status %c", status);
}
if (extra.len) {
color_fprintf(s->fp, color(WT_STATUS_HEADER, s), "%s", extra.buf);
strbuf_release(&extra);
}
fprintf(s->fp, "\n");
strbuf_release(&onebuf);
strbuf_release(&twobuf);
Expand Down Expand Up @@ -218,6 +237,9 @@ static void wt_status_collect_changed_cb(struct diff_queue_struct *q,
}
if (!d->worktree_status)
d->worktree_status = p->status;
d->dirty_submodule = p->two->dirty_submodule;
if (S_ISGITLINK(p->two->mode))
d->new_submodule_commits = !!hashcmp(p->one->sha1, p->two->sha1);
}
}

Expand Down Expand Up @@ -281,6 +303,7 @@ static void wt_status_collect_changes_worktree(struct wt_status *s)
init_revisions(&rev, NULL);
setup_revisions(0, NULL, &rev, NULL);
rev.diffopt.output_format |= DIFF_FORMAT_CALLBACK;
DIFF_OPT_SET(&rev.diffopt, DIRTY_SUBMODULES);
rev.diffopt.format_callback = wt_status_collect_changed_cb;
rev.diffopt.format_callback_data = s;
rev.prune_data = s->pathspec;
Expand Down Expand Up @@ -418,33 +441,39 @@ static void wt_status_print_updated(struct wt_status *s)
* 0 : no change
* 1 : some change but no delete
*/
static int wt_status_check_worktree_changes(struct wt_status *s)
static int wt_status_check_worktree_changes(struct wt_status *s,
int *dirty_submodules)
{
int i;
int changes = 0;

*dirty_submodules = 0;

for (i = 0; i < s->change.nr; i++) {
struct wt_status_change_data *d;
d = s->change.items[i].util;
if (!d->worktree_status ||
d->worktree_status == DIFF_STATUS_UNMERGED)
continue;
changes = 1;
if (!changes)
changes = 1;
if (d->dirty_submodule)
*dirty_submodules = 1;
if (d->worktree_status == DIFF_STATUS_DELETED)
return -1;
changes = -1;
}
return changes;
}

static void wt_status_print_changed(struct wt_status *s)
{
int i;
int worktree_changes = wt_status_check_worktree_changes(s);
int i, dirty_submodules;
int worktree_changes = wt_status_check_worktree_changes(s, &dirty_submodules);

if (!worktree_changes)
return;

wt_status_print_dirty_header(s, worktree_changes < 0);
wt_status_print_dirty_header(s, worktree_changes < 0, dirty_submodules);

for (i = 0; i < s->change.nr; i++) {
struct wt_status_change_data *d;
Expand Down
2 changes: 2 additions & 0 deletions wt-status.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ struct wt_status_change_data {
int index_status;
int stagemask;
char *head_path;
unsigned dirty_submodule : 2;
unsigned new_submodule_commits : 1;
};

struct wt_status {
Expand Down

0 comments on commit 9297f77

Please sign in to comment.