1//+build mage 2 3// This is the build script for Mage. The install target is all you really need. 4// The release target is for generating official releases and is really only 5// useful to project admins. 6package main 7 8import ( 9 "errors" 10 "fmt" 11 "os" 12 "path/filepath" 13 "regexp" 14 "runtime" 15 "strings" 16 "time" 17 18 "github.com/magefile/mage/mg" 19 "github.com/magefile/mage/sh" 20) 21 22var Aliases = map[string]interface{}{ 23 "Speak": Say, 24} 25 26// Say says something. 27func Say(msg string, i int, b bool, d time.Duration) error { 28 _, err := fmt.Printf("%v(%T) %v(%T) %v(%T) %v(%T)\n", msg, msg, i, i, b, b, d, d) 29 return err 30} 31 32// Runs "go install" for mage. This generates the version info the binary. 33func Install() error { 34 name := "mage" 35 if runtime.GOOS == "windows" { 36 name += ".exe" 37 } 38 39 gocmd := mg.GoCmd() 40 // use GOBIN if set in the environment, otherwise fall back to first path 41 // in GOPATH environment string 42 bin, err := sh.Output(gocmd, "env", "GOBIN") 43 if err != nil { 44 return fmt.Errorf("can't determine GOBIN: %v", err) 45 } 46 if bin == "" { 47 gopath, err := sh.Output(gocmd, "env", "GOPATH") 48 if err != nil { 49 return fmt.Errorf("can't determine GOPATH: %v", err) 50 } 51 paths := strings.Split(gopath, string([]rune{os.PathListSeparator})) 52 bin = filepath.Join(paths[0], "bin") 53 } 54 // specifically don't mkdirall, if you have an invalid gopath in the first 55 // place, that's not on us to fix. 56 if err := os.Mkdir(bin, 0700); err != nil && !os.IsExist(err) { 57 return fmt.Errorf("failed to create %q: %v", bin, err) 58 } 59 path := filepath.Join(bin, name) 60 61 // we use go build here because if someone built with go get, then `go 62 // install` turns into a no-op, and `go install -a` fails on people's 63 // machines that have go installed in a non-writeable directory (such as 64 // normal OS installs in /usr/bin) 65 return sh.RunV(gocmd, "build", "-o", path, "-ldflags="+flags(), "github.com/magefile/mage") 66} 67 68var releaseTag = regexp.MustCompile(`^v1\.[0-9]+\.[0-9]+$`) 69 70// Generates a new release. Expects a version tag in v1.x.x format. 71func Release(tag string) (err error) { 72 if !releaseTag.MatchString(tag) { 73 return errors.New("TAG environment variable must be in semver v1.x.x format, but was " + tag) 74 } 75 76 if err := sh.RunV("git", "tag", "-a", tag, "-m", tag); err != nil { 77 return err 78 } 79 if err := sh.RunV("git", "push", "origin", tag); err != nil { 80 return err 81 } 82 defer func() { 83 if err != nil { 84 sh.RunV("git", "tag", "--delete", "$TAG") 85 sh.RunV("git", "push", "--delete", "origin", "$TAG") 86 } 87 }() 88 return sh.RunV("goreleaser") 89} 90 91// Remove the temporarily generated files from Release. 92func Clean() error { 93 return sh.Rm("dist") 94} 95 96func flags() string { 97 timestamp := time.Now().Format(time.RFC3339) 98 hash := hash() 99 tag := tag() 100 if tag == "" { 101 tag = "dev" 102 } 103 return fmt.Sprintf(`-X "github.com/magefile/mage/mage.timestamp=%s" -X "github.com/magefile/mage/mage.commitHash=%s" -X "github.com/magefile/mage/mage.gitTag=%s"`, timestamp, hash, tag) 104} 105 106// tag returns the git tag for the current branch or "" if none. 107func tag() string { 108 s, _ := sh.Output("git", "describe", "--tags") 109 return s 110} 111 112// hash returns the git hash for the current repo or "" if none. 113func hash() string { 114 hash, _ := sh.Output("git", "rev-parse", "--short", "HEAD") 115 return hash 116} 117