Skip to content

Commit ffa3839

Browse files
committed
cmd/bundle: use caller's module version via go/packages
Also, remove obsolete -underscore option. Fixes golang/go#32031 Updates golang/go#24661 Change-Id: I47940a7ccfaf82a042eadc76f47304fc1dd8cbdd Reviewed-on: https://go-review.googlesource.com/c/tools/+/189818 Run-TryBot: Dmitri Shuralyov <[email protected]> gopls-CI: kokoro <[email protected]> TryBot-Result: Go Bot <[email protected]> Reviewed-by: Dmitri Shuralyov <[email protected]> Reviewed-by: Bryan C. Mills <[email protected]>
1 parent d7fc70a commit ffa3839

File tree

2 files changed

+67
-80
lines changed

2 files changed

+67
-80
lines changed

cmd/bundle/main.go

+50-67
Original file line numberDiff line numberDiff line change
@@ -33,12 +33,9 @@
3333
// corresponding symbols.
3434
// Bundle also must write a package declaration in the output and must
3535
// choose a name to use in that declaration.
36+
// If the -pkg option is given, bundle uses that name.
37+
// Otherwise, the name of the destination package is used.
3638
// Build constraints for the generated file can be specified using the -tags option.
37-
// If the -package option is given, bundle uses that name.
38-
// Otherwise, if the -dst option is given, bundle uses the last
39-
// element of the destination import path.
40-
// Otherwise, by default bundle uses the package name found in the
41-
// package sources in the current directory.
4239
//
4340
// To avoid collisions, bundle inserts a prefix at the beginning of
4441
// every package-level const, func, type, and var identifier in src's code,
@@ -58,28 +55,19 @@
5855
// bundle -o zip.go archive/zip
5956
//
6057
// Bundle golang.org/x/net/http2 for inclusion in net/http,
61-
// prefixing all identifiers by "http2" instead of "http2_",
62-
// and rewriting the import "golang.org/x/net/http2/hpack"
63-
// to "internal/golang.org/x/net/http2/hpack", and also include
64-
// a "!nethttpomithttp2" build constraint:
58+
// prefixing all identifiers by "http2" instead of "http2_", and
59+
// including a "!nethttpomithttp2" build constraint:
6560
//
6661
// cd $GOROOT/src/net/http
67-
// bundle -o h2_bundle.go \
68-
// -prefix http2 \
69-
// -import golang.org/x/net/http2/hpack=internal/golang.org/x/net/http2/hpack \
70-
// -tags '!nethttpomithttp2' \
71-
// golang.org/x/net/http2
62+
// bundle -o h2_bundle.go -prefix http2 -tags '!nethttpomithttp2' golang.org/x/net/http2
7263
//
73-
// Two ways to update the http2 bundle:
64+
// Update the http2 bundle in net/http:
7465
//
7566
// go generate net/http
7667
//
77-
// cd $GOROOT/src/net/http
78-
// go generate
79-
//
80-
// Update both bundles, restricting ``go generate'' to running bundle commands:
68+
// Update all bundles in the standard library:
8169
//
82-
// go generate -run bundle cmd/dist net/http
70+
// go generate -run bundle std
8371
//
8472
package main
8573

@@ -88,28 +76,24 @@ import (
8876
"flag"
8977
"fmt"
9078
"go/ast"
91-
"go/build"
9279
"go/format"
93-
"go/parser"
9480
"go/printer"
9581
"go/token"
9682
"go/types"
9783
"io/ioutil"
9884
"log"
9985
"os"
100-
"path"
10186
"strconv"
10287
"strings"
10388

104-
"golang.org/x/tools/go/loader"
89+
"golang.org/x/tools/go/packages"
10590
)
10691

