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
This commit is contained in:
Mithun Ayachit
2020-02-12 06:05:24 -06:00
parent 9fa18aaf59
commit c46413539e
5 changed files with 74 additions and 11 deletions

View File

@@ -1,13 +1,13 @@
dist: xenial
dist: bionic
git:
depth: 3
language: go
go:
- "1.x"
- "1.10.x"
- 1.13.x
before_script:
- go get golang.org/x/lint/golint
script:
- go mod tidy
- gofmt -d -e -l -s .
- golint -set_exit_status ./...
- go test -v ./...

5
go.mod Normal file
View File

@@ -0,0 +1,5 @@
module github.com/google/addlicense
go 1.13
require golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e

2
go.sum Normal file
View File

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

20
main.go
View File

@@ -26,8 +26,9 @@ import (
"os"
"path/filepath"
"strings"
"sync"
"time"
"golang.org/x/sync/errgroup"
)
const helpText = `Usage: addlicense [flags] pattern [pattern ...]
@@ -92,23 +93,26 @@ func main() {
ch := make(chan *file, 1000)
done := make(chan struct{})
go func() {
var wg sync.WaitGroup
var wg errgroup.Group
for f := range ch {
wg.Add(1)
go func(f *file) {
defer wg.Done()
f := f // https://golang.org/doc/faq#closures_and_goroutines
wg.Go(func() error {
modified, err := addLicense(f.path, f.mode, t, data)
if err != nil {
log.Printf("%s: %v", f.path, err)
return
return err
}
if *verbose && modified {
log.Printf("%s modified", f.path)
}
}(f)
return nil
})
}
wg.Wait()
err := wg.Wait()
close(done)
if err != nil {
os.Exit(1)
}
}()
for _, d := range flag.Args() {

View File

@@ -87,3 +87,55 @@ func TestMultiyear(t *testing.T) {
}
run(t, "diff", samplefile, sampleLicensed)
}
func TestWriteErrors(t *testing.T) {
if os.Getenv("RUNME") != "" {
main()
return
}
tmp := tempDir(t)
t.Logf("tmp dir: %s", tmp)
samplefile := filepath.Join(tmp, "file.c")
run(t, "cp", "testdata/initial/file.c", samplefile)
run(t, "chmod", "0444", samplefile)
cmd := exec.Command(os.Args[0],
"-test.run=TestWriteErrors",
"-l", "apache", "-c", "Google LLC", "-y", "2018",
samplefile,
)
cmd.Env = []string{"RUNME=1"}
out, err := cmd.CombinedOutput()
if err == nil {
run(t, "chmod", "0644", samplefile)
t.Fatalf("TestWriteErrors exited with a zero exit code.\n%s", out)
}
run(t, "chmod", "0644", samplefile)
}
func TestReadErrors(t *testing.T) {
if os.Getenv("RUNME") != "" {
main()
return
}
tmp := tempDir(t)
t.Logf("tmp dir: %s", tmp)
samplefile := filepath.Join(tmp, "file.c")
run(t, "cp", "testdata/initial/file.c", samplefile)
run(t, "chmod", "a-r", samplefile)
cmd := exec.Command(os.Args[0],
"-test.run=TestReadErrors",
"-l", "apache", "-c", "Google LLC", "-y", "2018",
samplefile,
)
cmd.Env = []string{"RUNME=1"}
out, err := cmd.CombinedOutput()
if err == nil {
run(t, "chmod", "0644", samplefile)
t.Fatalf("TestWriteErrors exited with a zero exit code.\n%s", out)
}
run(t, "chmod", "0644", samplefile)
}