// RunCommand detects the project root, parses flags and runs the Command. func RunCommand(fs *flag.FlagSet, cmd *Command, projectroot, goroot string, args []string) error { if cmd.AddFlags != nil { cmd.AddFlags(fs) } if err := fs.Parse(args); err != nil { fs.Usage() os.Exit(1) } args = fs.Args() // reset to the remaining arguments if projectroot == "" { return fmt.Errorf("project root is blank") } root, err := FindProjectroot(projectroot) if err != nil { return fmt.Errorf("could not locate project root: %v", err) } project := gb.NewProject(root) gb.Debugf("project root %q", project.Projectdir()) ctx, err := project.NewContext( gb.GcToolchain(), ) if err != nil { return fmt.Errorf("unable to construct context: %v", err) } gb.Debugf("args: %v", args) return cmd.Run(ctx, args) }
func main() { args := os.Args[1:] switch { case len(args) < 1, args[0] == "-h", args[0] == "-help": fs.Usage() os.Exit(1) case args[0] == "help": help(args[1:]) return case projectroot == "": gb.Fatalf("don't run this binary directly, it is meant to be run as 'gb vendor ...'") default: } root, err := cmd.FindProjectroot(projectroot) if err != nil { gb.Fatalf("could not locate project root: %v", err) } project := gb.NewProject(root, gb.SourceDir(filepath.Join(root, "src")), gb.SourceDir(filepath.Join(root, "vendor", "src"))) gb.Debugf("project root %q", project.Projectdir()) for _, command := range commands { if command.Name == args[0] && command.Runnable() { // add extra flags if necessary if command.AddFlags != nil { command.AddFlags(fs) } if command.FlagParse != nil { err = command.FlagParse(fs, args) } else { err = fs.Parse(args[1:]) } if err != nil { gb.Fatalf("could not parse flags: %v", err) } args = fs.Args() // reset args to the leftovers from fs.Parse gb.Debugf("args: %v", args) ctx, err := project.NewContext( gb.GcToolchain(), ) if err != nil { gb.Fatalf("unable to construct context: %v", err) } defer ctx.Destroy() if err := command.Run(ctx, args); err != nil { gb.Fatalf("command %q failed: %v", command.Name, err) } return } } gb.Fatalf("unknown command %q ", args[0]) }
func main() { root, err := cmd.FindProjectroot(projectroot) if err != nil { gb.Fatalf("could not locate project root: %v", err) } project := gb.NewProject(root) gb.Debugf("project root %q", project.Projectdir()) args := os.Args[1:] if len(args) < 1 || args[0] == "-h" { fs.Usage() os.Exit(1) } if args[0] == "help" { help(args[1:]) return } for _, command := range commands { if command.Name == args[0] && command.Runnable() { // add extra flags if necessary if command.AddFlags != nil { command.AddFlags(fs) } if command.FlagParse != nil { err = command.FlagParse(fs, args) } else { err = fs.Parse(args[1:]) } if err != nil { gb.Fatalf("could not parse flags: %v", err) } args = fs.Args() // reset args to the leftovers from fs.Parse gb.Debugf("args: %v", args) ctx, err := project.NewContext( gb.GcToolchain(), ) if err != nil { gb.Fatalf("unable to construct context: %v", err) } if err := command.Run(ctx, args); err != nil { gb.Fatalf("command %q failed: %v", command.Name, err) } return } } gb.Fatalf("unknown command %q ", args[0]) }
// ResolvePackagesWithTests is similar to ResolvePackages however // it also loads the test and external test packages of args into // the context. func ResolvePackagesWithTests(r Resolver, paths ...string) ([]*gb.Package, error) { var pkgs []*gb.Package for _, path := range paths { path = relImportPath(r.Srcdirs()[0], path) pkg, err := r.ResolvePackageWithTests(path) if err != nil { if _, ok := err.(*build.NoGoError); ok { gb.Debugf("skipping %q", path) continue } return pkgs, fmt.Errorf("failed to resolve package %q: %v", path, err) } pkgs = append(pkgs, pkg) } return pkgs, nil }
// loadTestFuncs returns the testFuncs describing the tests that will be run. func loadTestFuncs(ptest *build.Package) (*testFuncs, error) { t := &testFuncs{ Package: ptest, } gb.Debugf("loadTestFuncs: %v, %v", ptest.TestGoFiles, ptest.XTestGoFiles) for _, file := range ptest.TestGoFiles { if err := t.load(filepath.Join(ptest.Dir, file), "_test", &t.ImportTest, &t.NeedTest); err != nil { return nil, err } } for _, file := range ptest.XTestGoFiles { if err := t.load(filepath.Join(ptest.Dir, file), "_xtest", &t.ImportXtest, &t.NeedXtest); err != nil { return nil, err } } return t, nil }
// NewContext creates a gb.Context for the project root. func NewContext(projectroot string, options ...func(*gb.Context) error) (*gb.Context, error) { if projectroot == "" { return nil, fmt.Errorf("project root is blank") } root, err := FindProjectroot(projectroot) if err != nil { return nil, fmt.Errorf("could not locate project root: %v", err) } project := gb.NewProject(root, gb.SourceDir(filepath.Join(root, "src")), gb.SourceDir(filepath.Join(root, "vendor", "src")), ) gb.Debugf("project root %q", project.Projectdir()) return project.NewContext(options...) }
// RunCommand detects the project root, parses flags and runs the Command. func RunCommand(fs *flag.FlagSet, cmd *Command, projectroot, goroot string, args []string) error { if cmd.AddFlags != nil { cmd.AddFlags(fs) } if err := fs.Parse(args); err != nil { fs.Usage() os.Exit(1) } args = fs.Args() // reset to the remaining arguments ctx, err := NewContext(projectroot, gb.GcToolchain()) if err != nil { return fmt.Errorf("unable to construct context: %v", err) } gb.Debugf("args: %v", args) return cmd.Run(ctx, args) }
// TestPackages produces a graph of Actions that when executed build // and test the supplied packages. func TestPackages(flags []string, pkgs ...*gb.Package) (*gb.Action, error) { if len(pkgs) < 1 { return nil, fmt.Errorf("no test packages provided") } targets := make(map[string]*gb.Action) // maps package import paths to their test run action names := func(pkgs []*gb.Package) []string { var names []string for _, pkg := range pkgs { names = append(names, pkg.ImportPath) } return names } // create top level test action to root all test actions t0 := time.Now() test := gb.Action{ Name: fmt.Sprintf("test: %s", strings.Join(names(pkgs), ",")), Task: gb.TaskFn(func() error { gb.Debugf("test duration: %v %v", time.Since(t0), pkgs[0].Statistics.String()) return nil }), } for _, pkg := range pkgs { a, err := TestPackage(targets, pkg, flags) if err != nil { return nil, err } if a == nil { // nothing to do ?? not even a test action ? continue } test.Deps = append(test.Deps, a) } return &test, nil }
// TestPackage returns an Action representing the steps required to build // and test this Package. func TestPackage(targets map[string]*gb.Action, pkg *gb.Package, flags []string) (*gb.Action, error) { var gofiles []string gofiles = append(gofiles, pkg.GoFiles...) gofiles = append(gofiles, pkg.TestGoFiles...) var cgofiles []string cgofiles = append(cgofiles, pkg.CgoFiles...) var imports []string imports = append(imports, pkg.Package.Imports...) imports = append(imports, pkg.Package.TestImports...) name := pkg.Name if name == "main" { // rename the main package to its package name for testing. name = filepath.Base(filepath.FromSlash(pkg.ImportPath)) } // internal tests testpkg := gb.NewPackage(pkg.Context, &build.Package{ Name: name, ImportPath: pkg.ImportPath, Dir: pkg.Dir, SrcRoot: pkg.SrcRoot, GoFiles: gofiles, CFiles: pkg.CFiles, CgoFiles: cgofiles, TestGoFiles: pkg.TestGoFiles, // passed directly to buildTestMain XTestGoFiles: pkg.XTestGoFiles, // passed directly to buildTestMain CgoCFLAGS: pkg.CgoCFLAGS, CgoCPPFLAGS: pkg.CgoCPPFLAGS, CgoCXXFLAGS: pkg.CgoCXXFLAGS, CgoLDFLAGS: pkg.CgoLDFLAGS, CgoPkgConfig: pkg.CgoPkgConfig, Imports: imports, }) testpkg.Scope = "test" testpkg.Stale = true // build dependencies deps, err := gb.BuildDependencies(targets, testpkg) if err != nil { return nil, err } // only build the internal test if there is Go source or // internal test files. var testobj *gb.Action if len(testpkg.GoFiles)+len(testpkg.CgoFiles)+len(testpkg.TestGoFiles) > 0 { var err error testobj, err = gb.Compile(testpkg, deps...) if err != nil { return nil, err } } // external tests if len(pkg.XTestGoFiles) > 0 { xtestpkg := gb.NewPackage(pkg.Context, &build.Package{ Name: name, ImportPath: pkg.ImportPath + "_test", Dir: pkg.Dir, GoFiles: pkg.XTestGoFiles, Imports: pkg.XTestImports, }) // build external test dependencies deps, err := gb.BuildDependencies(targets, xtestpkg) if err != nil { return nil, err } xtestpkg.Scope = "test" xtestpkg.Stale = true xtestpkg.ExtraIncludes = filepath.Join(pkg.Workdir(), filepath.FromSlash(pkg.ImportPath), "_test") // if there is an internal test object, add it as a dependency. if testobj != nil { deps = append(deps, testobj) } testobj, err = gb.Compile(xtestpkg, deps...) if err != nil { return nil, err } } testmainpkg, err := buildTestMain(testpkg) if err != nil { return nil, err } testmain, err := gb.Compile(testmainpkg, testobj) if err != nil { return nil, err } cmd := exec.Command(testmainpkg.Binfile()+".test", flags...) cmd.Dir = pkg.Dir // tests run in the original source directory cmd.Stdout = os.Stdout cmd.Stderr = os.Stderr gb.Debugf("scheduling run of %v", cmd.Args) return &gb.Action{ Name: fmt.Sprintf("run: %s", cmd.Args), Deps: []*gb.Action{testmain}, Task: gb.TaskFn(func() error { return cmd.Run() }), }, nil }
func main() { args := os.Args if len(args) < 2 || args[1] == "-h" { fs.Usage() os.Exit(1) } name := args[1] if name == "help" { help(args[2:]) return } command, ok := commands[name] if (command != nil && !command.Runnable()) || !ok { if _, err := lookupPlugin(name); err != nil { gb.Errorf("unknown command %q", name) fs.Usage() os.Exit(1) } command = commands["plugin"] } // add extra flags if necessary if command.AddFlags != nil { command.AddFlags(fs) } var err error if command.FlagParse != nil { err = command.FlagParse(fs, args) } else { err = fs.Parse(args[2:]) } if err != nil { gb.Fatalf("could not parse flags: %v", err) } args = fs.Args() // reset args to the leftovers from fs.Parse if command == commands["plugin"] { args = append([]string{name}, args...) } cwd, err := filepath.Abs(cwd) // if cwd was passed in via -R, make sure it is absolute if err != nil { gb.Fatalf("could not make project root absolute: %v", err) } ctx, err := cmd.NewContext( cwd, // project root gb.GcToolchain(), gb.Gcflags(gcflags), gb.Ldflags(ldflags), ) if err != nil { gb.Fatalf("unable to construct context: %v", err) } if !noDestroyContext { defer ctx.Destroy() } if command.ParseArgs != nil { args = command.ParseArgs(ctx, ctx.Projectdir(), args) } else { args = cmd.ImportPaths(ctx, cwd, args) } gb.Debugf("args: %v", args) if err := command.Run(ctx, args); err != nil { gb.Fatalf("command %q failed: %v", name, err) } }
Short: "test packages", Long: ` 'gb test' automates testing the packages named by the import paths. 'gb test' recompiles each package along with any files with names matching the file pattern "*_test.go". See 'go help test' `, Run: func(ctx *gb.Context, args []string) error { t0 := time.Now() ctx.Force = F ctx.SkipInstall = FF defer func() { gb.Debugf("test duration: %v %v", time.Since(t0), ctx.Statistics.String()) }() pkgs, err := cmd.ResolvePackagesWithTests(ctx, args...) if err != nil { return err } if err := cmd.Test(cmd.TestFlags(tfs), pkgs...); err != nil { return err } return ctx.Destroy() }, AddFlags: addTestFlags, FlagParse: func(flags *flag.FlagSet, args []string) error { var err error args, tfs, err = cmd.TestFlagsExtraParse(args[2:]) if err != nil {
func main() { args := os.Args if len(args) < 2 || args[1] == "-h" { fs.Usage() os.Exit(1) } name := args[1] if name == "help" { help(args[2:]) return } command, ok := commands[name] if (command != nil && !command.Runnable()) || !ok { plugin, err := lookupPlugin(name) if err != nil { gb.Errorf("unknown command %q", name) fs.Usage() os.Exit(1) } command = &cmd.Command{ Run: func(ctx *gb.Context, args []string) error { if len(args) < 1 { return fmt.Errorf("plugin: no command supplied") } args = append([]string{plugin}, args...) env := cmd.MergeEnv(os.Environ(), map[string]string{ "GB_PROJECT_DIR": ctx.Projectdir(), }) cmd := exec.Cmd{ Path: plugin, Args: args, Env: env, Stdin: os.Stdin, Stdout: os.Stdout, Stderr: os.Stderr, } return cmd.Run() }, // plugin should not interpret arguments ParseArgs: func(_ *gb.Context, _ string, args []string) []string { return args }, } } // add extra flags if necessary if command.AddFlags != nil { command.AddFlags(fs) } var err error if command.FlagParse != nil { err = command.FlagParse(fs, args) } else { err = fs.Parse(args[2:]) } if err != nil { gb.Fatalf("could not parse flags: %v", err) } args = fs.Args() // reset args to the leftovers from fs.Parse if command == commands["plugin"] { args = append([]string{name}, args...) } cwd, err := filepath.Abs(cwd) // if cwd was passed in via -R, make sure it is absolute if err != nil { gb.Fatalf("could not make project root absolute: %v", err) } ctx, err := cmd.NewContext( cwd, // project root gb.GcToolchain(), gb.Gcflags(gcflags), gb.Ldflags(ldflags), ) if err != nil { gb.Fatalf("unable to construct context: %v", err) } if !noDestroyContext { defer ctx.Destroy() } if command.ParseArgs != nil { args = command.ParseArgs(ctx, ctx.Projectdir(), args) } else { args = cmd.ImportPaths(ctx, cwd, args) } gb.Debugf("args: %v", args) if err := command.Run(ctx, args); err != nil { gb.Fatalf("command %q failed: %v", name, err) } }
func testPackage(targets map[string]gb.PkgTarget, pkg *gb.Package, flags []string) gb.Target { var gofiles []string gofiles = append(gofiles, pkg.GoFiles...) gofiles = append(gofiles, pkg.TestGoFiles...) var cgofiles []string cgofiles = append(cgofiles, pkg.CgoFiles...) var imports []string imports = append(imports, pkg.Package.Imports...) imports = append(imports, pkg.Package.TestImports...) name := pkg.Name if name == "main" { // rename the main package to its package name for testing. name = filepath.Base(filepath.FromSlash(pkg.ImportPath)) } // internal tests testpkg := gb.NewPackage(pkg.Context, &build.Package{ Name: name, ImportPath: pkg.ImportPath, Dir: pkg.Dir, SrcRoot: pkg.SrcRoot, GoFiles: gofiles, CFiles: pkg.CFiles, CgoFiles: cgofiles, TestGoFiles: pkg.TestGoFiles, // passed directly to buildTestMain XTestGoFiles: pkg.XTestGoFiles, // passed directly to buildTestMain CgoCFLAGS: pkg.CgoCFLAGS, CgoCPPFLAGS: pkg.CgoCPPFLAGS, CgoCXXFLAGS: pkg.CgoCXXFLAGS, CgoLDFLAGS: pkg.CgoLDFLAGS, CgoPkgConfig: pkg.CgoPkgConfig, Imports: imports, }) // build dependencies deps := gb.BuildDependencies(targets, testpkg) testpkg.Scope = "test" testpkg.Stale = true testobj := gb.Compile(testpkg, deps...) // external tests if len(pkg.XTestGoFiles) > 0 { xtestpkg := gb.NewPackage(pkg.Context, &build.Package{ Name: name, ImportPath: pkg.ImportPath + "_test", Dir: pkg.Dir, GoFiles: pkg.XTestGoFiles, Imports: pkg.XTestImports, }) // build external test dependencies deps := gb.BuildDependencies(targets, xtestpkg) xtestpkg.Scope = "test" xtestpkg.Stale = true xtestpkg.ExtraIncludes = filepath.Join(pkg.Workdir(), filepath.FromSlash(pkg.ImportPath), "_test") testobj = gb.Compile(xtestpkg, append(deps, testobj)...) } testmain, err := buildTestMain(testpkg) if err != nil { return gb.ErrTarget{err} } buildmain := gb.Ld(testmain, gb.Compile(testmain, testobj)) cmd := exec.Command(testmain.Binfile()+".test", flags...) cmd.Dir = pkg.Dir // tests run in the original source directory cmd.Stdout = os.Stdout cmd.Stderr = os.Stderr gb.Debugf("scheduling run of %v", cmd.Args) return pkg.Run(cmd, buildmain) }