Skip to content

Commit c464135

Browse files
committed
replace WaitGroup with errgroup to allow error handling and propagation
The program now exits with a non-zero code when errors are encountered while reading and/or writing files. This now also introduces Go Modules for dependency management
1 parent 9fa18aa commit c464135

File tree

5 files changed

+74
-11
lines changed

5 files changed

+74
-11
lines changed

.travis.yml

+3-3
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
1-
dist: xenial
1+
dist: bionic
22
git:
33
depth: 3
44
language: go
55
go:
6-
- "1.x"
7-
- "1.10.x"
6+
- 1.13.x
87
before_script:
98
- go get golang.org/x/lint/golint
109
script:
10+
- go mod tidy
1111
- gofmt -d -e -l -s .
1212
- golint -set_exit_status ./...
1313
- go test -v ./...

go.mod

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
module github.com/google/addlicense
2+
3+
go 1.13
4+
5+
require golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e

go.sum

+2
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e h1:vcxGaoTs7kV8m5Np9uUNQin4BrLOthgV7252N8V+FwY=
2+
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=

main.go

+12-8
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,9 @@ import (
2626
"os"
2727
"path/filepath"
2828
"strings"
29-
"sync"
3029
"time"
30+
31+
"golang.org/x/sync/errgroup"
3132
)
3233

3334
const helpText = `Usage: addlicense [flags] pattern [pattern ...]
@@ -92,23 +93,26 @@ func main() {
9293
ch := make(chan *file, 1000)
9394
done := make(chan struct{})
9495
go func() {
95-
var wg sync.WaitGroup
96+
var wg errgroup.Group
9697
for f := range ch {
97-
wg.Add(1)
98-
go func(f *file) {
99-
defer wg.Done()
98+
f := f // https://golang.org/doc/faq#closures_and_goroutines
99+
wg.Go(func() error {
100100
modified, err := addLicense(f.path, f.mode, t, data)
101101
if err != nil {
102102
log.Printf("%s: %v", f.path, err)
103-
return
103+
return err
104104
}
105105
if *verbose && modified {
106106
log.Printf("%s modified", f.path)
107107
}
108-
}(f)
108+
return nil
109+
})
109110
}
110-
wg.Wait()
111+
err := wg.Wait()
111112
close(done)
113+
if err != nil {
114+
os.Exit(1)
115+
}
112116
}()
113117

114118
for _, d := range flag.Args() {

main_test.go

+52
Original file line numberDiff line numberDiff line change
@@ -87,3 +87,55 @@ func TestMultiyear(t *testing.T) {
8787
}
8888
run(t, "diff", samplefile, sampleLicensed)
8989
}
90+
91+
func TestWriteErrors(t *testing.T) {
92+
if os.Getenv("RUNME") != "" {
93+
main()
94+
return
95+
}
96+
97+
tmp := tempDir(t)
98+
t.Logf("tmp dir: %s", tmp)
99+
samplefile := filepath.Join(tmp, "file.c")
100+
101+
run(t, "cp", "testdata/initial/file.c", samplefile)
102+
run(t, "chmod", "0444", samplefile)
103+
cmd := exec.Command(os.Args[0],
104+
"-test.run=TestWriteErrors",
105+
"-l", "apache", "-c", "Google LLC", "-y", "2018",
106+
samplefile,
107+
)
108+
cmd.Env = []string{"RUNME=1"}
109+
out, err := cmd.CombinedOutput()
110+
if err == nil {
111+
run(t, "chmod", "0644", samplefile)
112+
t.Fatalf("TestWriteErrors exited with a zero exit code.\n%s", out)
113+
}
114+
run(t, "chmod", "0644", samplefile)
115+
}
116+
117+
func TestReadErrors(t *testing.T) {
118+
if os.Getenv("RUNME") != "" {
119+
main()
120+
return
121+
}
122+
123+
tmp := tempDir(t)
124+
t.Logf("tmp dir: %s", tmp)
125+
samplefile := filepath.Join(tmp, "file.c")
126+
127+
run(t, "cp", "testdata/initial/file.c", samplefile)
128+
run(t, "chmod", "a-r", samplefile)
129+
cmd := exec.Command(os.Args[0],
130+
"-test.run=TestReadErrors",
131+
"-l", "apache", "-c", "Google LLC", "-y", "2018",
132+
samplefile,
133+
)
134+
cmd.Env = []string{"RUNME=1"}
135+
out, err := cmd.CombinedOutput()
136+
if err == nil {
137+
run(t, "chmod", "0644", samplefile)
138+
t.Fatalf("TestWriteErrors exited with a zero exit code.\n%s", out)
139+
}
140+
run(t, "chmod", "0644", samplefile)
141+
}

0 commit comments

Comments
 (0)