Skip to content

Commit 1546d1b

Browse files
committed
advice: refuse to output if stderr not TTY
The advice system is intended to help end users around corner cases or other difficult spots when using the Git tool. As such, they are added without considering the possibility that they could break scripts or external tools that execute Git processes and then parse the output. I will not debate the merit of tools parsing stderr, but instead attempt to be helpful to tool authors by avoiding these behavior changes across Git versions. In b79deeb (advice: add --no-advice global option, 2024-05-03), the --no-advice option was presented as a way to help tool authors specify that they do not want any advice messages. As part of this implementation, the GIT_ADVICE environment variable is given as a way to communicate the desire for advice (=1) or no advice (=0) and pass that along to all child processes. However, both the --no-advice option and the GIT_ADVICE environment variable require the tool author to change how they interact with Git to gain this protection. If Git instead disables the advice system when stderr is not a terminal, then tool authors benefit immediately. It is important, though, to let interested users force advice to be enabled, even when redirecting stderr to a non-terminal file. Be sure to test this by ensuring GIT_ADVICE=1 forces advice to be written to non-terminals. The changes leading up to this already set GIT_ADVICE=1 in all other test scripts that care about the advice being output (or not). Signed-off-by: Derrick Stolee <derrickstolee@github.com>
1 parent 5819a17 commit 1546d1b

File tree

3 files changed

+22
-9
lines changed

3 files changed

+22
-9
lines changed

Documentation/config/advice.txt

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,11 @@
11
advice.*::
22
These variables control various optional help messages designed to
3-
aid new users. When left unconfigured, Git will give the message
4-
alongside instructions on how to squelch it. You can tell Git
5-
that you do not need the help message by setting these to `false`:
3+
aid new users. These are only output to `stderr` when it is a
4+
terminal.
5+
+
6+
When left unconfigured, Git will give the message alongside instructions
7+
on how to squelch it. You can tell Git that you do not need the help
8+
message by setting these to `false`:
69
+
710
--
811
addEmbeddedRepo::

advice.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -133,7 +133,9 @@ int advice_enabled(enum advice_type type)
133133
static int globally_enabled = -1;
134134

135135
if (globally_enabled < 0)
136-
globally_enabled = git_env_bool(GIT_ADVICE_ENVIRONMENT, 1);
136+
globally_enabled = git_env_bool(GIT_ADVICE_ENVIRONMENT, -1);
137+
if (globally_enabled < 0)
138+
globally_enabled = isatty(2);
137139
if (!globally_enabled)
138140
return 0;
139141

t/t0018-advice.sh

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
88
TEST_PASSES_SANITIZE_LEAK=true
99
. ./test-lib.sh
1010

11-
test_expect_success 'advice should be printed when config variable is unset' '
11+
test_expect_success TTY 'advice should be printed when config variable is unset' '
1212
cat >expect <<-\EOF &&
1313
hint: This is a piece of advice
1414
hint: Disable this message with "git config advice.nestedTag false"
@@ -17,7 +17,7 @@ test_expect_success 'advice should be printed when config variable is unset' '
1717
test_cmp expect actual
1818
'
1919

20-
test_expect_success 'advice should be printed when config variable is set to true' '
20+
test_expect_success TTY 'advice should be printed when config variable is set to true' '
2121
cat >expect <<-\EOF &&
2222
hint: This is a piece of advice
2323
EOF
@@ -26,13 +26,13 @@ test_expect_success 'advice should be printed when config variable is set to tru
2626
test_cmp expect actual
2727
'
2828

29-
test_expect_success 'advice should not be printed when config variable is set to false' '
29+
test_expect_success TTY 'advice should not be printed when config variable is set to false' '
3030
test_config advice.nestedTag false &&
3131
test-tool advise "This is a piece of advice" 2>actual &&
3232
test_must_be_empty actual
3333
'
3434

35-
test_expect_success 'advice should not be printed when --no-advice is used' '
35+
test_expect_success TTY 'advice should not be printed when --no-advice is used' '
3636
q_to_tab >expect <<-\EOF &&
3737
On branch trunk
3838
@@ -54,7 +54,7 @@ test_expect_success 'advice should not be printed when --no-advice is used' '
5454
test_cmp expect actual
5555
'
5656

57-
test_expect_success 'advice should not be printed when GIT_ADVICE is set to false' '
57+
test_expect_success TTY 'advice should not be printed when GIT_ADVICE is set to false' '
5858
q_to_tab >expect <<-\EOF &&
5959
On branch trunk
6060
@@ -76,6 +76,8 @@ test_expect_success 'advice should not be printed when GIT_ADVICE is set to fals
7676
test_cmp expect actual
7777
'
7878

79+
# This test also verifies that GIT_ADVICE=1 ignores the requirement
80+
# that stderr is a terminal.
7981
test_expect_success 'advice should be printed when GIT_ADVICE is set to true' '
8082
q_to_tab >expect <<-\EOF &&
8183
On branch trunk
@@ -99,4 +101,10 @@ test_expect_success 'advice should be printed when GIT_ADVICE is set to true' '
99101
test_cmp expect actual
100102
'
101103

104+
test_expect_success 'advice should not be printed when stderr is not a terminal' '
105+
test_config advice.nestedTag true &&
106+
test-tool advise "This is a piece of advice" 2>actual &&
107+
test_must_be_empty actual
108+
'
109+
102110
test_done

0 commit comments

Comments
 (0)