]> Cypherpunks repositories - gostls13.git/commitdiff
goinstall: added -a flag to mean "all remote packages"
authorScott Lawrence <bytbox@gmail.com>
Thu, 2 Sep 2010 17:48:28 +0000 (13:48 -0400)
committerRuss Cox <rsc@golang.org>
Thu, 2 Sep 2010 17:48:28 +0000 (13:48 -0400)
Fixes #897.

goinstall -a can be used to reinstall all packages after an upgrade
goinstall -a -u can be used to update all package
A history of remote package installs is stored in $GOROOT/goinstall.log

R=rsc, adg
CC=golang-dev
https://golang.org/cl/1947041

.hgignore
src/cmd/goinstall/doc.go
src/cmd/goinstall/main.go

index 450a7e17bead7a2a26f375cb0f0dc1ab47a2d117..54b54366df9ddddb6e412db499f7bb89fa1a8af3 100644 (file)
--- a/.hgignore
+++ b/.hgignore
@@ -40,6 +40,7 @@ test/pass.out
 test/run.out
 test/times.out
 test/garbage/*.out
+goinstall.log
 
 syntax:regexp
 ^bin/
index 81b8a4316a4aab75067bca4a9edb4ea8263fd320..5705266d016eba046fb7e011b07c17af2b8bef41 100644 (file)
@@ -10,14 +10,33 @@ It maintains a list of public Go packages at http://godashboard.appspot.com/pack
 
 Usage:
        goinstall [flags] importpath...
+       goinstall [flags] -a
 
 Flags and default settings:
+        -a=false          install all previously installed packages
        -dashboard=true   tally public packages on godashboard.appspot.com
-       -update=false     update already-downloaded packages
+       -log=true         log installed packages to $GOROOT/goinstall.log for use by -a
+       -u=false          update already-downloaded packages
        -v=false          verbose operation
 
-Goinstall installs each of the packages identified on the command line.
-It installs a package's prerequisites before trying to install the package itself.
+Goinstall installs each of the packages identified on the command line.  It
+installs a package's prerequisites before trying to install the package
+itself. Unless -log=false is specified, goinstall logs the import path of each
+installed package to $GOROOT/goinstall.log for use by goinstall -a.
+
+If the -a flag is given, goinstall reinstalls all previously installed
+packages, reading the list from $GOROOT/goinstall.log.  After updating to a
+new Go release, which deletes all package binaries, running
+
+       goinstall -a
+
+will recompile and reinstall goinstalled packages.
+
+Another common idiom is to use
+
+       goinstall -a -u
+
+to update, recompile, and reinstall all goinstalled packages.
 
 The source code for a package with import path foo/bar is expected
 to be in the directory $GOROOT/src/pkg/foo/bar/.  If the import
@@ -54,7 +73,7 @@ if necessary.  The recognized code hosting sites are:
 
 If the destination directory (e.g., $GOROOT/src/pkg/bitbucket.org/user/project)
 already exists and contains an appropriate checkout, goinstall will not
-attempt to fetch updates.  The -update flag changes this behavior,
+attempt to fetch updates.  The -u flag changes this behavior,
 causing goinstall to update all remote packages encountered during
 the installation.
 
index 59eeb64bf48d83e3f0c5ddf21ad05ecce26ea392..f0bd9c5b1cef2c8905c54253754070ab97de2102 100644 (file)
@@ -12,6 +12,7 @@ import (
        "flag"
        "fmt"
        "io"
+       "io/ioutil"
        "os"
        "path"
        "runtime"
@@ -20,19 +21,24 @@ import (
 
 func usage() {
        fmt.Fprint(os.Stderr, "usage: goinstall importpath...\n")
+       fmt.Fprintf(os.Stderr, "\tgoinstall -a\n")
        flag.PrintDefaults()
        os.Exit(2)
 }
 
 var (
-       argv0   = os.Args[0]
-       errors  = false
-       gobin   = os.Getenv("GOBIN")
-       parents = make(map[string]string)
-       root    = runtime.GOROOT()
-       visit   = make(map[string]status)
+       argv0         = os.Args[0]
+       errors        = false
+       gobin         = os.Getenv("GOBIN")
+       parents       = make(map[string]string)
+       root          = runtime.GOROOT()
+       visit         = make(map[string]status)
+       logfile       = path.Join(root, "goinstall.log")
+       installedPkgs = make(map[string]bool)
 
+       allpkg            = flag.Bool("a", false, "install all previously installed packages")
        reportToDashboard = flag.Bool("dashboard", true, "report public packages at "+dashboardURL)
+       logPkgs           = flag.Bool("log", true, "log installed packages to $GOROOT/goinstall.log for use by -a")
        update            = flag.Bool("u", false, "update already-downloaded packages")
        verbose           = flag.Bool("v", false, "verbose")
 )
@@ -59,8 +65,26 @@ func main() {
        // special case - "unsafe" is already installed
        visit["unsafe"] = done
 
-       // install command line arguments
        args := flag.Args()
+       if *allpkg || *logPkgs {
+               readPackageList()
+       }
+       if *allpkg {
+               if len(args) != 0 {
+                       usage() // -a and package list both provided
+               }
+               // install all packages that were ever installed
+               if len(installedPkgs) == 0 {
+                       fmt.Fprintf(os.Stderr, "%s: no installed packages\n", argv0)
+                       os.Exit(1)
+               }
+               args = make([]string, len(installedPkgs), len(installedPkgs))
+               i := 0
+               for pkg := range installedPkgs {
+                       args[i] = pkg
+                       i++
+               }
+       }
        if len(args) == 0 {
                usage()
        }
@@ -83,6 +107,29 @@ func printDeps(pkg string) {
        fmt.Fprintf(os.Stderr, "\t%s ->\n", pkg)
 }
 
+// readPackageList reads the list of installed packages from goinstall.log
+func readPackageList() {
+       pkglistdata, _ := ioutil.ReadFile(logfile)
+       pkglist := strings.Fields(string(pkglistdata))
+       for _, pkg := range pkglist {
+               installedPkgs[pkg] = true
+       }
+}
+
+// logPackage logs the named package as installed in goinstall.log, if the package is not found in there
+func logPackage(pkg string) {
+       if installedPkgs[pkg] {
+               return
+       }
+       fout, err := os.Open(logfile, os.O_WRONLY|os.O_APPEND|os.O_CREAT, 0644)
+       if err != nil {
+               fmt.Fprintf(os.Stderr, "%s: %s\n", argv0, err)
+               return
+       }
+       fmt.Fprintf(fout, "%s\n", pkg)
+       fout.Close()
+}
+
 // install installs the package named by path, which is needed by parent.
 func install(pkg, parent string) {
        // Make sure we're not already trying to install pkg.
@@ -153,9 +200,11 @@ func install(pkg, parent string) {
                if err := domake(dir, pkg, local); err != nil {
                        fmt.Fprintf(os.Stderr, "%s: installing %s: %s\n", argv0, pkg, err)
                        errors = true
+               } else if !local && *logPkgs {
+                       // mark this package as installed in $GOROOT/goinstall.log
+                       logPackage(pkg)
                }
        }
-
        visit[pkg] = done
 }