Skip to content

Commit

Permalink
Merge pull request #3 from bzl-io/use_commit
Browse files Browse the repository at this point in the history
Allow 'use' and 'install' commands to take sha1 argument
  • Loading branch information
pcj authored Apr 29, 2019
2 parents 3697fa6 + 7af7a92 commit 4f73bd6
Show file tree
Hide file tree
Showing 8 changed files with 329 additions and 93 deletions.
43 changes: 41 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,8 +43,22 @@ Examples:
| Command | Description |
| --- | --- |
| `$ bazel install` | List all available releases |
| `$ bazel install 0.8.0` | Install bazel release 0.8.0 |
| `$ bazel install --list 0.8.0` | Show the assets bundled in install 0.8.0 |
| `$ bazel install 0.24.1` | Install bazel release 0.24.1 |
| `$ bazel install --assets 0.24.1` | Show the assets bundled in install 0.24.1 |

To build bazel from source, specify a commit-id:

```
$ bazel install 9a32b861799278217c37eb32f864a951ca99617e
(( bzl )) Install successful. Remember to 'export BAZEL_VERSION=9a32b861799278217c37eb32f864a951ca99617e'
```

> The command above will clone bazel to
> `$HOME/.cache/bzl/github.com/bazebuild/bazel`. If you already have a version
> of bazel installed that you'd rather use instead, specify
> `--bazel_source_dir`. If you want to build & install from `bazel_source_dir`
> directly (without changing to a specific commit), use `bazel install snapshot
> --bazel_source_dir=/path/to/bazel` ().
### `$ bazel use`

