mirror of
https://github.com/golang/go
synced 2024-11-18 14:14:46 -07:00
7d75e8b219
fiximports enumerates the set of packages identified by the command-line arguments, using "go list" notation. Within each package, it replaces all imports of non-canonical packages by their canonical name, introducing an import renaming if (heuristically) necessary. If a package comes from one of the -baddomains, and it has no import comment, fiximports reports an error. The error message includes the list of packages that import the errant package, directly or indirectly. This flag is used to indicate "sinking ship" package hosting domains like code.google.com. Caveat: this process is not trivially reversible. Consider a package A to which we add an import comment "B", and run the tool. Package C, which imported A, now imports B. ('go get -u' would fetch package B). But changing the import comment in directory A and re-running the tool will not cause C to be changed because it no longer imports A; it imports B. + Tests. Change-Id: I3d3d9663d3c084356fffc7e55407709ebc6d9a39 Reviewed-on: https://go-review.googlesource.com/8562 Reviewed-by: Andrew Gerrand <adg@golang.org>
158 lines
4.1 KiB
Go
158 lines
4.1 KiB
Go
// Copyright 2015 The Go Authors. All rights reserved.
|
|
// Use of this source code is governed by a BSD-style
|
|
// license that can be found in the LICENSE file.
|
|
|
|
package main
|
|
|
|
import (
|
|
"bytes"
|
|
"os"
|
|
"strings"
|
|
"testing"
|
|
)
|
|
|
|
// TODO(adonovan):
|
|
// - test introduction of renaming imports.
|
|
// - test induced failures of rewriteFile.
|
|
|
|
// Guide to the test packages:
|
|
//
|
|
// new.com/one -- canonical name for old.com/one
|
|
// old.com/one -- non-canonical; has import comment "new.com/one"
|
|
// old.com/bad -- has a parse error
|
|
// fruit.io/orange \
|
|
// fruit.io/banana } orange -> pear -> banana -> titanic.biz/bar
|
|
// fruit.io/pear /
|
|
// titanic.biz/bar -- domain is sinking; package has jumped ship to new.com/bar
|
|
// titanic.biz/foo -- domain is sinking but package has no import comment yet
|
|
|
|
func TestFixImports(t *testing.T) {
|
|
gopath := cwd + "/testdata"
|
|
if err := os.Setenv("GOPATH", gopath); err != nil {
|
|
t.Fatalf("os.Setenv: %v", err)
|
|
}
|
|
defer func() {
|
|
stderr = os.Stderr
|
|
*badDomains = "code.google.com"
|
|
}()
|
|
|
|
for i, test := range []struct {
|
|
packages []string // packages to rewrite, "go list" syntax
|
|
badDomains string // -baddomains flag
|
|
wantOK bool
|
|
wantStderr string
|
|
wantRewrite map[string]string
|
|
}{
|
|
// #0. No errors.
|
|
{
|
|
packages: []string{"all"},
|
|
badDomains: "code.google.com",
|
|
wantOK: true,
|
|
wantStderr: `
|
|
testdata/src/old.com/bad/bad.go:2:43: expected 'package', found 'EOF'
|
|
fruit.io/banana
|
|
fixed: old.com/one -> new.com/one
|
|
fixed: titanic.biz/bar -> new.com/bar
|
|
`,
|
|
wantRewrite: map[string]string{
|
|
"$GOPATH/src/fruit.io/banana/banana.go": `package banana
|
|
|
|
import (
|
|
_ "new.com/bar"
|
|
_ "new.com/one"
|
|
_ "titanic.biz/foo"
|
|
)`,
|
|
},
|
|
},
|
|
// #1. No packages needed rewriting.
|
|
{
|
|
packages: []string{"titanic.biz/...", "old.com/...", "new.com/..."},
|
|
badDomains: "code.google.com",
|
|
wantOK: true,
|
|
wantStderr: `
|
|
testdata/src/old.com/bad/bad.go:2:43: expected 'package', found 'EOF'
|
|
`,
|
|
},
|
|
// #2. Some packages without import comments matched bad domains.
|
|
{
|
|
packages: []string{"all"},
|
|
badDomains: "titanic.biz",
|
|
wantOK: false,
|
|
wantStderr: `
|
|
testdata/src/old.com/bad/bad.go:2:43: expected 'package', found 'EOF'
|
|
fruit.io/banana
|
|
testdata/src/fruit.io/banana/banana.go:6: import "titanic.biz/foo"
|
|
fixed: old.com/one -> new.com/one
|
|
fixed: titanic.biz/bar -> new.com/bar
|
|
ERROR: titanic.biz/foo has no import comment
|
|
imported directly by:
|
|
fruit.io/pear
|
|
imported indirectly by:
|
|
fruit.io/orange
|
|
`,
|
|
wantRewrite: map[string]string{
|
|
"$GOPATH/src/fruit.io/banana/banana.go": `package banana
|
|
|
|
import (
|
|
_ "new.com/bar"
|
|
_ "new.com/one"
|
|
_ "titanic.biz/foo"
|
|
)`,
|
|
},
|
|
},
|
|
} {
|
|
*badDomains = test.badDomains
|
|
|
|
stderr = new(bytes.Buffer)
|
|
gotRewrite := make(map[string]string)
|
|
writeFile = func(filename string, content []byte, mode os.FileMode) error {
|
|
filename = strings.Replace(filename, gopath, "$GOPATH", 1)
|
|
gotRewrite[filename] = string(bytes.TrimSpace(content))
|
|
return nil
|
|
}
|
|
|
|
// Check status code.
|
|
if fiximports(test.packages...) != test.wantOK {
|
|
t.Errorf("#%d. fiximports() = %t", i, !test.wantOK)
|
|
}
|
|
|
|
// Compare stderr output.
|
|
if stderr.(*bytes.Buffer).String() != test.wantStderr {
|
|
t.Errorf("#%d. stderr: got <<%s>>, want <<%s>>",
|
|
i, stderr, test.wantStderr)
|
|
}
|
|
|
|
// Compare rewrites.
|
|
for k, v := range gotRewrite {
|
|
if test.wantRewrite[k] != v {
|
|
t.Errorf("#%d. rewrite[%s] = <<%s>>, want <<%s>>",
|
|
i, k, v, test.wantRewrite[k])
|
|
}
|
|
delete(test.wantRewrite, k)
|
|
}
|
|
for k, v := range test.wantRewrite {
|
|
t.Errorf("#%d. rewrite[%s] missing, want <<%s>>", i, k, v)
|
|
}
|
|
}
|
|
}
|
|
|
|
// TestDryRun tests that the -n flag suppresses calls to writeFile.
|
|
func TestDryRun(t *testing.T) {
|
|
gopath := cwd + "/testdata"
|
|
if err := os.Setenv("GOPATH", gopath); err != nil {
|
|
t.Fatalf("os.Setenv: %v", err)
|
|
}
|
|
|
|
*dryrun = true
|
|
defer func() { *dryrun = false }() // restore
|
|
stderr = new(bytes.Buffer)
|
|
writeFile = func(filename string, content []byte, mode os.FileMode) error {
|
|
t.Fatalf("writeFile(%s) called in dryrun mode", filename)
|
|
return nil
|
|
}
|
|
|
|
if !fiximports("all") {
|
|
t.Fatalf("fiximports failed: %s", stderr)
|
|
}
|
|
}
|