prefix, repo string
}
-// findHostedRepo checks whether pkg is located at one of
+// findPublicRepo checks whether pkg is located at one of
// the supported code hosting sites and, if so, returns a match.
-func findHostedRepo(pkg string) (*vcsMatch, os.Error) {
+func findPublicRepo(pkg string) (*vcsMatch, os.Error) {
for _, v := range vcsList {
for _, host := range v.defaultHosts {
if hm := host.pattern.FindStringSubmatch(pkg); hm != nil {
}
// download checks out or updates pkg from the remote server.
-func download(pkg, srcDir string) (dashReport bool, err os.Error) {
+func download(pkg, srcDir string) (public bool, err os.Error) {
if strings.Contains(pkg, "..") {
err = os.NewError("invalid path (contains ..)")
return
}
- m, err := findHostedRepo(pkg)
+ m, err := findPublicRepo(pkg)
if err != nil {
return
}
if m != nil {
- dashReport = true // only report public code hosting sites
+ public = true
} else {
m, err = findAnyRepo(pkg)
if err != nil {
err = os.NewError("cannot download: " + pkg)
return
}
- installed, err := m.checkoutRepo(srcDir, m.prefix, m.repo)
- if err != nil {
- return
- }
- if !installed {
- dashReport = false
- }
+ err = m.checkoutRepo(srcDir, m.prefix, m.repo)
return
}
// exists and -u was specified on the command line)
// the repository at tag/branch "release". If there is no
// such tag or branch, it falls back to the repository tip.
-func (vcs *vcs) checkoutRepo(srcDir, pkgprefix, repo string) (installed bool, err os.Error) {
+func (vcs *vcs) checkoutRepo(srcDir, pkgprefix, repo string) os.Error {
dst := filepath.Join(srcDir, filepath.FromSlash(pkgprefix))
dir, err := os.Stat(filepath.Join(dst, vcs.metadir))
if err == nil && !dir.IsDirectory() {
- err = os.NewError("not a directory: " + dst)
- return
+ return os.NewError("not a directory: " + dst)
}
if err != nil {
parent, _ := filepath.Split(dst)
if err = os.MkdirAll(parent, 0777); err != nil {
- return
+ return err
}
if err = run(string(filepath.Separator), nil, vcs.cmd, vcs.clone, repo, dst); err != nil {
- return
- }
- if err = vcs.updateRepo(dst); err != nil {
- return
+ return err
}
- installed = true
- } else if *update {
+ return vcs.updateRepo(dst)
+ }
+ if *update {
// Retrieve new revisions from the remote branch, if the VCS
// supports this operation independently (e.g. svn doesn't)
if vcs.pull != "" {
if vcs.pullForceFlag != "" {
if err = run(dst, nil, vcs.cmd, vcs.pull, vcs.pullForceFlag); err != nil {
- return
+ return err
}
} else if err = run(dst, nil, vcs.cmd, vcs.pull); err != nil {
- return
+ return err
}
}
// Update to release or latest revision
- if err = vcs.updateRepo(dst); err != nil {
- return
- }
+ return vcs.updateRepo(dst)
}
- return
+ return nil
}
os.Exit(2)
}
+const logfile = "goinstall.log"
+
var (
fset = token.NewFileSet()
argv0 = os.Args[0]
errors = false
parents = make(map[string]string)
visit = make(map[string]status)
- logfile = filepath.Join(runtime.GOROOT(), "goinstall.log")
- installedPkgs = make(map[string]bool)
+ installedPkgs = make(map[string]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")
doInstall = flag.Bool("install", true, "build and install")
clean = flag.Bool("clean", false, "clean the package directory before installing")
fmt.Fprintf(os.Stderr, "%s: no $GOROOT\n", argv0)
os.Exit(1)
}
+ readPackageList()
// special case - "unsafe" is already installed
visit["unsafe"] = done
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)
+ n := 0
+ for _, pkgs := range installedPkgs {
+ for pkg := range pkgs {
+ args = append(args, pkg)
+ n++
+ }
}
- args = make([]string, len(installedPkgs), len(installedPkgs))
- i := 0
- for pkg := range installedPkgs {
- args[i] = pkg
- i++
+ if n == 0 {
+ logf("no installed packages\n")
+ os.Exit(1)
}
}
if len(args) == 0 {
fmt.Fprintf(os.Stderr, "\t%s ->\n", pkg)
}
-// readPackageList reads the list of installed packages from goinstall.log
+// readPackageList reads the list of installed packages from the
+// goinstall.log files in GOROOT and the GOPATHs and initalizes
+// the installedPkgs variable.
func readPackageList() {
- pkglistdata, _ := ioutil.ReadFile(logfile)
- pkglist := strings.Fields(string(pkglistdata))
- for _, pkg := range pkglist {
- installedPkgs[pkg] = true
+ for _, t := range build.Path {
+ installedPkgs[t.Path] = make(map[string]bool)
+ name := filepath.Join(t.Path, logfile)
+ pkglistdata, err := ioutil.ReadFile(name)
+ if err != nil {
+ printf("%s\n", err)
+ continue
+ }
+ pkglist := strings.Fields(string(pkglistdata))
+ for _, pkg := range pkglist {
+ installedPkgs[t.Path][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
+// logPackage logs the named package as installed in the goinstall.log file
+// in the given tree if the package is not already in that file.
+func logPackage(pkg string, tree *build.Tree) (logged bool) {
+ if installedPkgs[tree.Path][pkg] {
+ return false
}
- fout, err := os.OpenFile(logfile, os.O_WRONLY|os.O_CREATE|os.O_APPEND, 0666)
+ name := filepath.Join(tree.Path, logfile)
+ fout, err := os.OpenFile(name, os.O_WRONLY|os.O_CREATE|os.O_APPEND, 0666)
if err != nil {
- fmt.Fprintf(os.Stderr, "%s: %s\n", argv0, err)
- return
+ logf("%s\n", err)
+ return false
}
fmt.Fprintf(fout, "%s\n", pkg)
fout.Close()
+ return true
}
// install installs the package named by path, which is needed by parent.
return
}
// Download remote packages if not found or forced with -u flag.
- remote := isRemote(pkg)
- dashReport := false
+ remote, public := isRemote(pkg), false
if remote && (err == build.ErrNotFound || (err == nil && *update)) {
printf("%s: download\n", pkg)
- dashReport, err = download(pkg, tree.SrcDir())
+ public, err = download(pkg, tree.SrcDir())
}
if err != nil {
errorf("%s: %v\n", pkg, err)
}
}
}
- if dashReport {
- maybeReportToDashboard(pkg)
- }
+
if remote {
- // mark package as installed in $GOROOT/goinstall.log
- logPackage(pkg)
+ // mark package as installed in goinstall.log
+ logged := logPackage(pkg, tree)
+
+ // report installation to the dashboard if this is the first
+ // install from a public repository.
+ if logged && public {
+ maybeReportToDashboard(pkg)
+ }
}
- return
}
// Is this a standard package path? strings container/vector etc.