blob: baaa2ae1bbe03fc2b528fd6cd478ed2618215249 [file] [log] [blame]
// Copyright 2017 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package main
import (
// gitCheckout sets w.Dir to the work directory
// at $HOME/go-releasebot-work/<release> (where <release> is a string like go1.8.5),
// creating it if it doesn't exist,
// and sets up a fresh git checkout in which to work,
// in $HOME/go-releasebot-work/<release>/gitwork.
// The first time it is run for a particular release,
// gitCheckout also creates a clean checkout in
// $HOME/go-releasebot-work/<release>/gitmirror,
// to use as an object cache to speed future checkouts.
// For beta releases in -mode=release, it sets w.Dir but doesn't
// fetch the latest master branch. This way the exact commit that
// was tested in prepare mode is also used in release mode.
func (w *Work) gitCheckout() {
w.Dir = filepath.Join(os.Getenv("HOME"), "go-releasebot-work/"+strings.ToLower(w.Version))
w.log.Printf("working in %s\n", w.Dir)
if err := os.MkdirAll(w.Dir, 0777); err != nil {
if w.BetaRelease && !w.Prepare {
// We don't want to fetch the latest "master" branch for
// a beta release. Instead, reuse the same commit that was
// already fetched from origin and tested in prepare mode.
const origin = ""
// Check out a local mirror to work-mirror, to speed future checkouts for this point release.
mirror := filepath.Join(w.Dir, "gitmirror")
r := w.runner(mirror)
if _, err := os.Stat(mirror); err != nil {
w.runner(w.Dir).run("git", "clone", origin, mirror)"git", "config", "", "0") // don't throw away refs we fetch
} else {"git", "fetch", "origin", "master")
}"git", "fetch", "origin", w.ReleaseBranch)
// Clone real Gerrit, but using local mirror for most objects.
gitDir := filepath.Join(w.Dir, "gitwork")
if err := os.RemoveAll(gitDir); err != nil {
w.runner(w.Dir).run("git", "clone", "--reference", mirror, "-b", w.ReleaseBranch, origin, gitDir)
r = w.runner(gitDir)"git", "codereview", "change", "relwork")"git", "config", "", "0") // don't throw away refs we fetch
// gitTagExists returns whether a git tag is already present in the repository.
func (w *Work) gitTagExists() bool {
_, err := w.runner(filepath.Join(w.Dir, "gitwork")).runErr("git", "rev-parse", w.Version)
return err == nil
// gitTagVersion tags the release candidate or release in Git.
func (w *Work) gitTagVersion() {
r := w.runner(filepath.Join(w.Dir, "gitwork"))
if w.gitTagExists() {
out := r.runOut("git", "rev-parse", w.Version)
w.VersionCommit = strings.TrimSpace(string(out))
w.log.Printf("Git tag already exists (%s), resuming release.", w.VersionCommit)
out := r.runOut("git", "rev-parse", "HEAD")
w.VersionCommit = strings.TrimSpace(string(out))
out = r.runOut("git", "show", w.VersionCommit)
fmt.Printf("About to tag the following commit as %s:\n\n%s\n\nOk? (Y/n) ", w.Version, out)
if dryRun {
var resp string
if _, err := fmt.Scanln(&resp); err != nil {
} else if resp != "Y" && resp != "y" {
w.log.Fatal("stopped as requested")
out, err := r.runErr("git", "tag", w.Version, w.VersionCommit)
if err != nil {
w.logError("git tag failed: %s\n%s", err, out)
}"git", "push", "origin", w.Version)
// gitHeadCommit returns the hash of the HEAD commit.
func (w *Work) gitHeadCommit() string {
r := w.runner(filepath.Join(w.Dir, "gitwork"))
out := r.runOut("git", "rev-parse", "HEAD")
return strings.TrimSpace(string(out))