Expand Down Expand Up @@ -87,6 +101,31 @@ $ bazel use rules_go
...
```

You can also specify a commit-id:

```
$ bazel use rules_go ef7cca8857f2f3a905b86c264737d0043c6a766e
http_archive(
name = "io_bazel_rules_go",
urls = ["https://github.com/bazelbuild/rules_go/archive/ef7cca8857f2f3a905b86c264737d0043c6a766e.tar.gz"],
strip_prefix = "rules_go-ef7cca8857f2f3a905b86c264737d0043c6a766e",
sha256 = "1a400dc2f69971e3ebce29f7950dc38f8bb7e41c727258b6d2fb70060a4ce429",
)
```

To list recent commits on a particular branch:

```
$ bazel use rules_go --history=master
(( bzl )) 2019/04/29 06:36:48 Listing recent commit history for bazelbuild/rules_go...
ef7cca8857f2f3a905b86c264737d0043c6a766e Wed Apr 24 2019 bazel_test: fix load of generate_toolchain_names (#2040)
56ecf4406adfd8917ac59ddd0ea008ff1d8f722a Wed Apr 24 2019 Ensure bazel paths don't leak in stdlib builds (#1945)
df1bb575ad1b35703e5b62fd0455907896c9eb32 Tue Apr 23 2019 update pin to bazel toolchains repo (#2038)
528f6faf83f85c23da367d61f784893d1b3bd72b Sat Apr 20 2019 GoCompilePkg: unified action for building a Go package (#2027)
...
```

### `$ bazel target`

Pretty-print available targets in the current workspace.
Expand Down
10 changes: 5 additions & 5 deletions WORKSPACE
Original file line number Diff line number Diff line change
Expand Up @@ -54,11 +54,11 @@ go_repository(
importpath = "github.com/davecgh/go-spew",
)

go_repository(
name = "com_golang_google_genproto",
commit = "3273178ea4684acc4f512f7bef7349dd72db88f6",
importpath = "google.golang.org/genproto",
)
# go_repository(
# name = "com_golang_google_genproto",
# commit = "3273178ea4684acc4f512f7bef7349dd72db88f6",
# importpath = "google.golang.org/genproto",
# )

go_repository(
name = "com_github_gregjones_httpcache",
Expand Down
4 changes: 2 additions & 2 deletions app.go
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ func NewApp() *App {
if err != nil {
log.Fatalf("Invalid bazel version %s, aborting: %v", version, err)
}
err, exitCode := bazelutil.New().Invoke(args)
err, exitCode := bazelutil.New().Invoke(args, "")
if exitCode != 0 {
log.Printf("bazel exited with exitCode %d: %v", exitCode, err)
os.Exit(exitCode)
Expand All @@ -85,7 +85,7 @@ func NewApp() *App {
} else {
log.Println("BAZEL_VERSION not set, falling back to bazel on your PATH")
args = append(args, c.Args().Tail()...)
err, exitCode := bazelutil.New().Invoke(args)
err, exitCode := bazelutil.New().Invoke(args, "")
if exitCode != 0 {
log.Printf("bazel exited with exitCode %d: %v", exitCode, err)
os.Exit(exitCode)
Expand Down
26 changes: 24 additions & 2 deletions bazelutil/bazelutil.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package bazelutil

import (
"fmt"
"io"
"io/ioutil"
"log"
"os"
Expand Down Expand Up @@ -49,12 +50,13 @@ func SetVersion(version string) error {
}

// Make Generic invocation to bazel
func (b *Bazel) Invoke(args []string) (error, int) {
func (b *Bazel) Invoke(args []string, dir string) (error, int) {

//fmt.Printf("\n%s %v\n", b.Name, args)
cmd := exec.Command(b.Name, args...)
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
cmd.Dir = ""
cmd.Dir = dir

err := cmd.Run()

Expand Down Expand Up @@ -171,3 +173,23 @@ func FirstTargetComplete(events []*bes.BuildEvent) *bes.TargetComplete {
}
return nil
}

// https://gist.github.com/elazarl/5507969
func CopyFile(src, dst string) error {
s, err := os.Open(src)
if err != nil {
return err
}
// no need to check errors on read only file, we already got everything
// we need from the filesystem, so nothing can go wrong now.
defer s.Close()
d, err := os.Create(dst)
if err != nil {
return err
}
if _, err := io.Copy(d, s); err != nil {
d.Close()
return err
}
return d.Close()
}
1 change: 1 addition & 0 deletions command/install/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ go_library(
importpath = "github.com/bzl-io/bzl/command/install",
visibility = ["//visibility:public"],
deps = [
"//bazelutil:go_default_library",
"//gh:go_default_library",
"@com_github_dustin_go_humanize//:go_default_library",
"@com_github_google_go_github//github:go_default_library",
Expand Down
188 changes: 163 additions & 25 deletions command/install/install.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import (
"strings"
"text/tabwriter"

"github.com/bzl-io/bzl/bazelutil"
"github.com/bzl-io/bzl/gh"
"github.com/google/go-github/github"
"github.com/mitchellh/go-homedir"
Expand All @@ -31,16 +32,56 @@ var Command = &cli.Command{
Name: "install",
Usage: "Install a bazel release (or list release assets)",
Flags: []cli.Flag{
cli.BoolFlag{Name: "list"},
cli.BoolFlag{Name: "force"},
cli.BoolFlag{
Name: "assets",
Usage: "List assets for a particular release (example: bazel install 0.24.1 --assets)",
},
cli.BoolFlag{
Name: "force",
Usage: "Force install",
},
cli.BoolFlag{Name: "without_jdk"},
cli.StringFlag{
Name: "bazel_source_dir",
Usage: "Location of the bazelbuild/bazel git repository (if building from source)",
Value: "$HOME/.cache/bzl/github.com/bazelbuild/bazel",
},
},
Action: func(c *cli.Context) error {
if err := execute(c); err != nil {
return cli.NewExitError(fmt.Sprintf("Install aborted: %v", err), 1)
}
return nil
},
Action: execute,
}

func execute(c *cli.Context) error {
version := c.Args().First()

//
// Check if already installed
//
if version != "" && !c.Bool("assets") {
homeDir, err := homedir.Dir()
if err != nil {
return fmt.Errorf("Failed to get home directory: %v", err)
}
releaseDir := path.Join(homeDir, ".cache", "bzl", "release", version)
if FileExists(releaseDir) && !c.Bool("force") && version != "snapshot" {
return fmt.Errorf("%v is already installed (use --force to re-install it)", version)
}
}

//
// if the version looks like a sha1 value, build from source instead.
//
if len(version) == 40 || version == "snapshot" {
return installFromSource(c, version)
}

//
// List available releases
//
listOptions := &github.ListOptions{}
client := gh.Client()
releases, _, err := client.Repositories.ListReleases(context.Background(), "bazelbuild", "bazel", listOptions)
Expand Down Expand Up @@ -86,7 +127,7 @@ func listReleases(c *cli.Context, releases []*github.RepositoryRelease) error {

func processRelease(c *cli.Context, release *github.RepositoryRelease) error {
command := "install"
if c.Bool("list") {
if c.Bool("assets") {
command = "assets"
}

Expand Down Expand Up @@ -120,8 +161,6 @@ func installRelease(c *cli.Context, release *github.RepositoryRelease) error {
goarch = "x86_64" // is this right?
}

//fmt.Printf("INSTALL %s %s %s: %s\n", goos, goarch, version, *release.Assets[0].BrowserDownloadURL)
// https://github.com/bazelbuild/bazel/releases/download/0.7.0/bazel-0.7.0-installer-darwin-x86_64.sh.sha256
baseDir := "/tmp"
homeDir, err := homedir.Dir()
if err == nil {
Expand Down Expand Up @@ -184,28 +223,23 @@ func installRelease(c *cli.Context, release *github.RepositoryRelease) error {
}

if actual != expected[0] {
if c.Bool("force") {
log.Printf(
"%s: got sha256 '%s' but expected '%s' (from %s). Proceeding with install due to --force\n",
exe,
actual,
expected,
sha)
} else {
return cli.NewExitError(
fmt.Sprintf(
"%s: got sha256 '%s' but expected '%s' (from %s)\n",
exe,
actual,
expected,
sha),
2)
}
return fmt.Errorf(
"%s: got sha256 '%s' but expected '%s' (from %s)\n",
exe,
actual,
expected,
sha,
)
}

log.Printf("Sha256 match %s: %s, proceeding with install\n", exe, sha)
log.Printf("Sha256 match %s: %s, proceeding with install...\n", exe, sha)

if err := install(c, version, exe); err != nil {
return err
}

log.Printf("Install was successful ('export BAZEL_VERSION=%s' to use it)", version)

install(c, version, exe)
return nil
}

Expand Down Expand Up @@ -355,3 +389,107 @@ func install(c *cli.Context, version, filename string) error {
cmd.Stderr = os.Stderr
return cmd.Run()
}

func installFromSource(c *cli.Context, version string) error {

// make sure bazel is checked out at the approprite location
bazelDir := os.ExpandEnv(c.String("bazel_source_dir"))

// If the directory does not exist, create it and clone bazel.
if !FileExists(bazelDir) {
parentDir := filepath.Dir(bazelDir)
if err := os.MkdirAll(parentDir, os.ModePerm); err != nil {
return fmt.Errorf("Failed to prepare bazel source directory: %v", err)
}

// Execute a git clone
cloneArgs := []string{
"clone",
"https://github.com/bazelbuild/bazel.git",
}
cmd := exec.Command("git", cloneArgs...)
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
cmd.Dir = parentDir
cmd.Env = os.Environ()

if err := cmd.Run(); err != nil {
return fmt.Errorf("Failed to clone bazel: %v", err)
}

}

//
// Make sure we have the correct version checked out.
//
if version != "snapshot" {
// Pull most recent stuff
cmd := exec.Command("git", []string{
"fetch",
// version,
}...)
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
cmd.Dir = bazelDir
cmd.Env = os.Environ()

if err := cmd.Run(); err != nil {
return fmt.Errorf("Failed to fetch %q: %v", version, err)
}

// Checkout to the requested commit
cmd = exec.Command("git", []string{
"checkout",
version,
}...)
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
cmd.Dir = bazelDir
cmd.Env = os.Environ()

if err := cmd.Run(); err != nil {
return fmt.Errorf("Failed to checkout %q: %v", version, err)
}
}

//
// And run the build...
//
if err, exitCode := bazelutil.New().Invoke([]string{
"build",
"//src:bazel",
}, bazelDir); err != nil {
return fmt.Errorf("Failed to build bazel: %v (exit %d)", err, exitCode)
}

//
// Make the release dir
//
var releaseDir string
homeDir, err := homedir.Dir()
if err != nil {
return fmt.Errorf("Failed to read home dir: %v", err)
}
releaseDir = filepath.Join(homeDir, ".cache", "bzl", "release", version, "bin")
if err := os.MkdirAll(releaseDir, os.ModePerm); err != nil {
return fmt.Errorf("Failed to prepare bazel release directory: %v", err)
}

//
// Copy the binary
//
srcFile := filepath.Join(bazelDir, "bazel-bin", "src", "bazel")
dstFile := filepath.Join(releaseDir, "bazel")
if err := bazelutil.CopyFile(srcFile, dstFile); err != nil {
return fmt.Errorf("Failed to copy bazel binary to release directory: %v", err)
}

//
// Set executable permisssions
//
os.Chmod(dstFile, 0755)

log.Printf("Build+Install was successful ('export BAZEL_VERSION=%s' to use it)", version)

return nil
}
Loading

0 comments on commit 4f73bd6

Please sign in to comment.