~ubuntu-branches/ubuntu/vivid/golang/vivid

« back to all changes in this revision

Viewing changes to misc/dist/bindist.go

  • Committer: Package Import Robot
  • Author(s): James Page
  • Date: 2013-08-20 14:06:23 UTC
  • mfrom: (14.1.23 saucy-proposed)
  • Revision ID: package-import@ubuntu.com-20130820140623-b414jfxi3m0qkmrq
Tags: 2:1.1.2-2ubuntu1
* Merge from Debian unstable (LP: #1211749, #1202027). Remaining changes:
  - 016-armhf-elf-header.patch: Use correct ELF header for armhf binaries.
  - d/control,control.cross: Update Breaks/Replaces for Ubuntu
    versions to ensure smooth upgrades, regenerate control file.

Show diffs side-by-side

added added

removed removed

Lines of Context:
3
3
// license that can be found in the LICENSE file.
4
4
 
5
5
// This is a tool for packaging binary releases.
6
 
// It supports FreeBSD, Linux, OS X, and Windows.
 
6
// It supports FreeBSD, Linux, NetBSD, OS X, and Windows.
7
7
package main
8
8
 
9
9
import (
13
13
        "bytes"
14
14
        "compress/gzip"
15
15
        "encoding/base64"
16
 
        "errors"
17
16
        "flag"
18
17
        "fmt"
19
18
        "io"
30
29
)
31
30
 
32
31
var (
33
 
        tag      = flag.String("tag", "weekly", "mercurial tag to check out")
34
 
        repo     = flag.String("repo", "https://code.google.com/p/go", "repo URL")
35
 
        verbose  = flag.Bool("v", false, "verbose output")
36
 
        upload   = flag.Bool("upload", true, "upload resulting files to Google Code")
37
 
        wxsFile  = flag.String("wxs", "", "path to custom installer.wxs")
38
 
        addLabel = flag.String("label", "", "additional label to apply to file when uploading")
 
32
        tag             = flag.String("tag", "release", "mercurial tag to check out")
 
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 repo import path")
 
35
        verbose         = flag.Bool("v", false, "verbose output")
 
36
        upload          = flag.Bool("upload", true, "upload resulting files to Google Code")
 
37
        wxsFile         = flag.String("wxs", "", "path to custom installer.wxs")
 
38
        addLabel        = flag.String("label", "", "additional label to apply to file when uploading")
 
39
        includeRace     = flag.Bool("race", true, "build race detector packages")
 
40
        versionOverride = flag.String("version", "", "override version name")
39
41
 
40
42
        username, password string // for Google Code upload
41
43
)
42
44
 
43
45
const (
44
 
        packageMaker = "/Applications/Utilities/PackageMaker.app/Contents/MacOS/PackageMaker"
45
 
        uploadURL    = "https://go.googlecode.com/files"
 
46
        uploadURL = "https://go.googlecode.com/files"
46
47
)
47
48
 
48
49
var preBuildCleanFiles = []string{
66
67
        "pkg",
67
68
}
68
69
 
69
 
var fileRe = regexp.MustCompile(`^go\.([a-z0-9-.]+)\.(src|([a-z0-9]+)-([a-z0-9]+))\.`)
 
70
var tourPackages = []string{
 
71
        "pic",
 
72
        "tree",
 
73
        "wc",
 
74
}
 
75
 
 
76
var tourContent = []string{
 
77
        "js",
 
78
        "prog",
 
79
        "solutions",
 
80
        "static",
 
81
        "template",
 
82
        "tour.article",
 
83
}
 
84
 
 
85
// The os-arches that support the race toolchain.
 
86
var raceAvailable = []string{
 
87
        "darwin-amd64",
 
88
        "linux-amd64",
 
89
        "windows-amd64",
 
90
}
 
91
 
 
92
var fileRe = regexp.MustCompile(`^(go[a-z0-9-.]+)\.(src|([a-z0-9]+)-([a-z0-9]+))\.`)
70
93
 
71
94
func main() {
72
95
        flag.Usage = func() {
117
140
                        }
118
141
                        b.OS = p[0]
119
142
                        b.Arch = p[1]
 
143
                        if *includeRace {
 
144
                                for _, t := range raceAvailable {
 
145
                                        if t == targ {
 
146
                                                b.Race = true
 
147
                                        }
 
148
                                }
 
149
                        }
120
150
                }
121
151
                if err := b.Do(); err != nil {
122
152
                        log.Printf("%s: %v", targ, err)
126
156
 
127
157
type Build struct {
128
158
        Source bool // if true, OS and Arch must be empty
 
159
        Race   bool // build race toolchain
129
160
        OS     string
130
161
        Arch   string
131
162
        root   string
 
163
        gopath string
132
164
}
133
165
 
134
166
func (b *Build) Do() error {
138
170
        }
139
171
        defer os.RemoveAll(work)
140
172
        b.root = filepath.Join(work, "go")
 
173
        b.gopath = work
141
174
 
142
175
        // Clone Go distribution and update to tag.
143
176
        _, err = b.run(work, "hg", "clone", "-q", *repo, b.root)
168
201
                } else {
169
202
                        _, err = b.run(src, "bash", "make.bash")
170
203
                }
 
204
                if b.Race {
 
205
                        if err != nil {
 
206
                                return err
 
207
                        }
 
208
                        goCmd := filepath.Join(b.root, "bin", "go")
 
209
                        if b.OS == "windows" {
 
210
                                goCmd += ".exe"
 
211
                        }
 
212
                        _, err = b.run(src, goCmd, "install", "-race", "std")
 
213
                        if err != nil {
 
214
                                return err
 
215
                        }
 
216
                        // Re-install std without -race, so that we're not left
 
217
                        // with a slower, race-enabled cmd/go, cmd/godoc, etc.
 
218
                        _, err = b.run(src, goCmd, "install", "-a", "std")
 
219
                }
 
220
                if err != nil {
 
221
                        return err
 
222
                }
 
223
                err = b.tour()
171
224
        }
