Commit fd9b544a authored by Jeff Hostetler's avatar Jeff Hostetler Committed by Junio C Hamano

status: add --[no-]ahead-behind to status and commit for V2 format.

Teach "git status" and "git commit" to accept "--no-ahead-behind"
and "--ahead-behind" arguments to request quick or full ahead/behind
reporting.

When "--no-ahead-behind" is given, the existing porcelain V2 line
"branch.ab +x -y" is replaced with a new "branch.ab +? -?" line.
This indicates that the branch and its upstream are or are not equal
without the expense of computing the full ahead/behind values.
Signed-off-by: default avatarJeff Hostetler <jeffhost@microsoft.com>
Signed-off-by: default avatarJunio C Hamano <gitster@pobox.com>
parent d7d1b496
......@@ -130,6 +130,11 @@ ignored, then the directory is not shown, but all contents are shown.
without options are equivalent to 'always' and 'never'
respectively.
--ahead-behind::
--no-ahead-behind::
Display or do not display detailed ahead/behind counts for the
branch relative to its upstream branch. Defaults to true.
<pathspec>...::
See the 'pathspec' entry in linkgit:gitglossary[7].
......
......@@ -1151,6 +1151,9 @@ static void finalize_deferred_config(struct wt_status *s)
s->show_branch = status_deferred_config.show_branch;
if (s->show_branch < 0)
s->show_branch = 0;
if (s->ahead_behind_flags == AHEAD_BEHIND_UNSPECIFIED)
s->ahead_behind_flags = AHEAD_BEHIND_FULL;
}
static int parse_and_validate_options(int argc, const char *argv[],
......@@ -1365,6 +1368,8 @@ int cmd_status(int argc, const char **argv, const char *prefix)
N_("show branch information")),
OPT_BOOL(0, "show-stash", &s.show_stash,
N_("show stash information")),
OPT_BOOL(0, "ahead-behind", &s.ahead_behind_flags,
N_("compute full ahead/behind values")),
{ OPTION_CALLBACK, 0, "porcelain", &status_format,
N_("version"), N_("machine-readable output"),
PARSE_OPT_OPTARG, opt_parse_porcelain },
......@@ -1648,6 +1653,8 @@ int cmd_commit(int argc, const char **argv, const char *prefix)
OPT_SET_INT(0, "short", &status_format, N_("show status concisely"),
STATUS_FORMAT_SHORT),
OPT_BOOL(0, "branch", &s.show_branch, N_("show branch information")),
OPT_BOOL(0, "ahead-behind", &s.ahead_behind_flags,
N_("compute full ahead/behind values")),
OPT_SET_INT(0, "porcelain", &status_format,
N_("machine-readable output"), STATUS_FORMAT_PORCELAIN),
OPT_SET_INT(0, "long", &status_format,
......
......@@ -2058,6 +2058,8 @@ int stat_tracking_info(struct branch *branch, int *num_ours, int *num_theirs,
return 0;
if (abf == AHEAD_BEHIND_QUICK)
return 1;
if (abf != AHEAD_BEHIND_FULL)
BUG("stat_tracking_info: invalid abf '%d'", abf);
/* Run "rev-list --left-right ours...theirs" internally... */
argv_array_push(&argv, ""); /* ignored */
......
......@@ -259,8 +259,9 @@ enum match_refs_flags {
/* Flags for --ahead-behind option. */
enum ahead_behind_flags {
AHEAD_BEHIND_QUICK = 0, /* just eq/neq reporting */
AHEAD_BEHIND_FULL = 1, /* traditional a/b reporting */
AHEAD_BEHIND_UNSPECIFIED = -1,
AHEAD_BEHIND_QUICK = 0, /* just eq/neq reporting */
AHEAD_BEHIND_FULL = 1, /* traditional a/b reporting */
};
/* Reporting of tracking info */
......
......@@ -390,6 +390,68 @@ test_expect_success 'verify upstream fields in branch header' '
)
'
test_expect_success 'verify --[no-]ahead-behind with V2 format' '
git checkout master &&
test_when_finished "rm -rf sub_repo" &&
git clone . sub_repo &&
(
## Confirm local master tracks remote master.
cd sub_repo &&
HUF=$(git rev-parse HEAD) &&
# Confirm --no-ahead-behind reports traditional branch.ab with 0/0 for equal branches.
cat >expect <<-EOF &&
# branch.oid $HUF
# branch.head master
# branch.upstream origin/master
# branch.ab +0 -0
EOF
git status --no-ahead-behind --porcelain=v2 --branch --untracked-files=all >actual &&
test_cmp expect actual &&
# Confirm --ahead-behind reports traditional branch.ab with 0/0.
cat >expect <<-EOF &&
# branch.oid $HUF
# branch.head master
# branch.upstream origin/master
# branch.ab +0 -0
EOF
git status --ahead-behind --porcelain=v2 --branch --untracked-files=all >actual &&
test_cmp expect actual &&
## Test non-equal ahead/behind.
echo xyz >file_xyz &&
git add file_xyz &&
git commit -m xyz &&
HUF=$(git rev-parse HEAD) &&
# Confirm --no-ahead-behind reports branch.ab with ?/? for non-equal branches.
cat >expect <<-EOF &&
# branch.oid $HUF
# branch.head master
# branch.upstream origin/master
# branch.ab +? -?
EOF
git status --no-ahead-behind --porcelain=v2 --branch --untracked-files=all >actual &&
test_cmp expect actual &&
# Confirm --ahead-behind reports traditional branch.ab with 1/0.
cat >expect <<-EOF &&
# branch.oid $HUF
# branch.head master
# branch.upstream origin/master
# branch.ab +1 -0
EOF
git status --ahead-behind --porcelain=v2 --branch --untracked-files=all >actual &&
test_cmp expect actual
)
'
test_expect_success 'create and add submodule, submodule appears clean (A. S...)' '
git checkout master &&
git clone . sub_repo &&
......
......@@ -136,6 +136,7 @@ void wt_status_prepare(struct wt_status *s)
s->ignored.strdup_strings = 1;
s->show_branch = -1; /* unspecified */
s->show_stash = 0;
s->ahead_behind_flags = AHEAD_BEHIND_UNSPECIFIED;
s->display_comment_prefix = 0;
}
......@@ -1883,18 +1884,19 @@ static void wt_porcelain_print(struct wt_status *s)
*
* <upstream> ::= the upstream branch name, when set.
*
* <ahead> ::= integer ahead value, when upstream set
* and the commit is present (not gone).
*
* <behind> ::= integer behind value, when upstream set
* and commit is present.
* <ahead> ::= integer ahead value or '?'.
*
* <behind> ::= integer behind value or '?'.
*
* The end-of-line is defined by the -z flag.
*
* <eol> ::= NUL when -z,
* LF when NOT -z.
*
* When an upstream is set and present, the 'branch.ab' line will
* be printed with the ahead/behind counts for the branch and the
* upstream. When AHEAD_BEHIND_QUICK is requested and the branches
* are different, '?' will be substituted for the actual count.
*/
static void wt_porcelain_v2_print_tracking(struct wt_status *s)
{
......@@ -1934,15 +1936,25 @@ static void wt_porcelain_v2_print_tracking(struct wt_status *s)
/* Lookup stats on the upstream tracking branch, if set. */
branch = branch_get(branch_name);
base = NULL;
ab_info = (stat_tracking_info(branch, &nr_ahead, &nr_behind,
&base, AHEAD_BEHIND_FULL) >= 0);
ab_info = stat_tracking_info(branch, &nr_ahead, &nr_behind,
&base, s->ahead_behind_flags);
if (base) {
base = shorten_unambiguous_ref(base, 0);
fprintf(s->fp, "# branch.upstream %s%c", base, eol);
free((char *)base);
if (ab_info)
fprintf(s->fp, "# branch.ab +%d -%d%c", nr_ahead, nr_behind, eol);
if (ab_info > 0) {
/* different */
if (nr_ahead || nr_behind)
fprintf(s->fp, "# branch.ab +%d -%d%c",
nr_ahead, nr_behind, eol);
else
fprintf(s->fp, "# branch.ab +? -?%c",
eol);
} else if (!ab_info) {
/* same */
fprintf(s->fp, "# branch.ab +0 -0%c", eol);
}
}
}
......
......@@ -5,6 +5,7 @@
#include "string-list.h"
#include "color.h"
#include "pathspec.h"
#include "remote.h"
struct worktree;
......@@ -86,6 +87,7 @@ struct wt_status {
int show_branch;
int show_stash;
int hints;
enum ahead_behind_flags ahead_behind_flags;
enum wt_status_format status_format;
unsigned char sha1_commit[GIT_MAX_RAWSZ]; /* when not Initial */
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment