|
5 | 5 | package modload
|
6 | 6 |
|
7 | 7 | import (
|
8 |
| - "bytes" |
9 | 8 | "errors"
|
10 | 9 | "fmt"
|
11 | 10 | "go/build"
|
@@ -52,6 +51,41 @@ func (e *ImportMissingError) Unwrap() error {
|
52 | 51 | return e.QueryErr
|
53 | 52 | }
|
54 | 53 |
|
| 54 | +// An AmbiguousImportError indicates an import of a package found in multiple |
| 55 | +// modules in the build list, or found in both the main module and its vendor |
| 56 | +// directory. |
| 57 | +type AmbiguousImportError struct { |
| 58 | + ImportPath string |
| 59 | + Dirs []string |
| 60 | + Modules []module.Version // Either empty or 1:1 with Dirs. |
| 61 | +} |
| 62 | + |
| 63 | +func (e *AmbiguousImportError) Error() string { |
| 64 | + locType := "modules" |
| 65 | + if len(e.Modules) == 0 { |
| 66 | + locType = "directories" |
| 67 | + } |
| 68 | + |
| 69 | + var buf strings.Builder |
| 70 | + fmt.Fprintf(&buf, "ambiguous import: found package %s in multiple %s:", e.ImportPath, locType) |
| 71 | + |
| 72 | + for i, dir := range e.Dirs { |
| 73 | + buf.WriteString("\n\t") |
| 74 | + if i < len(e.Modules) { |
| 75 | + m := e.Modules[i] |
| 76 | + buf.WriteString(m.Path) |
| 77 | + if m.Version != "" { |
| 78 | + fmt.Fprintf(&buf, " %s", m.Version) |
| 79 | + } |
| 80 | + fmt.Fprintf(&buf, " (%s)", dir) |
| 81 | + } else { |
| 82 | + buf.WriteString(dir) |
| 83 | + } |
| 84 | + } |
| 85 | + |
| 86 | + return buf.String() |
| 87 | +} |
| 88 | + |
55 | 89 | // Import finds the module and directory in the build list
|
56 | 90 | // containing the package with the given import path.
|
57 | 91 | // The answer must be unique: Import returns an error
|
@@ -96,7 +130,7 @@ func Import(path string) (m module.Version, dir string, err error) {
|
96 | 130 | mainDir, mainOK := dirInModule(path, targetPrefix, ModRoot(), true)
|
97 | 131 | vendorDir, vendorOK := dirInModule(path, "", filepath.Join(ModRoot(), "vendor"), false)
|
98 | 132 | if mainOK && vendorOK {
|
99 |
| - return module.Version{}, "", fmt.Errorf("ambiguous import: found %s in multiple directories:\n\t%s\n\t%s", path, mainDir, vendorDir) |
| 133 | + return module.Version{}, "", &AmbiguousImportError{ImportPath: path, Dirs: []string{mainDir, vendorDir}} |
100 | 134 | }
|
101 | 135 | // Prefer to return main directory if there is one,
|
102 | 136 | // Note that we're not checking that the package exists.
|
@@ -136,16 +170,7 @@ func Import(path string) (m module.Version, dir string, err error) {
|
136 | 170 | return mods[0], dirs[0], nil
|
137 | 171 | }
|
138 | 172 | if len(mods) > 0 {
|
139 |
| - var buf bytes.Buffer |
140 |
| - fmt.Fprintf(&buf, "ambiguous import: found %s in multiple modules:", path) |
141 |
| - for i, m := range mods { |
142 |
| - fmt.Fprintf(&buf, "\n\t%s", m.Path) |
143 |
| - if m.Version != "" { |
144 |
| - fmt.Fprintf(&buf, " %s", m.Version) |
145 |
| - } |
146 |
| - fmt.Fprintf(&buf, " (%s)", dirs[i]) |
147 |
| - } |
148 |
| - return module.Version{}, "", errors.New(buf.String()) |
| 173 | + return module.Version{}, "", &AmbiguousImportError{ImportPath: path, Dirs: dirs, Modules: mods} |
149 | 174 | }
|
150 | 175 |
|
151 | 176 | // Look up module containing the package, for addition to the build list.
|
|
0 commit comments