172
225
        if err != nil {
173
226
                return err
193
246
        fullVersion = bytes.TrimSpace(fullVersion)
194
247
        v := bytes.SplitN(fullVersion, []byte(" "), 2)
195
248
        version = string(v[0])
 
249
        if *versionOverride != "" {
 
250
                version = *versionOverride
 
251
        }
196
252
 
197
253
        // Write VERSION file.
198
254
        err = ioutil.WriteFile(filepath.Join(b.root, "VERSION"), fullVersion, 0644)
211
267
        }
212
268
 
213
269
        // Create packages.
214
 
        base := fmt.Sprintf("go.%s.%s-%s", version, b.OS, b.Arch)
 
270
        base := fmt.Sprintf("%s.%s-%s", version, b.OS, b.Arch)
 
271
        if !strings.HasPrefix(base, "go") {
 
272
                base = "go." + base
 
273
        }
215
274
        var targs []string
216
275
        switch b.OS {
217
 
        case "linux", "freebsd", "":
 
276
        case "linux", "freebsd", "netbsd", "":
218
277
                // build tarball
219
278
                targ := base
220
279
                if b.Source {
221
 
                        targ = fmt.Sprintf("go.%s.src", version)
 
280
                        targ = fmt.Sprintf("%s.src", version)
 
281
                        if !strings.HasPrefix(targ, "go") {
 
282
                                targ = "go." + targ
 
283
                        }
222
284
                }
223
285
                targ += ".tar.gz"
224
286
                err = makeTar(targ, work)
225
287
                targs = append(targs, targ)
226
288
        case "darwin":
 
289
                // build tarball
 
290
                targ := base + ".tar.gz"
 
291
                err = makeTar(targ, work)
 
292
                targs = append(targs, targ)
 
293
 
 
294
                // build pkg
227
295
                // arrange work so it's laid out as the dest filesystem
228
296
                etc := filepath.Join(b.root, "misc/dist/darwin/etc")
229
297
                _, err = b.run(work, "cp", "-r", etc, ".")
231
299
                        return err
232
300
                }
