blob: b61f7bc2e951b09ea267dcb7f6af66499cdfa1c1 [file] [log] [blame]
// Copyright 2018 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package vgo
import (
"strings"
"cmd/go/internal/base"
"cmd/go/internal/modfetch"
"cmd/go/internal/module"
"cmd/go/internal/mvs"
"cmd/go/internal/semver"
)
var CmdGet = &base.Command{
UsageLine: "get [build flags] [packages]",
Short: "download and install versioned modules and dependencies",
Long: `
Get downloads the latest versions of modules containing the named packages,
along with the versions of the dependencies required by those modules
(not necessarily the latest ones).
It then installs the named packages, like 'go install'.
The -u flag causes get to download the latest version of dependencies as well.
Each package being updated can be suffixed with @version to specify
the desired version. Specifying a version older than the one currently
in use causes a downgrade, which may in turn downgrade other
modules using that one, to keep everything consistent.
TODO: Make this documentation better once the semantic dust settles.
`,
}
var getU = CmdGet.Flag.Bool("u", false, "")
func init() {
CmdGet.Run = runGet // break init loop
}
func runGet(cmd *base.Command, args []string) {
if *getU && len(args) > 0 {
base.Fatalf("vgo get: -u not supported with argument list")
}
if !*getU && len(args) == 0 {
base.Fatalf("vgo get: need arguments or -u")
}
if *getU {
isGetU = true
ImportPaths([]string{"."})
return
}
Init()
InitMod()
var upgrade []module.Version
var downgrade []module.Version
var newPkgs []string
for _, pkg := range args {
var path, vers string
/* OLD CODE
if n := strings.Count(pkg, "(") + strings.Count(pkg, ")"); n > 0 {
i := strings.Index(pkg, "(")
j := strings.Index(pkg, ")")
if n != 2 || i < 0 || j <= i+1 || j != len(pkg)-1 && pkg[j+1] != '/' {
base.Errorf("vgo get: invalid module version syntax: %s", pkg)
continue
}
path, vers = pkg[:i], pkg[i+1:j]
pkg = pkg[:i] + pkg[j+1:]
*/
if i := strings.Index(pkg, "@"); i >= 0 {
path, pkg, vers = pkg[:i], pkg[:i], pkg[i+1:]
if strings.Contains(vers, "@") {
base.Errorf("vgo get: invalid module version syntax: %s", pkg)
continue
}
} else {
path = pkg
vers = "latest"
}
if vers == "none" {
downgrade = append(downgrade, module.Version{Path: path, Version: ""})
} else {
info, err := modfetch.Query(path, vers, allowed)
if err != nil {
base.Errorf("vgo get %v: %v", pkg, err)
continue
}
upgrade = append(upgrade, module.Version{Path: path, Version: info.Version})
newPkgs = append(newPkgs, pkg)
}
}
args = newPkgs
// Upgrade.
var err error
buildList, err = mvs.Upgrade(Target, newReqs(), upgrade...)
if err != nil {
base.Fatalf("vgo get: %v", err)
}
importPaths([]string{"."})
// Downgrade anything that went too far.
version := make(map[string]string)
for _, mod := range buildList {
version[mod.Path] = mod.Version
}
for _, mod := range upgrade {
if semver.Compare(mod.Version, version[mod.Path]) < 0 {
downgrade = append(downgrade, mod)
}
}
if len(downgrade) > 0 {
buildList, err = mvs.Downgrade(Target, newReqs(buildList[1:]...), downgrade...)
if err != nil {
base.Fatalf("vgo get: %v", err)
}
// TODO: Check that everything we need to import is still available.
/*
local := v.matchPackages("all", v.Reqs[:1])
for _, path := range local {
dir, err := v.importDir(path)
if err != nil {
return err // TODO
}
imports, testImports, err := scanDir(dir, v.Tags)
for _, path := range imports {
xxx
}
for _, path := range testImports {
xxx
}
}
*/
}
writeGoMod()
if len(args) > 0 {
InstallHook(args)
}
}
// Call into "go install". Set by internal/work, which imports us.
var InstallHook func([]string)