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 currently supports FreeBSD, Linux, and OS X. | 6 // It supports FreeBSD, Linux, and OS X. |
7 package main | 7 package main |
8 | 8 |
9 import ( | 9 import ( |
10 "bytes" | 10 "bytes" |
11 "encoding/base64" | 11 "encoding/base64" |
12 "errors" | 12 "errors" |
13 "flag" | 13 "flag" |
14 "fmt" | 14 "fmt" |
15 "io" | 15 "io" |
16 "io/ioutil" | 16 "io/ioutil" |
17 "log" | 17 "log" |
18 "mime/multipart" | 18 "mime/multipart" |
19 "net/http" | 19 "net/http" |
20 "os" | 20 "os" |
21 "os/exec" | 21 "os/exec" |
22 "path/filepath" | 22 "path/filepath" |
23 "strings" | 23 "strings" |
24 ) | 24 ) |
25 | 25 |
26 var ( | 26 var ( |
27 » tag = flag.String("tag", "weekly", "mercurial tag to check out") | 27 » tag = flag.String("tag", "weekly", "mercurial tag to check out") |
28 » repo = flag.String("repo", "https://code.google.com/p/go", "repo URL
") | 28 » repo = flag.String("repo", "https://code.google.com/p/go", "repo URL") |
29 » user = flag.String("user", "builder@golang.org", "Google Code upload
username") | 29 |
30 » password = flag.String("password", "", "Google Code upload password") | 30 » username, password string // for Google Code upload |
31 ) | 31 ) |
32 | 32 |
33 const ( | 33 const ( |
34 packageMaker = "/Applications/Utilities/PackageMaker.app/Contents/MacOS/
PackageMaker" | 34 packageMaker = "/Applications/Utilities/PackageMaker.app/Contents/MacOS/
PackageMaker" |
35 uploadURL = "https://go.googlecode.com/files" | 35 uploadURL = "https://go.googlecode.com/files" |
36 ) | 36 ) |
37 | 37 |
38 var cleanFiles = []string{ | 38 var cleanFiles = []string{ |
39 ".hg", | 39 ".hg", |
40 ".hgtags", | 40 ".hgtags", |
41 ".hgignore", | 41 ".hgignore", |
42 "VERSION.cache", | 42 "VERSION.cache", |
43 } | 43 } |
44 | 44 |
45 func main() { | 45 func main() { |
46 flag.Usage = func() { | 46 flag.Usage = func() { |
47 fmt.Fprintf(os.Stderr, "usage: %s [flags] targets...\n", os.Args
[0]) | 47 fmt.Fprintf(os.Stderr, "usage: %s [flags] targets...\n", os.Args
[0]) |
48 flag.PrintDefaults() | 48 flag.PrintDefaults() |
49 os.Exit(2) | 49 os.Exit(2) |
50 } | 50 } |
51 flag.Parse() | 51 flag.Parse() |
52 | |
53 log.Println((&Build{OS: "darwin", Arch: "amd64"}).upload("weekly.2012-02
-22", "go.weekly.2012-02-22.darwin-amd64.pkg")) | |
54 os.Exit(0) | |
55 | |
56 if flag.NArg() == 0 { | 52 if flag.NArg() == 0 { |
57 flag.Usage() | 53 flag.Usage() |
58 } | 54 } |
| 55 readCredentials() |
59 for _, targ := range flag.Args() { | 56 for _, targ := range flag.Args() { |
60 p := strings.SplitN(targ, "-", 2) | 57 p := strings.SplitN(targ, "-", 2) |
61 if len(p) != 2 { | 58 if len(p) != 2 { |
| 59 log.Println("Ignoring unrecognized target:", targ) |
62 continue | 60 continue |
63 } | 61 } |
64 » » err := (&Build{OS: p[0], Arch: p[1]}).Do() | 62 » » b := Build{OS: p[0], Arch: p[1]} |
65 » » if err != nil { | 63 » » if err := b.Do(); err != nil { |
66 log.Printf("%s: %v", targ, err) | 64 log.Printf("%s: %v", targ, err) |
67 } | 65 } |
68 } | 66 } |
69 } | 67 } |
70 | 68 |
71 type Build struct { | 69 type Build struct { |
72 » OS, Arch string | 70 » OS string |
73 » root string | 71 » Arch string |
| 72 » root string |
74 } | 73 } |
75 | 74 |
76 func (b *Build) Do() error { | 75 func (b *Build) Do() error { |
77 work, err := ioutil.TempDir("", "bindist") | 76 work, err := ioutil.TempDir("", "bindist") |
78 if err != nil { | 77 if err != nil { |
79 return err | 78 return err |
80 } | 79 } |
81 defer os.RemoveAll(work) | 80 defer os.RemoveAll(work) |
82 b.root = filepath.Join(work, "go") | 81 b.root = filepath.Join(work, "go") |
83 | 82 |
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
154 scripts := filepath.Join(work, "usr/local/go/misc/dist/darwin/sc
ripts") | 153 scripts := filepath.Join(work, "usr/local/go/misc/dist/darwin/sc
ripts") |
155 _, err = b.run("", pm, "-v", | 154 _, err = b.run("", pm, "-v", |
156 "-r", work, | 155 "-r", work, |
157 "-o", targ, | 156 "-o", targ, |
158 "--scripts", scripts, | 157 "--scripts", scripts, |
159 "--id", "com.googlecode.go", | 158 "--id", "com.googlecode.go", |
160 "--title", "Go", | 159 "--title", "Go", |
161 "--version", "1.0", | 160 "--version", "1.0", |
162 "--target", "10.5") | 161 "--target", "10.5") |
163 } | 162 } |
164 » if err == nil { | 163 » if err == nil && password != "" { |
165 » » log.Println("built", targ) | 164 » » err = b.upload(string(v[2]), targ) |
166 » » if *password != "" { | |
167 » » » err = b.upload(string(v[2]), targ) | |
168 » » } | |
169 } | 165 } |
170 return err | 166 return err |
171 } | 167 } |
172 | 168 |
173 func (b *Build) run(dir, name string, args ...string) ([]byte, error) { | 169 func (b *Build) run(dir, name string, args ...string) ([]byte, error) { |
174 buf := new(bytes.Buffer) | 170 buf := new(bytes.Buffer) |
175 cmd := exec.Command(name, args...) | 171 cmd := exec.Command(name, args...) |
176 cmd.Stdout = buf | 172 cmd.Stdout = buf |
177 cmd.Stderr = buf | 173 cmd.Stderr = buf |
178 cmd.Dir = dir | 174 cmd.Dir = dir |
179 cmd.Env = b.env() | 175 cmd.Env = b.env() |
180 if err := cmd.Run(); err != nil { | 176 if err := cmd.Run(); err != nil { |
181 fmt.Fprintf(os.Stderr, "%s", buf.Bytes()) | 177 fmt.Fprintf(os.Stderr, "%s", buf.Bytes()) |
182 return nil, fmt.Errorf("%s %s: %v", name, strings.Join(args, " "
), err) | 178 return nil, fmt.Errorf("%s %s: %v", name, strings.Join(args, " "
), err) |
183 } | 179 } |
184 return buf.Bytes(), nil | 180 return buf.Bytes(), nil |
185 } | 181 } |
186 | 182 |
| 183 var cleanEnv = []string{ |
| 184 "GOARCH", |
| 185 "GOBIN", |
| 186 "GOHOSTARCH", |
| 187 "GOHOSTOS", |
| 188 "GOOS", |
| 189 "GOROOT", |
| 190 "GOROOT_FINAL", |
| 191 } |
| 192 |
187 func (b *Build) env() []string { | 193 func (b *Build) env() []string { |
188 env := os.Environ() | 194 env := os.Environ() |
189 for i := 0; i < len(env); i++ { | 195 for i := 0; i < len(env); i++ { |
190 » » e := env[i] | 196 » » for _, c := range cleanEnv { |
191 » » if strings.HasPrefix(e, "GOROOT=") || | 197 » » » if strings.HasPrefix(env[i], c+"=") { |
192 » » » strings.HasPrefix(e, "GOOS=") || | 198 » » » » env = append(env[:i], env[i+1:]...) |
193 » » » strings.HasPrefix(e, "GOARCH=") { | 199 » » » } |
194 » » » env = append(env[:i], env[i+1:]...) | |
195 } | 200 } |
196 } | 201 } |
197 env = append(env, | 202 env = append(env, |
198 "GOARCH="+b.Arch, | 203 "GOARCH="+b.Arch, |
199 "GOHOSTARCH="+b.Arch, | 204 "GOHOSTARCH="+b.Arch, |
200 "GOHOSTOS="+b.OS, | 205 "GOHOSTOS="+b.OS, |
201 "GOOS="+b.OS, | 206 "GOOS="+b.OS, |
202 "GOROOT="+b.root, | 207 "GOROOT="+b.root, |
203 "GOROOT_FINAL=/usr/local/go", | 208 "GOROOT_FINAL=/usr/local/go", |
204 ) | 209 ) |
205 return env | 210 return env |
206 } | |
207 | |
208 func exists(path string) bool { | |
209 _, err := os.Stat(path) | |
210 return err == nil | |
211 } | 211 } |
212 | 212 |
213 func (b *Build) upload(version string, filename string) error { | 213 func (b *Build) upload(version string, filename string) error { |
214 // Prepare upload metadata. | 214 // Prepare upload metadata. |
215 labels := []string{"Arch-" + b.Arch} | 215 labels := []string{"Arch-" + b.Arch} |
216 os_, arch := b.OS, b.Arch | 216 os_, arch := b.OS, b.Arch |
217 switch b.Arch { | 217 switch b.Arch { |
218 case "386": | 218 case "386": |
219 arch = "32-bit" | 219 arch = "32-bit" |
220 case "amd64": | 220 case "amd64": |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
260 } | 260 } |
261 if err := w.Close(); err != nil { | 261 if err := w.Close(); err != nil { |
262 return err | 262 return err |
263 } | 263 } |
264 | 264 |
265 // Send the file to Google Code. | 265 // Send the file to Google Code. |
266 req, err := http.NewRequest("POST", uploadURL, body) | 266 req, err := http.NewRequest("POST", uploadURL, body) |
267 if err != nil { | 267 if err != nil { |
268 return err | 268 return err |
269 } | 269 } |
270 » token := fmt.Sprintf("%s:%s", *user, *password) | 270 » token := fmt.Sprintf("%s:%s", username, password) |
271 token = base64.StdEncoding.EncodeToString([]byte(token)) | 271 token = base64.StdEncoding.EncodeToString([]byte(token)) |
272 req.Header.Set("Authorization", "Basic "+token) | 272 req.Header.Set("Authorization", "Basic "+token) |
273 req.Header.Set("Content-type", w.FormDataContentType()) | 273 req.Header.Set("Content-type", w.FormDataContentType()) |
274 | 274 |
275 resp, err := http.DefaultTransport.RoundTrip(req) | 275 resp, err := http.DefaultTransport.RoundTrip(req) |
276 if err != nil { | 276 if err != nil { |
277 return err | 277 return err |
278 } | 278 } |
279 if resp.StatusCode/100 != 2 { | 279 if resp.StatusCode/100 != 2 { |
280 fmt.Fprintln(os.Stderr, "upload failed") | 280 fmt.Fprintln(os.Stderr, "upload failed") |
281 defer resp.Body.Close() | 281 defer resp.Body.Close() |
282 io.Copy(os.Stderr, resp.Body) | 282 io.Copy(os.Stderr, resp.Body) |
283 return fmt.Errorf("upload: %s", resp.Status) | 283 return fmt.Errorf("upload: %s", resp.Status) |
284 } | 284 } |
285 return nil | 285 return nil |
286 } | 286 } |
| 287 |
| 288 func exists(path string) bool { |
| 289 _, err := os.Stat(path) |
| 290 return err == nil |
| 291 } |
| 292 |
| 293 func readCredentials() { |
| 294 name := filepath.Join(os.Getenv("HOME"), ".gobuildkey") |
| 295 c, err := ioutil.ReadFile(name) |
| 296 if err != nil { |
| 297 log.Println("readCredentials:", err) |
| 298 return |
| 299 } |
| 300 v := bytes.Split(c, []byte("\n")) |
| 301 if len(v) >= 3 { |
| 302 username, password = string(v[1]), string(v[2]) |
| 303 } |
| 304 } |
LEFT | RIGHT |