233
301
                localDir := filepath.Join(work, "usr/local")
234
 
                err = os.MkdirAll(localDir, 0744)
 
302
                err = os.MkdirAll(localDir, 0755)
235
303
                if err != nil {
236
304
                        return err
237
305
                }
240
308
                        return err
241
309
                }
242
310
                // build package
243
 
                pm := packageMaker
244
 
                if !exists(pm) {
245
 
                        pm = "/Developer" + pm
246
 
                        if !exists(pm) {
247
 
                                return errors.New("couldn't find PackageMaker")
248
 
                        }
 
311
                pkgdest, err := ioutil.TempDir("", "pkgdest")
 
312
                if err != nil {
 
313
                        return err
249
314
                }
250
 
                targ := base + ".pkg"
251
 
                scripts := filepath.Join(work, "usr/local/go/misc/dist/darwin/scripts")
252
 
                _, err = b.run("", pm, "-v",
253
 
                        "-r", work,
254
 
                        "-o", targ,
255
 
                        "--scripts", scripts,
256
 
                        "--id", "com.googlecode.go",
257
 
                        "--title", "Go",
 
315
                defer os.RemoveAll(pkgdest)
 
316
                dist := filepath.Join(runtime.GOROOT(), "misc/dist")
 
317
                _, err = b.run("", "pkgbuild",
 
318
                        "--identifier", "com.googlecode.go",
258
319
                        "--version", "1.0",
259
 
                        "--target", "10.6")
 
320
                        "--scripts", filepath.Join(dist, "darwin/scripts"),
 
321
                        "--root", work,
 
322
                        filepath.Join(pkgdest, "com.googlecode.go.pkg"))
 
323
                if err != nil {
 
324
                        return err
 
325
                }
 
326
                targ = base + ".pkg"
 
327
                _, err = b.run("", "productbuild",
 
328
                        "--distribution", filepath.Join(dist, "darwin/Distribution"),
 
329
                        "--resources", filepath.Join(dist, "darwin/Resources"),
 
330
                        "--package-path", pkgdest,
 
331
                        targ)
 
332
                if err != nil {
 
333
                        return err
 
334
                }
260
335
                targs = append(targs, targ)
261
336
        case "windows":
262
337
                // Create ZIP file.
327
402
        return err
328
403
}
329
404
 
 
405
func (b *Build) tour() error {
 
406
        // go get the gotour package.
 
407
        _, err := b.run(b.gopath, filepath.Join(b.root, "bin", "go"), "get", *tourPath+"/gotour")
 
408
        if err != nil {
 
409
                return err
 
410
        }
 
411
 
 
412
        // Copy all the tour content to $GOROOT/misc/tour.
 
413
        importPath := filepath.FromSlash(*tourPath)
 
414
        tourSrc := filepath.Join(b.gopath, "src", importPath)
 
415
        contentDir := filepath.Join(b.root, "misc", "tour")
 
416
        if err = cpAllDir(contentDir, tourSrc, tourContent...); err != nil {
 
417
                return err
 
418
        }
 
419
 
 
420
        // Copy the tour source code so it's accessible with $GOPATH pointing to $GOROOT/misc/tour.
 
421
        if err = cpAllDir(filepath.Join(contentDir, "src", importPath), tourSrc, tourPackages...); err != nil {
 
422
                return err
 
423
        }
 
424
 
 
425
        // Copy gotour binary to tool directory as "tour"; invoked as "go tool tour".
 
426
        ext := ""
 
427
        if runtime.GOOS == "windows" {
 
428
                ext = ".exe"
 
429
        }
 
430
        return cp(
 
431
                filepath.Join(b.root, "pkg", "tool", b.OS+"_"+b.Arch, "tour"+ext),
 
432
                filepath.Join(b.gopath, "bin", "gotour"+ext),
 
433
        )
 
434
}
 
