LEFT | RIGHT |
1 // Copyright 2012 The Go Authors. All rights reserved. | 1 // Copyright 2012 The Go Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style | 2 // Use of this source code is governed by a BSD-style |
3 // license that can be found in the LICENSE file. | 3 // license that can be found in the LICENSE file. |
4 | 4 |
5 // This is a tool for packaging binary releases. | 5 // This is a tool for packaging binary releases. |
6 // It supports FreeBSD, Linux, NetBSD, OS X, and Windows. | 6 // It supports FreeBSD, Linux, NetBSD, OS X, and Windows. |
7 package main | 7 package main |
8 | 8 |
9 import ( | 9 import ( |
10 "archive/tar" | 10 "archive/tar" |
(...skipping 13 matching lines...) Expand all Loading... |
24 "os/exec" | 24 "os/exec" |
25 "path/filepath" | 25 "path/filepath" |
26 "regexp" | 26 "regexp" |
27 "runtime" | 27 "runtime" |
28 "strings" | 28 "strings" |
29 ) | 29 ) |
30 | 30 |
31 var ( | 31 var ( |
32 tag = flag.String("tag", "release", "mercurial tag to check out") | 32 tag = flag.String("tag", "release", "mercurial tag to check out") |
33 repo = flag.String("repo", "https://code.google.com/p/go", "repo URL
") | 33 repo = flag.String("repo", "https://code.google.com/p/go", "repo URL
") |
| 34 tourPath = flag.String("tour", "code.google.com/p/go-tour", "Go tour rep
o import path") |
34 verbose = flag.Bool("v", false, "verbose output") | 35 verbose = flag.Bool("v", false, "verbose output") |
35 upload = flag.Bool("upload", true, "upload resulting files to Google C
ode") | 36 upload = flag.Bool("upload", true, "upload resulting files to Google C
ode") |
36 wxsFile = flag.String("wxs", "", "path to custom installer.wxs") | 37 wxsFile = flag.String("wxs", "", "path to custom installer.wxs") |
37 addLabel = flag.String("label", "", "additional label to apply to file w
hen uploading") | 38 addLabel = flag.String("label", "", "additional label to apply to file w
hen uploading") |
38 tourRepo = flag.String("tour", "http://code.google.com/p/go-tour", "Go t
our repo URL") | |
39 | 39 |
40 username, password string // for Google Code upload | 40 username, password string // for Google Code upload |
41 ) | 41 ) |
42 | 42 |
43 const ( | 43 const ( |
44 uploadURL = "https://go.googlecode.com/files" | 44 uploadURL = "https://go.googlecode.com/files" |
45 ) | 45 ) |
46 | 46 |
47 var preBuildCleanFiles = []string{ | 47 var preBuildCleanFiles = []string{ |
48 "lib/codereview", | 48 "lib/codereview", |
49 "misc/dashboard/godashboard", | 49 "misc/dashboard/godashboard", |
50 "src/cmd/cov", | 50 "src/cmd/cov", |
51 "src/cmd/prof", | 51 "src/cmd/prof", |
52 "src/pkg/exp", | 52 "src/pkg/exp", |
53 "src/pkg/old", | 53 "src/pkg/old", |
54 } | 54 } |
55 | 55 |
56 var cleanFiles = []string{ | 56 var cleanFiles = []string{ |
57 ".hg", | 57 ".hg", |
58 ".hgtags", | 58 ".hgtags", |
59 ".hgignore", | 59 ".hgignore", |
60 "VERSION.cache", | 60 "VERSION.cache", |
61 } | 61 } |
62 | 62 |
63 var sourceCleanFiles = []string{ | 63 var sourceCleanFiles = []string{ |
64 "bin", | 64 "bin", |
65 "pkg", | 65 "pkg", |
| 66 } |
| 67 |
| 68 var tourPackages = []string{ |
| 69 "pic", |
| 70 "tree", |
| 71 "wc", |
| 72 } |
| 73 |
| 74 var tourContent = []string{ |
| 75 "prog", |
| 76 "solutions", |
| 77 "static", |
| 78 "template", |
| 79 "tour.article", |
66 } | 80 } |
67 | 81 |
68 var fileRe = regexp.MustCompile(`^go\.([a-z0-9-.]+)\.(src|([a-z0-9]+)-([a-z0-9]+
))\.`) | 82 var fileRe = regexp.MustCompile(`^go\.([a-z0-9-.]+)\.(src|([a-z0-9]+)-([a-z0-9]+
))\.`) |
69 | 83 |
70 func main() { | 84 func main() { |
71 flag.Usage = func() { | 85 flag.Usage = func() { |
72 fmt.Fprintf(os.Stderr, "usage: %s [flags] targets...\n", os.Args
[0]) | 86 fmt.Fprintf(os.Stderr, "usage: %s [flags] targets...\n", os.Args
[0]) |
73 flag.PrintDefaults() | 87 flag.PrintDefaults() |
74 os.Exit(2) | 88 os.Exit(2) |
75 } | 89 } |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
121 log.Printf("%s: %v", targ, err) | 135 log.Printf("%s: %v", targ, err) |
122 } | 136 } |
123 } | 137 } |
124 } | 138 } |
125 | 139 |
126 type Build struct { | 140 type Build struct { |
127 Source bool // if true, OS and Arch must be empty | 141 Source bool // if true, OS and Arch must be empty |
128 OS string | 142 OS string |
129 Arch string | 143 Arch string |
130 root string | 144 root string |
| 145 gopath string |
131 } | 146 } |
132 | 147 |
133 func (b *Build) Do() error { | 148 func (b *Build) Do() error { |
134 work, err := ioutil.TempDir("", "bindist") | 149 work, err := ioutil.TempDir("", "bindist") |
135 if err != nil { | 150 if err != nil { |
136 return err | 151 return err |
137 } | 152 } |
138 defer os.RemoveAll(work) | 153 defer os.RemoveAll(work) |
139 b.root = filepath.Join(work, "go") | 154 b.root = filepath.Join(work, "go") |
| 155 b.gopath = work |
140 | 156 |
141 // Clone Go distribution and update to tag. | 157 // Clone Go distribution and update to tag. |
142 _, err = b.run(work, "hg", "clone", "-q", *repo, b.root) | 158 _, err = b.run(work, "hg", "clone", "-q", *repo, b.root) |
143 if err != nil { | 159 if err != nil { |
144 return err | 160 return err |
145 } | 161 } |
146 _, err = b.run(b.root, "hg", "update", *tag) | 162 _, err = b.run(b.root, "hg", "update", *tag) |
147 if err != nil { | 163 if err != nil { |
148 return err | 164 return err |
149 } | 165 } |
(...skipping 193 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
343 err = b.Upload(version, targ) | 359 err = b.Upload(version, targ) |
344 if err != nil { | 360 if err != nil { |
345 return err | 361 return err |
346 } | 362 } |
347 } | 363 } |
348 } | 364 } |
349 return err | 365 return err |
350 } | 366 } |
351 | 367 |
352 func (b *Build) tour() error { | 368 func (b *Build) tour() error { |
353 » tmp, err := ioutil.TempDir("", "gotour") | 369 » // go get the gotour package. |
354 » if err != nil { | 370 » _, err := b.run(b.gopath, filepath.Join(b.root, "bin", "go"), "get", *to
urPath+"/gotour") |
355 » » return err | 371 » if err != nil { |
356 » } | 372 » » return err |
357 » defer os.RemoveAll(tmp) | 373 » } |
358 » var ( | 374 |
359 » » tourRoot = filepath.Join(tmp, "go-tour") | 375 » // Copy all the tour content to $GOROOT/misc/tour. |
360 » » tourPkg = filepath.Join(tourRoot, "gotour") | 376 » importPath := filepath.FromSlash(*tourPath) |
361 » » toolPath = filepath.Join(b.root, "pkg", "tool", b.OS+"_"+b.Arch) | 377 » tourSrc := filepath.Join(b.gopath, "src", importPath) |
362 » » pkgDir = filepath.Join(b.root, "src", "pkg") | 378 » contentDir := filepath.Join(b.root, "misc", "tour") |
363 » » miscDir = filepath.Join(b.root, "misc", "tour") | 379 » if err = cpAllDir(contentDir, tourSrc, tourContent...); err != nil { |
| 380 » » return err |
| 381 » } |
| 382 |
| 383 » // Copy the tour source code so it's accessible with $GOPATH pointing to
$GOROOT/misc/tour. |
| 384 » if err = cpAllDir(filepath.Join(contentDir, "src", importPath), tourSrc,
tourPackages...); err != nil { |
| 385 » » return err |
| 386 » } |
| 387 |
| 388 » // Copy gotour binary to tool directory as "tour"; invoked as "go tool t
our". |
| 389 » return cp( |
| 390 » » filepath.Join(b.root, "pkg", "tool", b.OS+"_"+b.Arch, "tour"), |
| 391 » » filepath.Join(b.gopath, "bin", "gotour"), |
364 ) | 392 ) |
365 if err := os.MkdirAll(miscDir, 0755); err != nil { | |
366 return err | |
367 } | |
368 | |
369 cmds := [][]string{ | |
370 {tmp, "hg", "clone", "-q", tourRepoURL, tourRoot}, | |
371 {tourRoot, "hg", "update"}, | |
372 {tourPkg, "go", "build", "-o", "tour"}, | |
373 {tourPkg, "mv", "tour", toolPath}, | |
374 {tourRoot, "mv", "tree", "pic", "wc", pkgDir}, | |
375 {tourRoot, "mv", "static", miscDir}, | |
376 } | |
377 | |
378 for _, cmd := range cmds { | |
379 if _, err := b.run(cmd[0], cmd[1], cmd[2:]...); err != nil { | |
380 return err | |
381 } | |
382 } | |
383 return nil | |
384 } | 393 } |
385 | 394 |
386 func (b *Build) run(dir, name string, args ...string) ([]byte, error) { | 395 func (b *Build) run(dir, name string, args ...string) ([]byte, error) { |
387 buf := new(bytes.Buffer) | 396 buf := new(bytes.Buffer) |
388 absName, err := lookPath(name) | 397 absName, err := lookPath(name) |
389 if err != nil { | 398 if err != nil { |
390 return nil, err | 399 return nil, err |
391 } | 400 } |
392 cmd := exec.Command(absName, args...) | 401 cmd := exec.Command(absName, args...) |
393 var output io.Writer = buf | 402 var output io.Writer = buf |
(...skipping 13 matching lines...) Expand all Loading... |
407 } | 416 } |
408 | 417 |
409 var cleanEnv = []string{ | 418 var cleanEnv = []string{ |
410 "GOARCH", | 419 "GOARCH", |
411 "GOBIN", | 420 "GOBIN", |
412 "GOHOSTARCH", | 421 "GOHOSTARCH", |
413 "GOHOSTOS", | 422 "GOHOSTOS", |
414 "GOOS", | 423 "GOOS", |
415 "GOROOT", | 424 "GOROOT", |
416 "GOROOT_FINAL", | 425 "GOROOT_FINAL", |
| 426 "GOPATH", |
417 } | 427 } |
418 | 428 |
419 func (b *Build) env() []string { | 429 func (b *Build) env() []string { |
420 env := os.Environ() | 430 env := os.Environ() |
421 for i := 0; i < len(env); i++ { | 431 for i := 0; i < len(env); i++ { |
422 for _, c := range cleanEnv { | 432 for _, c := range cleanEnv { |
423 if strings.HasPrefix(env[i], c+"=") { | 433 if strings.HasPrefix(env[i], c+"=") { |
424 env = append(env[:i], env[i+1:]...) | 434 env = append(env[:i], env[i+1:]...) |
425 } | 435 } |
426 } | 436 } |
427 } | 437 } |
428 final := "/usr/local/go" | 438 final := "/usr/local/go" |
429 if b.OS == "windows" { | 439 if b.OS == "windows" { |
430 final = `c:\go` | 440 final = `c:\go` |
431 } | 441 } |
432 env = append(env, | 442 env = append(env, |
433 "GOARCH="+b.Arch, | 443 "GOARCH="+b.Arch, |
434 "GOHOSTARCH="+b.Arch, | 444 "GOHOSTARCH="+b.Arch, |
435 "GOHOSTOS="+b.OS, | 445 "GOHOSTOS="+b.OS, |
436 "GOOS="+b.OS, | 446 "GOOS="+b.OS, |
437 "GOROOT="+b.root, | 447 "GOROOT="+b.root, |
438 "GOROOT_FINAL="+final, | 448 "GOROOT_FINAL="+final, |
| 449 "GOPATH="+b.gopath, |
439 ) | 450 ) |
440 return env | 451 return env |
441 } | 452 } |
442 | 453 |
443 func (b *Build) Upload(version string, filename string) error { | 454 func (b *Build) Upload(version string, filename string) error { |
444 // Prepare upload metadata. | 455 // Prepare upload metadata. |
445 var labels []string | 456 var labels []string |
446 os_, arch := b.OS, b.Arch | 457 os_, arch := b.OS, b.Arch |
447 switch b.Arch { | 458 switch b.Arch { |
448 case "386": | 459 case "386": |
(...skipping 153 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
602 defer sf.Close() | 613 defer sf.Close() |
603 df, err := os.Create(dst) | 614 df, err := os.Create(dst) |
604 if err != nil { | 615 if err != nil { |
605 return err | 616 return err |
606 } | 617 } |
607 defer df.Close() | 618 defer df.Close() |
608 _, err = io.Copy(df, sf) | 619 _, err = io.Copy(df, sf) |
609 return err | 620 return err |
610 } | 621 } |
611 | 622 |
| 623 func cpDir(dst, src string) error { |
| 624 walk := func(srcPath string, info os.FileInfo, err error) error { |
| 625 if err != nil { |
| 626 return err |
| 627 } |
| 628 dstPath := filepath.Join(dst, srcPath[len(src):]) |
| 629 if info.IsDir() { |
| 630 return os.MkdirAll(dstPath, 0755) |
| 631 } |
| 632 return cp(dstPath, srcPath) |
| 633 } |
| 634 return filepath.Walk(src, walk) |
| 635 } |
| 636 |
| 637 func cpAllDir(dst, basePath string, dirs ...string) error { |
| 638 for _, dir := range dirs { |
| 639 if err := cpDir(filepath.Join(dst, dir), filepath.Join(basePath,
dir)); err != nil { |
| 640 return err |
| 641 } |
| 642 } |
| 643 return nil |
| 644 } |
| 645 |
612 func makeTar(targ, workdir string) error { | 646 func makeTar(targ, workdir string) error { |
613 f, err := os.Create(targ) | 647 f, err := os.Create(targ) |
614 if err != nil { | 648 if err != nil { |
615 return err | 649 return err |
616 } | 650 } |
617 zout := gzip.NewWriter(f) | 651 zout := gzip.NewWriter(f) |
618 tw := tar.NewWriter(zout) | 652 tw := tar.NewWriter(zout) |
619 | 653 |
620 err = filepath.Walk(workdir, func(path string, fi os.FileInfo, err error
) error { | 654 err = filepath.Walk(workdir, func(path string, fi os.FileInfo, err error
) error { |
621 if !strings.HasPrefix(path, workdir) { | 655 if !strings.HasPrefix(path, workdir) { |
(...skipping 178 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
800 absPath = filepath.Join(dir, prog+"."+ext) | 834 absPath = filepath.Join(dir, prog+"."+ext) |
801 if _, err1 := os.Stat(absPath); err1 == nil { | 835 if _, err1 := os.Stat(absPath); err1 == nil { |
802 err = nil | 836 err = nil |
803 os.Setenv("PATH", os.Getenv("PATH")+";"+dir) | 837 os.Setenv("PATH", os.Getenv("PATH")+";"+dir) |
804 return | 838 return |
805 } | 839 } |
806 } | 840 } |
807 } | 841 } |
808 return | 842 return |
809 } | 843 } |
LEFT | RIGHT |