Skip to content

Commit

Permalink
buildsystem for vendoring
Browse files Browse the repository at this point in the history
  • Loading branch information
tychoish committed Sep 7, 2016
1 parent 36f9ec7 commit 9a7a42f
Show file tree
Hide file tree
Showing 3 changed files with 182 additions and 0 deletions.
58 changes: 58 additions & 0 deletions buildscripts/make-vendor.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
/*
The current vendoring solution supports both new and old style
vendoring, via a trick: We commit all vendored code to the "vendor"
directory, and then, if we're on a version/deployment of go that
doesn't support new style vendoring, we symlink to "build/vendor/src"
and add "build/vendor" to the gopath, which the render-gopath program
generates inside of the makefile.
This script sets up the symlink. This is somewhat fragile for go1.5
and go1.6, if you change the value of the GO15VENDOREXPERIMENT
environment variable, in between runs of "make-vendor" and
builds. Similar switching between go1.4 environments and go1.6
will require manually rerunning this script.
*/
package main

import (
"fmt"
"os"
"path/filepath"

"./vendoring"
)

func main() {
if vendoring.NeedsLegacy() {
pwd, err := os.Getwd()
if err != nil {
fmt.Println(err.Error())
os.Exit(1)
}

path := filepath.Join(pwd, vendoring.Path)

if _, err = os.Stat(path); !os.IsNotExist(err) {
fmt.Println("legacy vendor path configured.")
return
}

err = os.MkdirAll(path, 0755)
if err != nil {
fmt.Println(err.Error())
os.Exit(1)

}

err = os.Symlink(filepath.Join(pwd, "vendor"), filepath.Join(pwd, vendoring.Src))
if err != nil {
fmt.Println(err.Error())
os.Exit(1)
}

fmt.Println("created vendor legacy link")
return
}

fmt.Println("can use existing (new-style) vendoring configuration")
}
47 changes: 47 additions & 0 deletions buildscripts/render-gopath.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
// Simple script to print the current GOPATH with additional vendoring
// component for legacy vendoring, as needed. Use in conjunction with
// makefile configuration and the "make-vendor" script.
package main

import (
"fmt"
"os"
"path/filepath"
"strings"

"./vendoring"
)

func main() {
currentGoPath := os.Getenv("GOPATH")
pwd, err := os.Getwd()

// print error and exit if there's an error
if err != nil {
fmt.Println(err)
os.Exit(1)
}

// initialize the gopath components.
goPathParts := []string{currentGoPath}

// if this version of go does not support new-style vendoring,
// then we need to mangle the gopath so that the build can use
// vendored dependencies.
if vendoring.NeedsLegacy() {
goPathParts = append(goPathParts, filepath.Join(pwd, vendoring.Path))

// add any additional paths to nested vendored gopaths.
for _, path := range os.Args[1:] {
absPath, err := filepath.Abs(path)

if err == nil {
goPathParts = append(goPathParts, absPath)
} else {
goPathParts = append(goPathParts, path)
}
}
}

fmt.Printf("GOPATH=%s", strings.Join(goPathParts, ":"))
}
77 changes: 77 additions & 0 deletions buildscripts/vendoring/vendoring.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
// Package vendoring provides a several variables used in vendoring
// buildscripts and function that reports (without any external
// dependencies) if the current environment requires legacy-style
// vendoring, or if its safe to use new-style vendoring.
package vendoring

import (
"fmt"
"os"
"path/filepath"
"runtime"
"strconv"
"strings"
)

var (
// Path to the vendored gopath component.
Path = filepath.Join("build", "vendor")

// Path to the legacy vendor source directory.
Src = filepath.Join(Path, "src")
)

// NeedsLegacy determines what kind vendoring system to use. Returns
// true when using pre-go1.5 vendoring, and false otherwise.
func NeedsLegacy() bool {
var version []int

versionString := strings.TrimPrefix(runtime.Version(), "go")

// gccgo version strings need a bit more processing.
if strings.Contains(versionString, "gccgo") {
versionString = strings.Split(versionString, " ")[0]
}

// parse the version number.
for _, part := range strings.Split(versionString, ".") {
value, err := strconv.Atoi(part)

if err != nil {
// if it's a dev version, and a part of the
// version string isn't a number, then given
// that this script is written in the go1.6
// era, then let's assume that its new-style
// vendoring.

return false
}

version = append(version, value)
}

// determine what kind of vendoring we can use.
if version[0] > 1 || version[1] >= 7 {
// go 2.0 and greater, or go 1.7+, do not require
// legacy verndoring, and can use the top-level vendor
// directory.
return false
} else if version[1] <= 4 {
// everything less than or equal to go1.4 uses legacy
// vendoring (e.g. a modified GOPATH.)
return true
}

// for go1.5 and go1.6, use the environment variable to
// determine the vendoring configuration.
vendorExperiment := os.Getenv("GO15VENDOREXPERIMENT")
if version[1] == 6 {
return vendorExperiment == "0"
} else if version[1] == 5 {
return vendorExperiment != "1"
}

// last resort, shouldn't ever hit this.
panic(fmt.Sprintf("cannot determine vendoring requirements for this version of go. (%s)",
versionString))
}

0 comments on commit 9a7a42f

Please sign in to comment.