435
 
330
436
func (b *Build) run(dir, name string, args ...string) ([]byte, error) {
331
437
        buf := new(bytes.Buffer)
332
438
        absName, err := lookPath(name)
358
464
        "GOOS",
359
465
        "GOROOT",
360
466
        "GOROOT_FINAL",
 
467
        "GOPATH",
361
468
}
362
469
 
363
470
func (b *Build) env() []string {
380
487
                "GOOS="+b.OS,
381
488
                "GOROOT="+b.root,
382
489
                "GOROOT_FINAL="+final,
 
490
                "GOPATH="+b.gopath,
383
491
        )
384
492
        return env
385
493
}
390
498
        os_, arch := b.OS, b.Arch
391
499
        switch b.Arch {
392
500
        case "386":
393
 
                arch = "32-bit"
 
501
                arch = "x86 32-bit"
394
502
        case "amd64":
395
 
                arch = "64-bit"
 
503
                arch = "x86 64-bit"
396
504
        }
397
505
        if arch != "" {
398
506
                labels = append(labels, "Arch-"+b.Arch)
399
507
        }
 
508
        var opsys, ftype string // labels
400
509
        switch b.OS {
401
510
        case "linux":
402
511
                os_ = "Linux"
403
 
                labels = append(labels, "Type-Archive", "OpSys-Linux")
 
512
                opsys = "Linux"
404
513
        case "freebsd":
405
514
                os_ = "FreeBSD"
406
 
                labels = append(labels, "Type-Archive", "OpSys-FreeBSD")
 
515
                opsys = "FreeBSD"
407
516
        case "darwin":
408
517
                os_ = "Mac OS X"
409
 
                labels = append(labels, "Type-Installer", "OpSys-OSX")
 
518
                opsys = "OSX"
 
519
        case "netbsd":
 
520
                os_ = "NetBSD"
 
521
                opsys = "NetBSD"
410
522
        case "windows":
411
523
                os_ = "Windows"
412
 
                labels = append(labels, "OpSys-Windows")
 
524
                opsys = "Windows"
413
525
        }
414
526
        summary := fmt.Sprintf("%s %s (%s)", version, os_, arch)
415
 
        if b.OS == "windows" {
416
 
                switch {
417
 
                case strings.HasSuffix(filename, ".msi"):
418
 
                        labels = append(labels, "Type-Installer")
419
 
                        summary += " MSI installer"
420
 
                case strings.HasSuffix(filename, ".zip"):
421
 
                        labels = append(labels, "Type-Archive")
422
 
                        summary += " ZIP archive"
423
 
                }
 
527
        switch {
 
528
        case strings.HasSuffix(filename, ".msi"):
 
529
                ftype = "Installer"
 
530
                summary += " MSI installer"
 
531
        case strings.HasSuffix(filename, ".pkg"):
 
532
                ftype = "Installer"
 
533
                summary += " PKG installer"
 
534
        case strings.HasSuffix(filename, ".zip"):
 
535
                ftype = "Archive"
 
536
                summary += " ZIP archive"
 
537
        case strings.HasSuffix(filename, ".tar.gz"):
 
538
                ftype = "Archive"
 
539
                summary += " tarball"
424
540
        }
425
541
        if b.Source {
426
 
                labels = append(labels, "Type-Source")
 
542
                ftype = "Source"
427
543
                summary = fmt.Sprintf("%s (source only)", version)
428
544
        }
 
545
        if opsys != "" {
 
546
                labels = append(labels, "OpSys-"+opsys)
 
547
        }
 
548
        if ftype != "" {
 
549
                labels = append(labels, "Type-"+ftype)
 
550
        }
429
551
        if *addLabel != "" {
430
552
                labels = append(labels, *addLabel)
431
553
        }
535
657
                return err
536
658
        }
