Skip to content

Commit 0658622

Browse files
committed
Filter out unwanted stderr output during git push commands
1 parent 0d593e7 commit 0658622

File tree

3 files changed

+193
-1
lines changed

3 files changed

+193
-1
lines changed

git/git.go

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import (
1212
"strings"
1313

1414
"github.com/cli/cli/internal/run"
15+
"github.com/cli/cli/pkg/iostreams"
1516
)
1617

1718
// ErrNotOnAnyBranch indicates that the user is in detached HEAD state
@@ -164,8 +165,10 @@ func CommitBody(sha string) (string, error) {
164165
// Push publishes a git ref to a remote and sets up upstream configuration
165166
func Push(remote string, ref string) error {
166167
pushCmd := GitCommand("push", "--set-upstream", remote, ref)
168+
regexp := regexp.MustCompile("^remote:.*$")
169+
filterErr := iostreams.NewRegexFilterWriter(os.Stderr, regexp, "")
167170
pushCmd.Stdout = os.Stdout
168-
pushCmd.Stderr = os.Stderr
171+
pushCmd.Stderr = filterErr
169172
return run.PrepareCmd(pushCmd).Run()
170173
}
171174

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
package iostreams
2+
3+
import (
4+
"bufio"
5+
"bytes"
6+
"io"
7+
"regexp"
8+
)
9+
10+
func NewRegexFilterWriter(out io.Writer, regexp *regexp.Regexp, repl string) io.Writer {
11+
return &RegexFilterWriter{out: out, regexp: *regexp, repl: repl}
12+
}
13+
14+
type RegexFilterWriter struct {
15+
out io.Writer
16+
regexp regexp.Regexp
17+
repl string
18+
}
19+
20+
func (s RegexFilterWriter) Write(data []byte) (int, error) {
21+
filtered := []byte{}
22+
repl := []byte(s.repl)
23+
scanner := bufio.NewScanner(bytes.NewReader(data))
24+
25+
for scanner.Scan() {
26+
b := scanner.Bytes()
27+
f := s.regexp.ReplaceAll(b, repl)
28+
if len(f) > 0 {
29+
filtered = append(filtered, f...)
30+
filtered = append(filtered, []byte("\n")...)
31+
}
32+
}
33+
34+
if err := scanner.Err(); err != nil {
35+
return 0, err
36+
}
37+
38+
if len(filtered) != 0 {
39+
_, err := s.out.Write(filtered)
40+
if err != nil {
41+
return 0, err
42+
}
43+
}
44+
45+
return len(data), nil
46+
}
Lines changed: 143 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,143 @@
1+
package iostreams
2+
3+
import (
4+
"bytes"
5+
"regexp"
6+
"testing"
7+
8+
"github.com/MakeNowJust/heredoc"
9+
"github.com/stretchr/testify/assert"
10+
)
11+
12+
func Test_Write(t *testing.T) {
13+
type input struct {
14+
in string
15+
regexp *regexp.Regexp
16+
repl string
17+
}
18+
type output struct {
19+
wantsErr bool
20+
out string
21+
length int
22+
}
23+
tests := []struct {
24+
name string
25+
input input
26+
output output
27+
}{
28+
{
29+
name: "single line input",
30+
input: input{
31+
in: "some input line that has wrong information",
32+
regexp: regexp.MustCompile("wrong"),
33+
repl: "right",
34+
},
35+
output: output{
36+
wantsErr: false,
37+
out: "some input line that has right information\n",
38+
length: 42,
39+
},
40+
},
41+
{
42+
name: "multiple line input",
43+
input: input{
44+
in: "multiple lines\nin this\ninput lines",
45+
regexp: regexp.MustCompile("lines"),
46+
repl: "tests",
47+
},
48+
output: output{
49+
wantsErr: false,
50+
out: "multiple tests\nin this\ninput tests\n",
51+
length: 34,
52+
},
53+
},
54+
{
55+
name: "no matches",
56+
input: input{
57+
in: "this line has no matches",
58+
regexp: regexp.MustCompile("wrong"),
59+
repl: "right",
60+
},
61+
output: output{
62+
wantsErr: false,
63+
out: "this line has no matches\n",
64+
length: 24,
65+
},
66+
},
67+
{
68+
name: "no output",
69+
input: input{
70+
in: "remove this whole line",
71+
regexp: regexp.MustCompile("^remove.*$"),
72+
repl: "",
73+
},
74+
output: output{
75+
wantsErr: false,
76+
out: "",
77+
length: 22,
78+
},
79+
},
80+
{
81+
name: "no input",
82+
input: input{
83+
in: "",
84+
regexp: regexp.MustCompile("remove"),
85+
repl: "",
86+
},
87+
output: output{
88+
wantsErr: false,
89+
out: "",
90+
length: 0,
91+
},
92+
},
93+
{
94+
name: "multiple lines removed",
95+
input: input{
96+
in: "begining line\nremove this whole line\nremove this one also\nnot this one",
97+
regexp: regexp.MustCompile("^remove.*$"),
98+
repl: "",
99+
},
100+
output: output{
101+
wantsErr: false,
102+
out: "begining line\nnot this one\n",
103+
length: 70,
104+
},
105+
},
106+
{
107+
name: "removes remote from git push output",
108+
input: input{
109+
in: heredoc.Doc(`
110+
output: some information
111+
remote:
112+
remote: Create a pull request for 'regex' on GitHub by visiting:
113+
remote: https://github.com/owner/repo/pull/new/regex
114+
remote:
115+
output: more information
116+
`),
117+
regexp: regexp.MustCompile("^remote.*$"),
118+
repl: "",
119+
},
120+
output: output{
121+
wantsErr: false,
122+
out: "output: some information\noutput: more information\n",
123+
length: 189,
124+
},
125+
},
126+
}
127+
128+
for _, tt := range tests {
129+
out := &bytes.Buffer{}
130+
writer := NewRegexFilterWriter(out, tt.input.regexp, tt.input.repl)
131+
t.Run(tt.name, func(t *testing.T) {
132+
length, err := writer.Write([]byte(tt.input.in))
133+
134+
if tt.output.wantsErr {
135+
assert.Error(t, err)
136+
return
137+
}
138+
assert.NoError(t, err)
139+
assert.Equal(t, tt.output.out, out.String())
140+
assert.Equal(t, tt.output.length, length)
141+
})
142+
}
143+
}

0 commit comments

Comments
 (0)