Skip to content

Commit 7ab11fd

Browse files
jeffhostetlerdscho
authored andcommitted
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: Jeff Hostetler <[email protected]> Signed-off-by: Johannes Schindelin <[email protected]>
1 parent c2efcf5 commit 7ab11fd

File tree

7 files changed

+103
-11
lines changed

7 files changed

+103
-11
lines changed

Documentation/git-status.txt

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,12 @@ configuration variable documented in linkgit:git-config[1].
118118
update it afterwards if any changes were detected. Defaults to
119119
`--lock-index`.
120120

121+
--ahead-behind::
122+
--no-ahead-behind::
123+
EXPERIMENTAL, Display or do not display detailed ahead/behind
124+
counts for the branch relative to its upstream branch. Defaults
125+
to true.
126+
121127
<pathspec>...::
122128
See the 'pathspec' entry in linkgit:gitglossary[7].
123129

builtin/commit.c

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1137,6 +1137,9 @@ static void finalize_deferred_config(struct wt_status *s)
11371137
s->show_branch = status_deferred_config.show_branch;
11381138
if (s->show_branch < 0)
11391139
s->show_branch = 0;
1140+
1141+
if (s->ahead_behind_flags == AHEAD_BEHIND_UNSPECIFIED)
1142+
s->ahead_behind_flags = AHEAD_BEHIND_FULL;
11401143
}
11411144