537
659
        defer sf.Close()
 
660
        fi, err := sf.Stat()
 
661
        if err != nil {
 
662
                return err
 
663
        }
538
664
        df, err := os.Create(dst)
539
665
        if err != nil {
540
666
                return err
541
667
        }
542
668
        defer df.Close()
 
669
        // Windows doesn't currently implement Fchmod
 
670
        if runtime.GOOS != "windows" {
 
671
                if err := df.Chmod(fi.Mode()); err != nil {
 
672
                        return err
 
673
                }
 
674
        }
543
675
        _, err = io.Copy(df, sf)
544
676
        return err
545
677
}
546
678
 
 
679
func cpDir(dst, src string) error {
 
680
        walk := func(srcPath string, info os.FileInfo, err error) error {
 
681
                if err != nil {
 
682
                        return err
 
683
                }
 
684
                dstPath := filepath.Join(dst, srcPath[len(src):])
 
685
                if info.IsDir() {
 
686
                        return os.MkdirAll(dstPath, 0755)
 
687
                }
 
688
                return cp(dstPath, srcPath)
 
689
        }
 
690
        return filepath.Walk(src, walk)
 
691
}
 
692
 
 
693
func cpAllDir(dst, basePath string, dirs ...string) error {
 
694
        for _, dir := range dirs {
 
695
                if err := cpDir(filepath.Join(dst, dir), filepath.Join(basePath, dir)); err != nil {
 
696
                        return err
 
697
                }
 
698
        }
 
699
        return nil
 
700
}
 
701
 
547
702
func makeTar(targ, workdir string) error {
548
703
        f, err := os.Create(targ)
549
704
        if err != nil {
552
707
        zout := gzip.NewWriter(f)
553
708
        tw := tar.NewWriter(zout)
554
709
 
555
 
        filepath.Walk(workdir, filepath.WalkFunc(func(path string, fi os.FileInfo, err error) error {
 
710
        err = filepath.Walk(workdir, func(path string, fi os.FileInfo, err error) error {
556
711
                if !strings.HasPrefix(path, workdir) {
557
712
                        log.Panicf("walked filename %q doesn't begin with workdir %q", path, workdir)
558
713
                }
570
725
                if *verbose {
571
726
                        log.Printf("adding to tar: %s", name)
572
727
                }
573
 
                if fi.IsDir() {
574
 
                        return nil
575
 
                }
576
 
                hdr, err := tarFileInfoHeader(fi, path)
 
728
                target, _ := os.Readlink(path)
 
729
                hdr, err := tar.FileInfoHeader(fi, target)
577
730
                if err != nil {
578
731
                        return err
579
732
                }
594
747
                if err != nil {
595
748
                        return fmt.Errorf("Error writing file %q: %v", name, err)
596
749
                }
 
750
                if fi.IsDir() {
 
751
                        return nil
 
752
                }
597
753
                r, err := os.Open(path)
598
754
                if err != nil {
599
755
                        return err
601
757
                defer r.Close()
602
758
                _, err = io.Copy(tw, r)
603
759
                return err
604
 
        }))
605
 
 
 
760
        })
 
761
        if err != nil {
 
762
                return err
 
763
        }
606
764
        if err := tw.Close(); err != nil {
607
765
                return err
608
766
        }
619
777
        }
620
778
        zw := zip.NewWriter(f)
621
779
 
622
 
        filepath.Walk(workdir, filepath.WalkFunc(func(path string, fi os.FileInfo, err error) error {
623
 
                if fi.IsDir() {
624
 
                        return nil
625
 
                }
 
780
        err = filepath.Walk(workdir, func(path string, fi os.FileInfo, err error) error {
626
781
                if !strings.HasPrefix(path, workdir) {
627
782
                        log.Panicf("walked filename %q doesn't begin with workdir %q", path, workdir)
628
783
                }
649
804
                }
650
805
                fh.Name = name
651
806
                fh.Method = zip.Deflate
 
807
                if fi.IsDir() {
 
808
                        fh.Name += "/"        // append trailing slash
 
809
                        fh.Method = zip.Store // no need to deflate 0 byte files
 
810
                }
652
811
                w, err := zw.CreateHeader(fh)
653
812
                if err != nil {
654
813
                        return err
655
814
                }
 
815
                if fi.IsDir() {
 
816
                        return nil
 
817
                }
656
818
                r, err := os.Open(path)
657
819
                if err != nil {
658
820
                        return err
660
822
                defer r.Close()
661
823
                _, err = io.Copy(w, r)
662
824
                return err
663
 
        }))
664
 
 
 
825
        })
 
826
        if err != nil {
 
827
                return err
 
828
        }
665
829
        if err := zw.Close(); err != nil {
666
830
                return err
667
831
        }
733
897
        }
734
898
        return
735
899
}
736
 
 
737
 
