// installPackage installs the specified package and its dependencies. func installPackage(pkg, parent string, tree *build.Tree, retry bool) (installErr error) { printf("%s: install\n", pkg) // Read package information. dir := filepath.Join(tree.SrcDir(), filepath.FromSlash(pkg)) dirInfo, err := build.ScanDir(dir) if err != nil { return &PackageError{pkg, err} } // We reserve package main to identify commands. if parent != "" && dirInfo.Package == "main" { return &PackageError{pkg, fmt.Errorf("found only package main in %s; cannot import", dir)} } // Run gofix if we fail to build and -fix is set. defer func() { if retry || installErr == nil || !*doGofix { return } if e, ok := (installErr).(*DependencyError); ok { // If this package failed to build due to a // DependencyError, only attempt to gofix it if its // dependency failed for some reason other than a // DependencyError or BuildError. // (If a dep or one of its deps doesn't build there's // no way that gofixing this package can help.) switch e.err.(type) { case *DependencyError: return case *BuildError: return } } gofix(pkg, dir, dirInfo) installErr = installPackage(pkg, parent, tree, true) // retry }() // Install prerequisites. for _, p := range dirInfo.Imports { if p == "C" { continue } if err := install(p, pkg); err != nil { return &DependencyError{pkg, err} } } // Install this package. err = domake(dir, pkg, tree, dirInfo.IsCommand()) if err != nil { return &BuildError{pkg, err} } return nil }