@@ -24,12 +24,12 @@ type BlamePart struct {
24
24
25
25
// BlameReader returns part of file blame one by one
26
26
type BlameReader struct {
27
- cmd * exec.Cmd
28
- output io.ReadCloser
29
- reader * bufio. Reader
30
- lastSha * string
31
- cancel context. CancelFunc // Cancels the context that this reader runs in
32
- finished process. FinishedFunc // Tells the process manager we're finished and it can remove the associated process from the process table
27
+ cmd * exec.Cmd
28
+ reader io.ReadCloser
29
+ lastSha * string
30
+ cancel context. CancelFunc // Cancels the context that this reader runs in
31
+ finished process. FinishedFunc // Tells the process manager we're finished and it can remove the associated process from the process table
32
+ bufferedReader * bufio. Reader
33
33
}
34
34
35
35
var shaLineRegex = regexp .MustCompile ("^([a-z0-9]{40})" )
@@ -38,8 +38,6 @@ var shaLineRegex = regexp.MustCompile("^([a-z0-9]{40})")
38
38
func (r * BlameReader ) NextPart () (* BlamePart , error ) {
39
39
var blamePart * BlamePart
40
40
41
- reader := r .reader
42
-
43
41
if r .lastSha != nil {
44
42
blamePart = & BlamePart {* r .lastSha , make ([]string , 0 )}
45
43
}
@@ -49,7 +47,7 @@ func (r *BlameReader) NextPart() (*BlamePart, error) {
49
47
var err error
50
48
51
49
for err != io .EOF {
52
- line , isPrefix , err = reader .ReadLine ()
50
+ line , isPrefix , err = r . bufferedReader .ReadLine ()
53
51
if err != nil && err != io .EOF {
54
52
return blamePart , err
55
53
}
@@ -71,7 +69,7 @@ func (r *BlameReader) NextPart() (*BlamePart, error) {
71
69
r .lastSha = & sha1
72
70
// need to munch to end of line...
73
71
for isPrefix {
74
- _ , isPrefix , err = reader .ReadLine ()
72
+ _ , isPrefix , err = r . bufferedReader .ReadLine ()
75
73
if err != nil && err != io .EOF {
76
74
return blamePart , err
77
75
}
@@ -86,7 +84,7 @@ func (r *BlameReader) NextPart() (*BlamePart, error) {
86
84
87
85
// need to munch to end of line...
88
86
for isPrefix {
89
- _ , isPrefix , err = reader .ReadLine ()
87
+ _ , isPrefix , err = r . bufferedReader .ReadLine ()
90
88
if err != nil && err != io .EOF {
91
89
return blamePart , err
92
90
}
@@ -102,9 +100,9 @@ func (r *BlameReader) NextPart() (*BlamePart, error) {
102
100
func (r * BlameReader ) Close () error {
103
101
defer r .finished () // Only remove the process from the process table when the underlying command is closed
104
102
r .cancel () // However, first cancel our own context early
103
+ r .bufferedReader = nil
105
104
106
- _ = r .output .Close ()
107
-
105
+ _ = r .reader .Close ()
108
106
if err := r .cmd .Wait (); err != nil {
109
107
return fmt .Errorf ("Wait: %w" , err )
110
108
}
@@ -126,25 +124,27 @@ func createBlameReader(ctx context.Context, dir string, command ...string) (*Bla
126
124
cmd .Stderr = os .Stderr
127
125
process .SetSysProcAttribute (cmd )
128
126
129
- stdout , err := cmd . StdoutPipe ()
127
+ reader , stdout , err := os . Pipe ()
130
128
if err != nil {
131
129
defer finished ()
132
130
return nil , fmt .Errorf ("StdoutPipe: %w" , err )
133
131
}
132
+ cmd .Stdout = stdout
134
133
135
134
if err = cmd .Start (); err != nil {
136
135
defer finished ()
137
136
_ = stdout .Close ()
138
137
return nil , fmt .Errorf ("Start: %w" , err )
139
138
}
139
+ _ = stdout .Close ()
140
140
141
- reader := bufio .NewReader (stdout )
141
+ bufferedReader := bufio .NewReader (reader )
142
142
143
143
return & BlameReader {
144
- cmd : cmd ,
145
- output : stdout ,
146
- reader : reader ,
147
- cancel : cancel ,
148
- finished : finished ,
144
+ cmd : cmd ,
145
+ reader : reader ,
146
+ cancel : cancel ,
147
+ finished : finished ,
148
+ bufferedReader : bufferedReader ,
149
149
}, nil
150
150
}
0 commit comments