// sysStat, if non-nil, populates h from system-dependent fields of fi.
738
 
var sysStat func(fi os.FileInfo, h *tar.Header) error
739
 
 
740
 
// Mode constants from the tar spec.
741
 
const (
742
 
        c_ISDIR  = 040000
743
 
        c_ISFIFO = 010000
744
 
        c_ISREG  = 0100000
745
 
        c_ISLNK  = 0120000
746
 
        c_ISBLK  = 060000
747
 
        c_ISCHR  = 020000
748
 
        c_ISSOCK = 0140000
749
 
)
750
 
 
751
 
// tarFileInfoHeader creates a partially-populated Header from an os.FileInfo.
752
 
// The filename parameter is used only in the case of symlinks, to call os.Readlink.
753
 
// If fi is a symlink but filename is empty, an error is returned.
754
 
func tarFileInfoHeader(fi os.FileInfo, filename string) (*tar.Header, error) {
755
 
        h := &tar.Header{
756
 
                Name:    fi.Name(),
757
 
                ModTime: fi.ModTime(),
758
 
                Mode:    int64(fi.Mode().Perm()), // or'd with c_IS* constants later
759
 
        }
760
 
        switch {
761
 
        case fi.Mode()&os.ModeType == 0:
762
 
                h.Mode |= c_ISREG
763
 
                h.Typeflag = tar.TypeReg
764
 
                h.Size = fi.Size()
765
 
        case fi.IsDir():
766
 
                h.Typeflag = tar.TypeDir
767
 
                h.Mode |= c_ISDIR
768
 
        case fi.Mode()&os.ModeSymlink != 0:
769
 
                h.Typeflag = tar.TypeSymlink
770
 
                h.Mode |= c_ISLNK
771
 
                if filename == "" {
772
 
                        return h, fmt.Errorf("archive/tar: unable to populate Header.Linkname of symlinks")
773
 
                }
774
 
                targ, err := os.Readlink(filename)
775
 
                if err != nil {
776
 
                        return h, err
777
 
                }
778
 
                h.Linkname = targ
779
 
        case fi.Mode()&os.ModeDevice != 0:
780
 
                if fi.Mode()&os.ModeCharDevice != 0 {
781
 
                        h.Mode |= c_ISCHR
782
 
                        h.Typeflag = tar.TypeChar
783
 
                } else {
784
 
                        h.Mode |= c_ISBLK
785
 
                        h.Typeflag = tar.TypeBlock
786
 
                }
787
 
        case fi.Mode()&os.ModeSocket != 0:
788
 
                h.Mode |= c_ISSOCK
789
 
        default:
790
 
                return nil, fmt.Errorf("archive/tar: unknown file mode %v", fi.Mode())
791
 
        }
792
 
        if sysStat != nil {
793
 
                return h, sysStat(fi, h)
794
 
        }
795
 
        return h, nil
796
 
}