From: Jeff Hostetler <git@jeffhostetler.com>
To: git@vger.kernel.org
Cc: gitster@pobox.com, peff@peff.net,
Jeff Hostetler <jeffhost@microsoft.com>
Subject: [PATCH v3 2/5] status: add --[no-]ahead-behind to status and commit for V2 format.
Date: Wed, 3 Jan 2018 21:47:30 +0000 [thread overview]
Message-ID: <20180103214733.797-3-git@jeffhostetler.com> (raw)
In-Reply-To: <20180103214733.797-1-git@jeffhostetler.com>
From: Jeff Hostetler <jeffhost@microsoft.com>
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 equal eq|neq" line.
This indicates that the branch and its upstream are or are not equal
without the expense of computing the full ahead/behind values.
Added "status.aheadBehind" config setting. This is only used by
non-porcelain format for backward-compatibility.
Signed-off-by: Jeff Hostetler <jeffhost@microsoft.com>
---
Documentation/config.txt | 6 ++++
Documentation/git-status.txt | 5 ++++
builtin/commit.c | 18 +++++++++++-
remote.c | 2 ++
remote.h | 5 ++--
t/t7064-wtstatus-pv2.sh | 69 ++++++++++++++++++++++++++++++++++++++++++++
wt-status.c | 27 +++++++++++++----
wt-status.h | 2 ++
8 files changed, 125 insertions(+), 9 deletions(-)
diff --git a/Documentation/config.txt b/Documentation/config.txt
index 9593bfa..affb0d6 100644
--- a/Documentation/config.txt
+++ b/Documentation/config.txt
@@ -3035,6 +3035,12 @@ status.branch::
Set to true to enable --branch by default in linkgit:git-status[1].
The option --no-branch takes precedence over this variable.
+status.aheadBehind::
+ Set to true to enable --ahead-behind and to false to enable
+ --no-ahead-behind by default in linkgit:git-status[1] for
+ non-porcelain formats. This setting is ignored by porcelain
+ formats for backwards compatibility.
+
status.displayCommentPrefix::
If set to true, linkgit:git-status[1] will insert a comment
prefix before each output line (starting with
diff --git a/Documentation/git-status.txt b/Documentation/git-status.txt
index 9f3a78a..603bf40 100644
--- a/Documentation/git-status.txt
+++ b/Documentation/git-status.txt
@@ -111,6 +111,11 @@ configuration variable documented in linkgit:git-config[1].
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].
diff --git a/builtin/commit.c b/builtin/commit.c
index be370f6..416fe2c 100644
--- a/builtin/commit.c
+++ b/builtin/commit.c
@@ -1109,9 +1109,11 @@ static const char *read_commit_message(const char *name)
static struct status_deferred_config {
enum wt_status_format status_format;
int show_branch;
+ enum ahead_behind_flags ahead_behind;
} status_deferred_config = {
STATUS_FORMAT_UNSPECIFIED,
- -1 /* unspecified */
+ -1, /* unspecified */
+ AHEAD_BEHIND_UNSPECIFIED,
};
static void finalize_deferred_config(struct wt_status *s)
@@ -1137,6 +1139,12 @@ 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 (use_deferred_config &&
+ s->ahead_behind_flags == AHEAD_BEHIND_UNSPECIFIED)
+ s->ahead_behind_flags = status_deferred_config.ahead_behind;
+ 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[],
@@ -1297,6 +1305,10 @@ static int git_status_config(const char *k, const char *v, void *cb)
status_deferred_config.show_branch = git_config_bool(k, v);
return 0;
}
+ if (!strcmp(k, "status.aheadbehind")) {
+ status_deferred_config.ahead_behind = git_config_bool(k, v);
+ return 0;
+ }
if (!strcmp(k, "status.showstash")) {
s->show_stash = git_config_bool(k, v);
return 0;
@@ -1351,6 +1363,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 },
@@ -1628,6 +1642,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,
diff --git a/remote.c b/remote.c
index ca5a416..32706bc 100644
--- a/remote.c
+++ b/remote.c
@@ -2028,6 +2028,8 @@ int stat_tracking_info(struct branch *branch, int *num_ours, int *num_theirs,
}
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 */
diff --git a/remote.h b/remote.h
index 00932f5..27feb63 100644
--- a/remote.h
+++ b/remote.h
@@ -257,8 +257,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 */
diff --git a/t/t7064-wtstatus-pv2.sh b/t/t7064-wtstatus-pv2.sh
index e319fa2..67b90cd 100755
--- a/t/t7064-wtstatus-pv2.sh
+++ b/t/t7064-wtstatus-pv2.sh
@@ -390,6 +390,75 @@ 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 branch.equal with "eq".
+ cat >expect <<-EOF &&
+ # branch.oid $HUF
+ # branch.head master
+ # branch.upstream origin/master
+ # branch.equal eq
+ 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 &&
+
+ # Confirm that porcelain=v2 format does not inherit status.aheadBehind value.
+ git -c status.aheadbehind=false status --porcelain=v2 --branch --untracked-files=all >actual &&
+ test_cmp expect actual &&
+
+ git -c status.aheadbehind=true status --porcelain=v2 --branch --untracked-files=all >actual &&
+ test_cmp expect actual &&
+
+ ## Test 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.equal with "neq".
+ cat >expect <<-EOF &&
+ # branch.oid $HUF
+ # branch.head master
+ # branch.upstream origin/master
+ # branch.equal neq
+ 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 &&
diff --git a/wt-status.c b/wt-status.c
index 8f7fdc6..3959d31 100644
--- a/wt-status.c
+++ b/wt-status.c
@@ -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;
}
@@ -1866,7 +1867,8 @@ static void wt_porcelain_print(struct wt_status *s)
* # branch.oid <commit><eol>
* # branch.head <head><eol>
* [# branch.upstream <upstream><eol>
- * [# branch.ab +<ahead> -<behind><eol>]]
+ * [# branch.ab +<ahead> -<behind><eol>]
+ * [# branch.equal <equal><eol>]]
*
* <commit> ::= the current commit hash or the the literal
* "(initial)" to indicate an initialized repo
@@ -1884,12 +1886,16 @@ static void wt_porcelain_print(struct wt_status *s)
* <behind> ::= integer behind value, when upstream set
* and commit is present.
*
+ * <equal> ::= literal string "eq" or "neq".
*
* 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 when the ahead_behind_flags are set to _FULL and
+ * the 'branch.equal' line will be printed when set to _QUICK.
*/
static void wt_porcelain_v2_print_tracking(struct wt_status *s)
{
@@ -1897,7 +1903,7 @@ static void wt_porcelain_v2_print_tracking(struct wt_status *s)
const char *base;
const char *branch_name;
struct wt_status_state state;
- int ab_info, nr_ahead, nr_behind;
+ int sti, nr_ahead, nr_behind;
char eol = s->null_termination ? '\0' : '\n';
memset(&state, 0, sizeof(state));
@@ -1929,15 +1935,24 @@ 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);
+ sti = 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 (sti >= 0) {
+ if (s->ahead_behind_flags == AHEAD_BEHIND_FULL)
+ fprintf(s->fp, "# branch.ab +%d -%d%c",
+ nr_ahead, nr_behind, eol);
+ else if (s->ahead_behind_flags == AHEAD_BEHIND_QUICK)
+ fprintf(s->fp, "# branch.equal %s%c",
+ sti ? "neq" : "eq", eol);
+ else
+ BUG("invalid ahead_behind_flag '%d'",
+ s->ahead_behind_flags);
+ }
}
}
diff --git a/wt-status.h b/wt-status.h
index 64f4d33..b450b53 100644
--- a/wt-status.h
+++ b/wt-status.h
@@ -5,6 +5,7 @@
#include "string-list.h"
#include "color.h"
#include "pathspec.h"
+#include "remote.h"
struct worktree;
@@ -80,6 +81,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 */
--
2.9.3
next prev parent reply other threads:[~2018-01-03 21:47 UTC|newest]
Thread overview: 14+ messages / expand[flat|nested] mbox.gz Atom feed top
2018-01-03 21:47 [PATCH v3 0/5] Add --no-ahead-behind to status Jeff Hostetler
2018-01-03 21:47 ` [PATCH v3 1/5] stat_tracking_info: return +1 when branches not equal Jeff Hostetler
2018-01-04 21:41 ` Junio C Hamano
2018-01-03 21:47 ` Jeff Hostetler [this message]
2018-01-04 22:05 ` [PATCH v3 2/5] status: add --[no-]ahead-behind to status and commit for V2 format Junio C Hamano
2018-01-05 16:31 ` Jeff Hostetler
2018-01-03 21:47 ` [PATCH v3 3/5] status: update short status to respect --no-ahead-behind Jeff Hostetler
2018-01-03 21:47 ` [PATCH v3 4/5] status: support --no-ahead-behind in long format Jeff Hostetler
2018-01-03 21:47 ` [PATCH v3 5/5] status: add status.aheadBehind value for porcelain output Jeff Hostetler
2018-01-04 23:06 ` [PATCH v3 0/5] Add --no-ahead-behind to status Jeff King
2018-01-05 16:46 ` Jeff Hostetler
2018-01-05 19:56 ` Junio C Hamano
2018-01-08 6:37 ` Jeff King
2018-01-08 14:22 ` Jeff Hostetler
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20180103214733.797-3-git@jeffhostetler.com \
--to=git@jeffhostetler.com \
--cc=git@vger.kernel.org \
--cc=gitster@pobox.com \
--cc=jeffhost@microsoft.com \
--cc=peff@peff.net \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.