11421145
static int parse_and_validate_options(int argc, const char *argv[],
@@ -1352,6 +1355,8 @@ int cmd_status(int argc, const char **argv, const char *prefix)
13521355
N_("show branch information")),
13531356
OPT_BOOL(0, "show-stash", &s.show_stash,
13541357
N_("show stash information")),
1358+
OPT_BOOL(0, "ahead-behind", &s.ahead_behind_flags,
1359+
N_("compute full ahead/behind values (EXPERIMENTAL)")),
13551360
{ OPTION_CALLBACK, 0, "porcelain", &status_format,
13561361
N_("version"), N_("machine-readable output"),
13571362
PARSE_OPT_OPTARG, opt_parse_porcelain },
@@ -1638,6 +1643,8 @@ int cmd_commit(int argc, const char **argv, const char *prefix)
16381643
OPT_SET_INT(0, "short", &status_format, N_("show status concisely"),
16391644
STATUS_FORMAT_SHORT),
16401645
OPT_BOOL(0, "branch", &s.show_branch, N_("show branch information")),
1646+
OPT_BOOL(0, "ahead-behind", &s.ahead_behind_flags,
1647+
N_("compute full ahead/behind values (EXPERIMENTAL)")),
16411648
OPT_SET_INT(0, "porcelain", &status_format,
16421649
N_("machine-readable output"), STATUS_FORMAT_PORCELAIN),
16431650
OPT_SET_INT(0, "long", &status_format,

remote.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2028,6 +2028,8 @@ int stat_tracking_info(struct branch *branch, int *num_ours, int *num_theirs,
20282028
return 0;
20292029
if (abf == AHEAD_BEHIND_QUICK)
20302030
return 1;
2031+
if (abf != AHEAD_BEHIND_FULL)
2032+
BUG("stat_tracking_info: invalid abf '%d'", abf);
20312033

20322034
/* Run "rev-list --left-right ours...theirs" internally... */
20332035
argv_array_push(&argv, ""); /* ignored */

remote.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -257,8 +257,9 @@ enum match_refs_flags {
257257

258258
/* Flags for --ahead-behind option. */
259259
enum ahead_behind_flags {
260-
AHEAD_BEHIND_QUICK = 0, /* just eq/neq reporting */
261-
AHEAD_BEHIND_FULL = 1, /* traditional a/b reporting */
260+
AHEAD_BEHIND_UNSPECIFIED = -1,
261+
AHEAD_BEHIND_QUICK = 0, /* just eq/neq reporting */
262+
AHEAD_BEHIND_FULL = 1, /* traditional a/b reporting */
262263
};
263264

264265
/* Reporting of tracking info */

t/t7064-wtstatus-pv2.sh

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -390,6 +390,68 @@ test_expect_success 'verify upstream fields in branch header' '
390390
)
391391
'
392392

393+
test_expect_success 'verify --[no-]ahead-behind with V2 format' '
394+
git checkout master &&
395+
test_when_finished "rm -rf sub_repo" &&
396+
git clone . sub_repo &&
397+
(
398+
## Confirm local master tracks remote master.
399+
cd sub_repo &&
400+
HUF=$(git rev-parse HEAD) &&
401+
402+
# Confirm --no-ahead-behind reports traditional branch.ab with 0/0 for equal branches.
403+
cat >expect <<-EOF &&
404+
# branch.oid $HUF
405+
# branch.head master
406+
# branch.upstream origin/master
407+
# branch.ab +0 -0
408+
EOF
409+
410+
git status --no-ahead-behind --porcelain=v2 --branch --untracked-files=all >actual &&
411+
test_cmp expect actual &&
412+
413+
# Confirm --ahead-behind reports traditional branch.ab with 0/0.
414+
cat >expect <<-EOF &&
415+
# branch.oid $HUF
416+
# branch.head master
417+
# branch.upstream origin/master
418+
# branch.ab +0 -0
419+
EOF
420+
421+
git status --ahead-behind --porcelain=v2 --branch --untracked-files=all >actual &&
422+
test_cmp expect actual &&
423+
424+
## Test non-equal ahead/behind.
425+
echo xyz >file_xyz &&
426+
git add file_xyz &&
427+
git commit -m xyz &&
428+
429+
HUF=$(git rev-parse HEAD) &&
430+
431+
# Confirm --no-ahead-behind reports branch.ab with ?/? for non-equal branches.
432+
cat >expect <<-EOF &&
433+
# branch.oid $HUF
434+
# branch.head master
435+
# branch.upstream origin/master
436+
# branch.ab +? -?
437+
EOF
438+
439+
git status --no-ahead-behind --porcelain=v2 --branch --untracked-files=all >actual &&
440+
test_cmp expect actual &&
441+
442+
# Confirm --ahead-behind reports traditional branch.ab with 1/0.
443+
cat >expect <<-EOF &&
444+
# branch.oid $HUF
445+
# branch.head master
446+
# branch.upstream origin/master
447+
# branch.ab +1 -0
448+
EOF
449+
450+
git status --ahead-behind --porcelain=v2 --branch --untracked-files=all >actual &&
451+
test_cmp expect actual
452+
)
453+
'
454+
393455
test_expect_success 'create and add submodule, submodule appears clean (A. S...)' '
394456
git checkout master &&
395457
git clone . sub_repo &&

wt-status.c

Lines changed: 21 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,7 @@ void wt_status_prepare(struct wt_status *s)
136136
s->ignored.strdup_strings = 1;
137137
s->show_branch = -1; /* unspecified */
138138
s->show_stash = 0;
139+
s->ahead_behind_flags = AHEAD_BEHIND_UNSPECIFIED;
139140
s->display_comment_prefix = 0;
140141
}
141142

@@ -1878,18 +1879,19 @@ static void wt_porcelain_print(struct wt_status *s)
18781879
*
18791880
* <upstream> ::= the upstream branch name, when set.
18801881
*
1881-
* <ahead> ::= integer ahead value, when upstream set
1882-
* and the commit is present (not gone).
1883-
*
1884-
* <behind> ::= integer behind value, when upstream set
1885-
* and commit is present.
1882+
* <ahead> ::= integer ahead value or '?'.
18861883
*
1884+
* <behind> ::= integer behind value or '?'.
18871885
*
18881886
* The end-of-line is defined by the -z flag.
18891887
*
18901888
* <eol> ::= NUL when -z,
18911889
* LF when NOT -z.
18921890
*
1891+
* When an upstream is set and present, the 'branch.ab' line will
1892+
* be printed with the ahead/behind counts for the branch and the
1893+
* upstream. When AHEAD_BEHIND_QUICK is requested and the branches
1894+
* are different, '?' will be substituted for the actual count.
18931895
*/
18941896
static void wt_porcelain_v2_print_tracking(struct wt_status *s)
18951897
{
@@ -1929,15 +1931,25 @@ static void wt_porcelain_v2_print_tracking(struct wt_status *s)
19291931
/* Lookup stats on the upstream tracking branch, if set. */
19301932
branch = branch_get(branch_name);
19311933
base = NULL;
1932-
ab_info = (stat_tracking_info(branch, &nr_ahead, &nr_behind,
1933-
&base, AHEAD_BEHIND_FULL) >= 0);
1934+
ab_info = stat_tracking_info(branch, &nr_ahead, &nr_behind,
1935+
&base, s->ahead_behind_flags);
19341936
if (base) {
19351937
base = shorten_unambiguous_ref(base, 0);
19361938
fprintf(s->fp, "# branch.upstream %s%c", base, eol);
19371939
free((char *)base);
19381940

1939-
if (ab_info)
1940-
fprintf(s->fp, "# branch.ab +%d -%d%c", nr_ahead, nr_behind, eol);
1941+
if (ab_info > 0) {
1942+
/* different */
1943+
if (nr_ahead || nr_behind)
1944+
fprintf(s->fp, "# branch.ab +%d -%d%c",
1945+
nr_ahead, nr_behind, eol);
1946+
else
1947+
fprintf(s->fp, "# branch.ab +? -?%c",
1948+
eol);
1949+
} else if (!ab_info) {
1950+
/* same */
1951+
fprintf(s->fp, "# branch.ab +0 -0%c", eol);
1952+
}
19411953
}
19421954
}
19431955

wt-status.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
#include "string-list.h"
66
#include "color.h"
77
#include "pathspec.h"
8+
#include "remote.h"
89

910
struct worktree;
1011

@@ -80,6 +81,7 @@ struct wt_status {
8081
int show_branch;
8182
int show_stash;
8283
int hints;
84+
enum ahead_behind_flags ahead_behind_flags;
8385

8486
enum wt_status_format status_format;
8587
unsigned char sha1_commit[GIT_MAX_RAWSZ]; /* when not Initial */

0 commit comments

Comments
 (0)