// repoForTool returns the correct RepoRoot for the buildTool, or an error if // the tool is unknown. func repoForTool() (*vcs.RepoRoot, error) { switch *buildTool { case "go": return vcs.RepoRootForImportPath(*gcPath, *verbose) case "gccgo": return vcs.RepoRootForImportPath(gofrontendImportPath, *verbose) default: return nil, fmt.Errorf("unknown build tool: %s", *buildTool) } }
// RemoteRepo constructs a *Repo representing a remote repository. func RemoteRepo(url, path string) (*Repo, error) { rr, err := vcs.RepoRootForImportPath(url, *verbose) if err != nil { return nil, err } return &Repo{ Path: path, Master: rr, }, nil }
func VCSForImportPath(importPath string) (*VCS, *vcs.RepoRoot, error) { rr, err := vcs.RepoRootForImportPath(importPath, false) if err != nil { return nil, nil, err } vcs := cmd[rr.VCS] if vcs == nil { return nil, nil, fmt.Errorf("%s is unsupported: %s", rr.VCS.Name, importPath) } return vcs, rr, nil }
func main() { flag.Parse() if *importPathFlag != "" { repoRoot, err := vcs.RepoRootForImportPath(*importPathFlag, false) if err == nil { fmt.Fprintln(os.Stdout, toJson(repoRoot)) os.Exit(0) } else { fmt.Fprintln(os.Stderr, err.Error()) os.Exit(1) } } }
// buildSubrepo fetches the given package, updates it to the specified hash, // and runs 'go test -short pkg/...'. It returns the build log and any error. func (b *Builder) buildSubrepo(goRoot, goPath, pkg, hash string) (string, error) { goTool := filepath.Join(goRoot, "bin", "go") + exeExt env := append(b.envv(), "GOROOT="+goRoot, "GOPATH="+goPath) // add $GOROOT/bin and $GOPATH/bin to PATH for i, e := range env { const p = "PATH=" if !strings.HasPrefix(e, p) { continue } sep := string(os.PathListSeparator) env[i] = p + filepath.Join(goRoot, "bin") + sep + filepath.Join(goPath, "bin") + sep + e[len(p):] } // fetch package and dependencies log, ok, err := runLog(*cmdTimeout, env, goPath, goTool, "get", "-d", pkg+"/...") if err == nil && !ok { err = fmt.Errorf("go exited with status 1") } if err != nil { return log, err } // hg update to the specified hash pkgmaster, err := vcs.RepoRootForImportPath(pkg, *verbose) if err != nil { return "", fmt.Errorf("Error finding subrepo (%s): %s", pkg, err) } repo := &Repo{ Path: filepath.Join(goPath, "src", pkg), Master: pkgmaster, } if err := repo.UpdateTo(hash); err != nil { return "", err } // test the package log, ok, err = runLog(*buildTimeout, env, goPath, goTool, "test", "-short", pkg+"/...") if err == nil && !ok { err = fmt.Errorf("go exited with status 1") } return log, err }
// commitWatcher polls hg for new commits and tells the dashboard about them. func commitWatcher(goroot *Repo) { if *commitInterval == 0 { log.Printf("commitInterval is %s, disabling commitWatcher", *commitInterval) return } // Create builder just to get master key. b, err := NewBuilder(goroot, "mercurial-commit") if err != nil { log.Fatal(err) } key := b.key benchMutex.RLock() for { if *verbose { log.Printf("poll...") } // Main Go repository. commitPoll(goroot, "", key) // Go sub-repositories. for _, pkg := range dashboardPackages("subrepo") { pkgmaster, err := vcs.RepoRootForImportPath(pkg, *verbose) if err != nil { log.Printf("Error finding subrepo (%s): %s", pkg, err) continue } pkgroot := &Repo{ Path: filepath.Join(*buildroot, pkg), Master: pkgmaster, } commitPoll(pkgroot, pkg, key) } benchMutex.RUnlock() if *verbose { log.Printf("sleep...") } time.Sleep(*commitInterval) benchMutex.RLock() } }
// buildSubrepo fetches the given package, updates it to the specified hash, // and runs 'go test -short pkg/...'. It returns the build log and any error. func (b *Builder) buildSubrepo(goRoot, goPath, pkg, hash string) (string, error) { goTool := filepath.Join(goRoot, "bin", "go") + exeExt env := append(b.envv(), "GOROOT="+goRoot, "GOPATH="+goPath) // add $GOROOT/bin and $GOPATH/bin to PATH for i, e := range env { const p = "PATH=" if !strings.HasPrefix(e, p) { continue } sep := string(os.PathListSeparator) env[i] = p + filepath.Join(goRoot, "bin") + sep + filepath.Join(goPath, "bin") + sep + e[len(p):] } // fetch package and dependencies var outbuf bytes.Buffer err := run(exec.Command(goTool, "get", "-d", pkg+"/..."), runEnv(env), allOutput(&outbuf), runDir(goPath)) if err != nil { return outbuf.String(), err } outbuf.Reset() // hg update to the specified hash pkgmaster, err := vcs.RepoRootForImportPath(pkg, *verbose) if err != nil { return "", fmt.Errorf("Error finding subrepo (%s): %s", pkg, err) } repo := &Repo{ Path: filepath.Join(goPath, "src", pkg), Master: pkgmaster, } if err := repo.UpdateTo(hash); err != nil { return "", err } // test the package err = run(exec.Command(goTool, "test", "-short", pkg+"/..."), runTimeout(*buildTimeout), runEnv(env), allOutput(&outbuf), runDir(goPath)) return outbuf.String(), err }
func repoForDep(dep *parser.Dependency) (*vcs.RepoRoot, error) { if dep.URL != "" { return RepoRootForImportPathWithURLOverride(dep.Pkg, dep.URL) } return vcs.RepoRootForImportPath(dep.Pkg, true) }
func (g *Goop) parseAndInstall(goopfile *os.File, writeLockFile bool) error { defer goopfile.Close() deps, err := parser.Parse(goopfile) if err != nil { return err } srcPath := path.Join(g.vendorDir(), "src") tmpGoPath := path.Join(g.vendorDir(), "tmp") tmpSrcPath := path.Join(tmpGoPath, "src") err = os.RemoveAll(tmpGoPath) if err != nil { return err } err = os.MkdirAll(tmpSrcPath, 0775) if err != nil { return err } repos := map[string]*vcs.RepoRoot{} lockedDeps := map[string]*parser.Dependency{} for _, dep := range deps { if dep.URL == "" { g.stdout.Write([]byte(colors.OK + "=> Fetching " + dep.Pkg + "..." + colors.Reset + "\n")) } else { g.stdout.Write([]byte(colors.OK + "=> Fetching " + dep.Pkg + " from " + dep.URL + "..." + colors.Reset + "\n")) } repo, err := repoForDep(dep) if err != nil { return err } repos[dep.Pkg] = repo pkgPath := path.Join(srcPath, repo.Root) tmpPkgPath := path.Join(tmpSrcPath, repo.Root) err = os.MkdirAll(path.Join(tmpPkgPath, ".."), 0775) if err != nil { return err } noclone := false exists, err := pathExists(pkgPath) if err != nil { return err } tmpExists, err := pathExists(tmpPkgPath) if err != nil { return err } if exists { // if package already exists, just symlink package dir and skip cloning g.stderr.Write([]byte(colors.Warn + "Warning: " + pkgPath + " already exists; skipping!" + colors.Reset + "\n")) if !tmpExists { err = os.Symlink(pkgPath, tmpPkgPath) if err != nil { return err } } noclone = true } else { noclone = tmpExists } if !noclone { // clone repo err = g.clone(repo.VCS.Cmd, repo.Repo, tmpPkgPath) if err != nil { return err } } // if rev is not given, record current rev in path if dep.Rev == "" { rev, err := g.currentRev(repo.VCS.Cmd, tmpPkgPath) if err != nil { return err } dep.Rev = rev } lockedDeps[dep.Pkg] = dep // checkout specified rev err = g.checkout(repo.VCS.Cmd, tmpPkgPath, dep.Rev) if err != nil { return err } } for _, dep := range deps { g.stdout.Write([]byte(colors.OK + "=> Fetching dependencies for " + dep.Pkg + "..." + colors.Reset + "\n")) repo := repos[dep.Pkg] tmpPkgPath := path.Join(tmpSrcPath, repo.Root) // fetch sub-dependencies subdeps, err := g.goGet(tmpPkgPath, tmpGoPath) if err != nil { return err } for _, subdep := range subdeps { subdepRepo, err := vcs.RepoRootForImportPath(subdep, true) if err != nil { return err } subdepPkgPath := path.Join(tmpSrcPath, subdepRepo.Root) rev, err := g.currentRev(subdepRepo.VCS.Cmd, subdepPkgPath) if err != nil { return err } err = g.checkout(subdepRepo.VCS.Cmd, subdepPkgPath, rev) if err != nil { return err } repos[subdep] = subdepRepo lockedDeps[subdep] = &parser.Dependency{Pkg: subdep, Rev: rev} } } for _, dep := range lockedDeps { g.stdout.Write([]byte(colors.OK + "=> Installing " + dep.Pkg + "..." + colors.Reset + "\n")) repo := repos[dep.Pkg] pkgPath := path.Join(srcPath, repo.Root) tmpPkgPath := path.Join(tmpSrcPath, repo.Root) err = os.MkdirAll(path.Join(pkgPath, ".."), 0775) if err != nil { return err } lfi, err := os.Lstat(tmpPkgPath) if err != nil && !os.IsNotExist(err) { return err } if err == nil { if lfi.Mode()&os.ModeSymlink == 0 { // move package to vendor path err = os.RemoveAll(pkgPath) if err != nil { return err } err = os.Rename(tmpPkgPath, pkgPath) } else { // package already in vendor path, just remove the symlink err = os.Remove(tmpPkgPath) } if err != nil { return err } } } for _, dep := range lockedDeps { // install repo := repos[dep.Pkg] pkgPath := path.Join(srcPath, repo.Root) cmd := g.command(pkgPath, "go", "install", "-x", dep.Pkg) cmd.Env = g.patchedEnv(true).Strings() cmd.Run() } err = os.RemoveAll(tmpGoPath) if err != nil { return err } // in order to minimize diffs, we sort lockedDeps first and write the // sorted results if writeLockFile { lf, err := os.Create(path.Join(g.dir, "Goopfile.lock")) defer lf.Close() var keys []string for k := range lockedDeps { keys = append(keys, k) } sort.Strings(keys) for _, k := range keys { dep := lockedDeps[k] _, err = lf.WriteString(dep.String() + "\n") if err != nil { return err } } } g.stdout.Write([]byte(colors.OK + "=> Done!" + colors.Reset + "\n")) return nil }