10792
var (
10893
outputFile = flag.String("o", "", "write output to `file` (default standard output)")
109-
dstPath = flag.String("dst", "", "set destination import `path` (default taken from current directory)")
110-
pkgName = flag.String("pkg", "", "set destination package `name` (default taken from current directory)")
94+
dstPath = flag.String("dst", ".", "set destination import `path`")
95+
pkgName = flag.String("pkg", "", "set destination package `name`")
11196
prefix = flag.String("prefix", "&_", "set bundled identifier prefix to `p` (default is \"&_\", where & stands for the original name)")
112-
underscore = flag.Bool("underscore", false, "rewrite golang.org/x/* to internal/x/* imports; temporary workaround for golang.org/issue/16333")
11397
buildTags = flag.String("tags", "", "the build constraints to be inserted into the generated file")
11498

11599
importMap = map[string]string{}
@@ -148,23 +132,19 @@ func main() {
148132
os.Exit(2)
149133
}
150134

151-
if *dstPath != "" {
152-
if *pkgName == "" {
153-
*pkgName = path.Base(*dstPath)
154-
}
155-
} else {
156-
wd, _ := os.Getwd()
157-
pkg, err := build.ImportDir(wd, 0)
158-
if err != nil {
159-
log.Fatalf("cannot find package in current directory: %v", err)
160-
}
161-
*dstPath = pkg.ImportPath
162-
if *pkgName == "" {
163-
*pkgName = pkg.Name
164-
}
135+
cfg := &packages.Config{Mode: packages.NeedName}
136+
pkgs, err := packages.Load(cfg, *dstPath)
137+
if err != nil {
138+
log.Fatalf("cannot load destination package: %v", err)
139+
}
140+
if packages.PrintErrors(pkgs) > 0 || len(pkgs) != 1 {
141+
log.Fatalf("failed to load destination package")
142+
}
143+
if *pkgName == "" {
144+
*pkgName = pkgs[0].Name
165145
}
166146

167-
code, err := bundle(args[0], *dstPath, *pkgName, *prefix, *buildTags)
147+
code, err := bundle(args[0], pkgs[0].PkgPath, *pkgName, *prefix, *buildTags)
168148
if err != nil {
169149
log.Fatal(err)
170150
}
@@ -191,24 +171,30 @@ func isStandardImportPath(path string) bool {
191171
return !strings.Contains(elem, ".")
192172
}
193173

194-
var ctxt = &build.Default
174+
var testingOnlyPackagesConfig *packages.Config
195175

196176
func bundle(src, dst, dstpkg, prefix, buildTags string) ([]byte, error) {
197177
// Load the initial package.
198-
conf := loader.Config{ParserMode: parser.ParseComments, Build: ctxt}
199-
conf.TypeCheckFuncBodies = func(p string) bool { return p == src }
200-
conf.Import(src)
201-
202-
lprog, err := conf.Load()
178+
cfg := &packages.Config{}
179+
if testingOnlyPackagesConfig != nil {
180+
*cfg = *testingOnlyPackagesConfig
181+
} else {
182+
// Bypass default vendor mode, as we need a package not available in the
183+
// std module vendor folder.
184+
cfg.Env = append(os.Environ(), "GOFLAGS=-mod=mod")
185+
}
186+
cfg.Mode = packages.NeedTypes | packages.NeedSyntax | packages.NeedTypesInfo
187+
pkgs, err := packages.Load(cfg, src)
203188
if err != nil {
204189
return nil, err
205190
}
191+
if packages.PrintErrors(pkgs) > 0 || len(pkgs) != 1 {
192+
return nil, fmt.Errorf("failed to load source package")
193+
}
194+
pkg := pkgs[0]
206195

207-
// Because there was a single Import call and Load succeeded,
208-
// InitialPackages is guaranteed to hold the sole requested package.
209-
info := lprog.InitialPackages()[0]
210196
if strings.Contains(prefix, "&") {
211-
prefix = strings.Replace(prefix, "&", info.Files[0].Name.Name, -1)
197+
prefix = strings.Replace(prefix, "&", pkg.Syntax[0].Name.Name, -1)
212198
}
213199

214200
objsToUpdate := make(map[types.Object]bool)
@@ -223,9 +209,9 @@ func bundle(src, dst, dstpkg, prefix, buildTags string) ([]byte, error) {
223209
// var s struct {T}
224210
// print(s.T) // ...this must change too
225211
if _, ok := from.(*types.TypeName); ok {
226-
for id, obj := range info.Uses {
212+
for id, obj := range pkg.TypesInfo.Uses {
227213
if obj == from {
228-
if field := info.Defs[id]; field != nil {
214+
if field := pkg.TypesInfo.Defs[id]; field != nil {
229215
rename(field)
230216
}
231217
}
@@ -235,7 +221,7 @@ func bundle(src, dst, dstpkg, prefix, buildTags string) ([]byte, error) {
235221
}
236222

237223
// Rename each package-level object.
238-
scope := info.Pkg.Scope()
224+
scope := pkg.Types.Scope()
239225
for _, name := range scope.Names() {
240226
rename(scope.Lookup(name))
241227
}
@@ -254,7 +240,7 @@ func bundle(src, dst, dstpkg, prefix, buildTags string) ([]byte, error) {
254240
fmt.Fprintf(&out, "\n")
255241

256242
// Concatenate package comments from all files...
257-
for _, f := range info.Files {
243+
for _, f := range pkg.Syntax {
258244
if doc := f.Doc.Text(); strings.TrimSpace(doc) != "" {
259245
for _, line := range strings.Split(doc, "\n") {
260246
fmt.Fprintf(&out, "// %s\n", line)
@@ -283,11 +269,11 @@ func bundle(src, dst, dstpkg, prefix, buildTags string) ([]byte, error) {
283269
// to deduplicate instances of the same import name and path.
284270
var pkgStd = make(map[string]bool)
285271
var pkgExt = make(map[string]bool)
286-
for _, f := range info.Files {
272+
for _, f := range pkg.Syntax {
287273
for _, imp := range f.Imports {
288274
path, err := strconv.Unquote(imp.Path.Value)
289275
if err != nil {
290-
log.Fatalf("invalid import path string: %v", err) // Shouldn't happen here since conf.Load succeeded.
276+
log.Fatalf("invalid import path string: %v", err) // Shouldn't happen here since packages.Load succeeded.
291277
}
292278
if path == dst {
293279
continue
@@ -304,9 +290,6 @@ func bundle(src, dst, dstpkg, prefix, buildTags string) ([]byte, error) {
304290
if isStandardImportPath(path) {
305291
pkgStd[spec] = true
306292
} else {
307-
if *underscore {
308-
spec = strings.Replace(spec, "golang.org/x/", "internal/x/", 1)
309-
}
310293
pkgExt[spec] = true
311294
}
312295
}
@@ -326,14 +309,14 @@ func bundle(src, dst, dstpkg, prefix, buildTags string) ([]byte, error) {
326309
fmt.Fprint(&out, ")\n\n")
327310

328311
// Modify and print each file.
329-
for _, f := range info.Files {
312+
for _, f := range pkg.Syntax {
330313
// Update renamed identifiers.
331-
for id, obj := range info.Defs {
314+
for id, obj := range pkg.TypesInfo.Defs {
332315
if objsToUpdate[obj] {
333316
id.Name = prefix + obj.Name()
334317
}
335318
}
336-
for id, obj := range info.Uses {
319+
for id, obj := range pkg.TypesInfo.Uses {
337320
if objsToUpdate[obj] {
338321
id.Name = prefix + obj.Name()
339322
}
@@ -345,7 +328,7 @@ func bundle(src, dst, dstpkg, prefix, buildTags string) ([]byte, error) {
345328
ast.Inspect(f, func(n ast.Node) bool {
346329
if sel, ok := n.(*ast.SelectorExpr); ok {
347330
if id, ok := sel.X.(*ast.Ident); ok {
348-
if obj, ok := info.Uses[id].(*types.PkgName); ok {
331+
if obj, ok := pkg.TypesInfo.Uses[id].(*types.PkgName); ok {
349332
if obj.Imported().Path() == dst {
350333
id.Name = "@@@"
351334
}
@@ -379,12 +362,12 @@ func bundle(src, dst, dstpkg, prefix, buildTags string) ([]byte, error) {
379362
printComments(&out, f.Comments, last, beg)
380363

381364
buf.Reset()
382-
format.Node(&buf, lprog.Fset, &printer.CommentedNode{Node: decl, Comments: f.Comments})
365+
format.Node(&buf, pkg.Fset, &printer.CommentedNode{Node: decl, Comments: f.Comments})
383366
// Remove each "@@@." in the output.
384367
// TODO(adonovan): not hygienic.
385368
out.Write(bytes.Replace(buf.Bytes(), []byte("@@@."), nil, -1))
386369

387-
last = printSameLineComment(&out, f.Comments, lprog.Fset, end)
370+
last = printSameLineComment(&out, f.Comments, pkg.Fset, end)
388371

389372
out.WriteString("\n\n")
390373
}

cmd/bundle/main_test.go

+17-13
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,6 @@
22
// Use of this source code is governed by a BSD-style
33
// license that can be found in the LICENSE file.
44

5-
// +build go1.9
6-
75
package main
86

97
import (
@@ -14,7 +12,7 @@ import (
1412
"runtime"
1513
"testing"
1614

17-
"golang.org/x/tools/go/buildutil"
15+
"golang.org/x/tools/go/packages/packagestest"
1816
)
1917

2018
func TestBundle(t *testing.T) {
@@ -26,25 +24,31 @@ func TestBundle(t *testing.T) {
2624
return string(data)
2725
}
2826

29-
ctxt = buildutil.FakeContext(map[string]map[string]string{
30-
"initial": {
31-
"a.go": load("testdata/src/initial/a.go"),
32-
"b.go": load("testdata/src/initial/b.go"),
33-
"c.go": load("testdata/src/initial/c.go"),
34-
},
35-
"domain.name/importdecl": {
36-
"p.go": load("testdata/src/domain.name/importdecl/p.go"),
27+
e := packagestest.Export(t, packagestest.Modules, []packagestest.Module{
28+
{
29+
Name: "initial",
30+
Files: map[string]interface{}{
31+
"a.go": load("testdata/src/initial/a.go"),
32+
"b.go": load("testdata/src/initial/b.go"),
33+
"c.go": load("testdata/src/initial/c.go"),
34+
},
3735
},
38-
"fmt": {
39-
"print.go": `package fmt; func Println(...interface{})`,
36+
{
37+
Name: "domain.name/importdecl",
38+
Files: map[string]interface{}{
39+
"p.go": load("testdata/src/domain.name/importdecl/p.go"),
40+
},
4041
},
4142
})
43+
defer e.Cleanup()
44+
testingOnlyPackagesConfig = e.Config
4245

4346
os.Args = os.Args[:1] // avoid e.g. -test=short in the output
4447
out, err := bundle("initial", "github.com/dest", "dest", "prefix", "tag")
4548
if err != nil {
4649
t.Fatal(err)
4750
}
51+
4852
if got, want := string(out), load("testdata/out.golden"); got != want {
4953
t.Errorf("-- got --\n%s\n-- want --\n%s\n-- diff --", got, want)
5054

0 commit comments

Comments
 (0)