summaryrefslogtreecommitdiff
path: root/misc/dist/bindist.go
diff options
context:
space:
mode:
authorMichael Stapelberg <stapelberg@debian.org>2013-03-04 21:27:36 +0100
committerMichael Stapelberg <michael@stapelberg.de>2013-03-04 21:27:36 +0100
commit04b08da9af0c450d645ab7389d1467308cfc2db8 (patch)
treedb247935fa4f2f94408edc3acd5d0d4f997aa0d8 /misc/dist/bindist.go
parent917c5fb8ec48e22459d77e3849e6d388f93d3260 (diff)
downloadgolang-upstream/1.1_hg20130304.tar.gz
Imported Upstream version 1.1~hg20130304upstream/1.1_hg20130304
Diffstat (limited to 'misc/dist/bindist.go')
-rw-r--r--misc/dist/bindist.go282
1 files changed, 168 insertions, 114 deletions
diff --git a/misc/dist/bindist.go b/misc/dist/bindist.go
index 16193bdc1..29454c73c 100644
--- a/misc/dist/bindist.go
+++ b/misc/dist/bindist.go
@@ -3,7 +3,7 @@
// license that can be found in the LICENSE file.
// This is a tool for packaging binary releases.
-// It supports FreeBSD, Linux, OS X, and Windows.
+// It supports FreeBSD, Linux, NetBSD, OS X, and Windows.
package main
import (
@@ -13,7 +13,6 @@ import (
"bytes"
"compress/gzip"
"encoding/base64"
- "errors"
"flag"
"fmt"
"io"
@@ -30,8 +29,9 @@ import (
)
var (
- tag = flag.String("tag", "weekly", "mercurial tag to check out")
+ tag = flag.String("tag", "release", "mercurial tag to check out")
repo = flag.String("repo", "https://code.google.com/p/go", "repo URL")
+ tourPath = flag.String("tour", "code.google.com/p/go-tour", "Go tour repo import path")
verbose = flag.Bool("v", false, "verbose output")
upload = flag.Bool("upload", true, "upload resulting files to Google Code")
wxsFile = flag.String("wxs", "", "path to custom installer.wxs")
@@ -41,8 +41,7 @@ var (
)
const (
- packageMaker = "/Applications/Utilities/PackageMaker.app/Contents/MacOS/PackageMaker"
- uploadURL = "https://go.googlecode.com/files"
+ uploadURL = "https://go.googlecode.com/files"
)
var preBuildCleanFiles = []string{
@@ -66,6 +65,20 @@ var sourceCleanFiles = []string{
"pkg",
}
+var tourPackages = []string{
+ "pic",
+ "tree",
+ "wc",
+}
+
+var tourContent = []string{
+ "prog",
+ "solutions",
+ "static",
+ "template",
+ "tour.article",
+}
+
var fileRe = regexp.MustCompile(`^go\.([a-z0-9-.]+)\.(src|([a-z0-9]+)-([a-z0-9]+))\.`)
func main() {
@@ -129,6 +142,7 @@ type Build struct {
OS string
Arch string
root string
+ gopath string
}
func (b *Build) Do() error {
@@ -138,6 +152,7 @@ func (b *Build) Do() error {
}
defer os.RemoveAll(work)
b.root = filepath.Join(work, "go")
+ b.gopath = work
// Clone Go distribution and update to tag.
_, err = b.run(work, "hg", "clone", "-q", *repo, b.root)
@@ -173,6 +188,10 @@ func (b *Build) Do() error {
return err
}
+ if err := b.tour(); err != nil {
+ return err
+ }
+
// Get version strings.
var (
version string // "weekly.2012-03-04"
@@ -211,19 +230,31 @@ func (b *Build) Do() error {
}
// Create packages.
- base := fmt.Sprintf("go.%s.%s-%s", version, b.OS, b.Arch)
+ base := fmt.Sprintf("%s.%s-%s", version, b.OS, b.Arch)
+ if !strings.HasPrefix(base, "go") {
+ base = "go." + base
+ }
var targs []string
switch b.OS {
- case "linux", "freebsd", "":
+ case "linux", "freebsd", "netbsd", "":
// build tarball
targ := base
if b.Source {
- targ = fmt.Sprintf("go.%s.src", version)
+ targ = fmt.Sprintf("%s.src", version)
+ if !strings.HasPrefix(targ, "go") {
+ targ = "go." + targ
+ }
}
targ += ".tar.gz"
err = makeTar(targ, work)
targs = append(targs, targ)
case "darwin":
+ // build tarball
+ targ := base + ".tar.gz"
+ err = makeTar(targ, work)
+ targs = append(targs, targ)
+
+ // build pkg
// arrange work so it's laid out as the dest filesystem
etc := filepath.Join(b.root, "misc/dist/darwin/etc")
_, err = b.run(work, "cp", "-r", etc, ".")
@@ -231,7 +262,7 @@ func (b *Build) Do() error {
return err
}
localDir := filepath.Join(work, "usr/local")
- err = os.MkdirAll(localDir, 0744)
+ err = os.MkdirAll(localDir, 0755)
if err != nil {
return err
}
@@ -240,23 +271,30 @@ func (b *Build) Do() error {
return err
}
// build package
- pm := packageMaker
- if !exists(pm) {
- pm = "/Developer" + pm
- if !exists(pm) {
- return errors.New("couldn't find PackageMaker")
- }
+ pkgdest, err := ioutil.TempDir("", "pkgdest")
+ if err != nil {
+ return err
}
- targ := base + ".pkg"
- scripts := filepath.Join(work, "usr/local/go/misc/dist/darwin/scripts")
- _, err = b.run("", pm, "-v",
- "-r", work,
- "-o", targ,
- "--scripts", scripts,
- "--id", "com.googlecode.go",
- "--title", "Go",
+ defer os.RemoveAll(pkgdest)
+ dist := filepath.Join(runtime.GOROOT(), "misc/dist")
+ _, err = b.run("", "pkgbuild",
+ "--identifier", "com.googlecode.go",
"--version", "1.0",
- "--target", "10.6")
+ "--scripts", filepath.Join(dist, "darwin/scripts"),
+ "--root", work,
+ filepath.Join(pkgdest, "com.googlecode.go.pkg"))
+ if err != nil {
+ return err
+ }
+ targ = base + ".pkg"
+ _, err = b.run("", "productbuild",
+ "--distribution", filepath.Join(dist, "darwin/Distribution"),
+ "--resources", filepath.Join(dist, "darwin/Resources"),
+ "--package-path", pkgdest,
+ targ)
+ if err != nil {
+ return err
+ }
targs = append(targs, targ)
case "windows":
// Create ZIP file.
@@ -327,6 +365,33 @@ func (b *Build) Do() error {
return err
}
+func (b *Build) tour() error {
+ // go get the gotour package.
+ _, err := b.run(b.gopath, filepath.Join(b.root, "bin", "go"), "get", *tourPath+"/gotour")
+ if err != nil {
+ return err
+ }
+
+ // Copy all the tour content to $GOROOT/misc/tour.
+ importPath := filepath.FromSlash(*tourPath)
+ tourSrc := filepath.Join(b.gopath, "src", importPath)
+ contentDir := filepath.Join(b.root, "misc", "tour")
+ if err = cpAllDir(contentDir, tourSrc, tourContent...); err != nil {
+ return err
+ }
+
+ // Copy the tour source code so it's accessible with $GOPATH pointing to $GOROOT/misc/tour.
+ if err = cpAllDir(filepath.Join(contentDir, "src", importPath), tourSrc, tourPackages...); err != nil {
+ return err
+ }
+
+ // Copy gotour binary to tool directory as "tour"; invoked as "go tool tour".
+ return cp(
+ filepath.Join(b.root, "pkg", "tool", b.OS+"_"+b.Arch, "tour"),
+ filepath.Join(b.gopath, "bin", "gotour"),
+ )
+}
+
func (b *Build) run(dir, name string, args ...string) ([]byte, error) {
buf := new(bytes.Buffer)
absName, err := lookPath(name)
@@ -358,6 +423,7 @@ var cleanEnv = []string{
"GOOS",
"GOROOT",
"GOROOT_FINAL",
+ "GOPATH",
}
func (b *Build) env() []string {
@@ -380,6 +446,7 @@ func (b *Build) env() []string {
"GOOS="+b.OS,
"GOROOT="+b.root,
"GOROOT_FINAL="+final,
+ "GOPATH="+b.gopath,
)
return env
}
@@ -390,42 +457,51 @@ func (b *Build) Upload(version string, filename string) error {
os_, arch := b.OS, b.Arch
switch b.Arch {
case "386":
- arch = "32-bit"
+ arch = "x86 32-bit"
case "amd64":
- arch = "64-bit"
+ arch = "x86 64-bit"
}
if arch != "" {
labels = append(labels, "Arch-"+b.Arch)
}
+ var opsys, ftype string // labels
switch b.OS {
case "linux":
os_ = "Linux"
- labels = append(labels, "Type-Archive", "OpSys-Linux")
+ opsys = "Linux"
case "freebsd":
os_ = "FreeBSD"
- labels = append(labels, "Type-Archive", "OpSys-FreeBSD")
+ opsys = "FreeBSD"
case "darwin":
os_ = "Mac OS X"
- labels = append(labels, "Type-Installer", "OpSys-OSX")
+ opsys = "OSX"
+ case "netbsd":
+ os_ = "NetBSD"
+ opsys = "NetBSD"
case "windows":
os_ = "Windows"
- labels = append(labels, "OpSys-Windows")
+ opsys = "Windows"
}
summary := fmt.Sprintf("%s %s (%s)", version, os_, arch)
- if b.OS == "windows" {
- switch {
- case strings.HasSuffix(filename, ".msi"):
- labels = append(labels, "Type-Installer")
- summary += " MSI installer"
- case strings.HasSuffix(filename, ".zip"):
- labels = append(labels, "Type-Archive")
- summary += " ZIP archive"
- }
+ switch {
+ case strings.HasSuffix(filename, ".msi"):
+ ftype = "Installer"
+ summary += " MSI installer"
+ case strings.HasSuffix(filename, ".pkg"):
+ ftype = "Installer"
+ summary += " PKG installer"
+ case strings.HasSuffix(filename, ".zip"):
+ ftype = "Archive"
+ summary += " ZIP archive"
+ case strings.HasSuffix(filename, ".tar.gz"):
+ ftype = "Archive"
+ summary += " tarball"
}
if b.Source {
- labels = append(labels, "Type-Source")
+ ftype = "Source"
summary = fmt.Sprintf("%s (source only)", version)
}
+ labels = append(labels, "OpSys-"+opsys, "Type-"+ftype)
if *addLabel != "" {
labels = append(labels, *addLabel)
}
@@ -535,15 +611,45 @@ func cp(dst, src string) error {
return err
}
defer sf.Close()
+ fi, err := sf.Stat()
+ if err != nil {
+ return err
+ }
df, err := os.Create(dst)
if err != nil {
return err
}
defer df.Close()
+ if err := df.Chmod(fi.Mode()); err != nil {
+ return err
+ }
_, err = io.Copy(df, sf)
return err
}
+func cpDir(dst, src string) error {
+ walk := func(srcPath string, info os.FileInfo, err error) error {
+ if err != nil {
+ return err
+ }
+ dstPath := filepath.Join(dst, srcPath[len(src):])
+ if info.IsDir() {
+ return os.MkdirAll(dstPath, 0755)
+ }
+ return cp(dstPath, srcPath)
+ }
+ return filepath.Walk(src, walk)
+}
+
+func cpAllDir(dst, basePath string, dirs ...string) error {
+ for _, dir := range dirs {
+ if err := cpDir(filepath.Join(dst, dir), filepath.Join(basePath, dir)); err != nil {
+ return err
+ }
+ }
+ return nil
+}
+
func makeTar(targ, workdir string) error {
f, err := os.Create(targ)
if err != nil {
@@ -552,7 +658,7 @@ func makeTar(targ, workdir string) error {
zout := gzip.NewWriter(f)
tw := tar.NewWriter(zout)
- filepath.Walk(workdir, filepath.WalkFunc(func(path string, fi os.FileInfo, err error) error {
+ err = filepath.Walk(workdir, func(path string, fi os.FileInfo, err error) error {
if !strings.HasPrefix(path, workdir) {
log.Panicf("walked filename %q doesn't begin with workdir %q", path, workdir)
}
@@ -570,10 +676,8 @@ func makeTar(targ, workdir string) error {
if *verbose {
log.Printf("adding to tar: %s", name)
}
- if fi.IsDir() {
- return nil
- }
- hdr, err := tarFileInfoHeader(fi, path)
+ target, _ := os.Readlink(path)
+ hdr, err := tar.FileInfoHeader(fi, target)
if err != nil {
return err
}
@@ -594,6 +698,9 @@ func makeTar(targ, workdir string) error {
if err != nil {
return fmt.Errorf("Error writing file %q: %v", name, err)
}
+ if fi.IsDir() {
+ return nil
+ }
r, err := os.Open(path)
if err != nil {
return err
@@ -601,8 +708,10 @@ func makeTar(targ, workdir string) error {
defer r.Close()
_, err = io.Copy(tw, r)
return err
- }))
-
+ })
+ if err != nil {
+ return err
+ }
if err := tw.Close(); err != nil {
return err
}
@@ -619,10 +728,7 @@ func makeZip(targ, workdir string) error {
}
zw := zip.NewWriter(f)
- filepath.Walk(workdir, filepath.WalkFunc(func(path string, fi os.FileInfo, err error) error {
- if fi.IsDir() {
- return nil
- }
+ err = filepath.Walk(workdir, func(path string, fi os.FileInfo, err error) error {
if !strings.HasPrefix(path, workdir) {
log.Panicf("walked filename %q doesn't begin with workdir %q", path, workdir)
}
@@ -649,10 +755,17 @@ func makeZip(targ, workdir string) error {
}
fh.Name = name
fh.Method = zip.Deflate
+ if fi.IsDir() {
+ fh.Name += "/" // append trailing slash
+ fh.Method = zip.Store // no need to deflate 0 byte files
+ }
w, err := zw.CreateHeader(fh)
if err != nil {
return err
}
+ if fi.IsDir() {
+ return nil
+ }
r, err := os.Open(path)
if err != nil {
return err
@@ -660,8 +773,10 @@ func makeZip(targ, workdir string) error {
defer r.Close()
_, err = io.Copy(w, r)
return err
- }))
-
+ })
+ if err != nil {
+ return err
+ }
if err := zw.Close(); err != nil {
return err
}
@@ -733,64 +848,3 @@ func lookPath(prog string) (absPath string, err error) {
}
return
}
-
-// sysStat, if non-nil, populates h from system-dependent fields of fi.
-var sysStat func(fi os.FileInfo, h *tar.Header) error
-
-// Mode constants from the tar spec.
-const (
- c_ISDIR = 040000
- c_ISFIFO = 010000
- c_ISREG = 0100000
- c_ISLNK = 0120000
- c_ISBLK = 060000
- c_ISCHR = 020000
- c_ISSOCK = 0140000
-)
-
-// tarFileInfoHeader creates a partially-populated Header from an os.FileInfo.
-// The filename parameter is used only in the case of symlinks, to call os.Readlink.
-// If fi is a symlink but filename is empty, an error is returned.
-func tarFileInfoHeader(fi os.FileInfo, filename string) (*tar.Header, error) {
- h := &tar.Header{
- Name: fi.Name(),
- ModTime: fi.ModTime(),
- Mode: int64(fi.Mode().Perm()), // or'd with c_IS* constants later
- }
- switch {
- case fi.Mode()&os.ModeType == 0:
- h.Mode |= c_ISREG
- h.Typeflag = tar.TypeReg
- h.Size = fi.Size()
- case fi.IsDir():
- h.Typeflag = tar.TypeDir
- h.Mode |= c_ISDIR
- case fi.Mode()&os.ModeSymlink != 0:
- h.Typeflag = tar.TypeSymlink
- h.Mode |= c_ISLNK
- if filename == "" {
- return h, fmt.Errorf("archive/tar: unable to populate Header.Linkname of symlinks")
- }
- targ, err := os.Readlink(filename)
- if err != nil {
- return h, err
- }
- h.Linkname = targ
- case fi.Mode()&os.ModeDevice != 0:
- if fi.Mode()&os.ModeCharDevice != 0 {
- h.Mode |= c_ISCHR
- h.Typeflag = tar.TypeChar
- } else {
- h.Mode |= c_ISBLK
- h.Typeflag = tar.TypeBlock
- }
- case fi.Mode()&os.ModeSocket != 0:
- h.Mode |= c_ISSOCK
- default:
- return nil, fmt.Errorf("archive/tar: unknown file mode %v", fi.Mode())
- }
- if sysStat != nil {
- return h, sysStat(fi, h)
- }
- return h, nil
-}