blob: 49164580bab0529c4ff014080e0dbf7ce6ae3132 [file] [log] [blame] [edit]
package cmd
import (
"io/ioutil"
"os"
"path"
"github.com/Masterminds/cookoo"
"github.com/kylelemons/go-gypsy/yaml"
)
// Recurse does glide installs on dependent packages.
// Recurse looks in all known packages for a glide.yaml files and installs for
// each one it finds.
func Recurse(c cookoo.Context, p *cookoo.Params) (interface{}, cookoo.Interrupt) {
if !p.Get("enable", true).(bool) {
return nil, nil
}
force := p.Get("force", true).(bool)
godeps, gpm := false, false
if g, ok := p.Has("importGodeps"); ok {
godeps = g.(bool)
}
if g, ok := p.Has("importGPM"); ok {
gpm = g.(bool)
}
Info("Checking dependencies for updates. Godeps: %v, GPM: %v\n", godeps, gpm)
conf := p.Get("conf", &Config{}).(*Config)
vend, _ := VendorPath(c)
return recDepResolve(conf, vend, godeps, gpm, force)
}
func recDepResolve(conf *Config, vend string, godeps, gpm, force bool) (interface{}, error) {
Info("Inspecting %s.\n", vend)
if len(conf.Imports) == 0 {
Info("No imports.\n")
}
// Look in each package to see whether it has a glide.yaml, and no vendor/
for _, imp := range conf.Imports {
base := path.Join(vend, imp.Name)
Info("Looking in %s for a glide.yaml file.\n", base)
if !needsGlideUp(base) {
if godeps {
importGodep(base, imp.Name)
}
if gpm {
importGPM(base, imp.Name)
}
if !needsGlideUp(base) {
Info("Package %s manages its own dependencies.\n", imp.Name)
continue
}
}
if err := dependencyGlideUp(base, godeps, gpm, force); err != nil {
Warn("Failed to update dependency %s: %s", imp.Name, err)
}
}
// Run `glide up`
return nil, nil
}
func dependencyGlideUp(base string, godep, gpm, force bool) error {
//conf := new(Config)
fname := path.Join(base, "glide.yaml")
f, err := yaml.ReadFile(fname)
if err != nil {
return err
}
conf, err := FromYaml(f.Root)
if err != nil {
return err
}
for _, imp := range conf.Imports {
// We don't use the global var to find vendor dir name because the
// user may mis-use that var to modify the local vendor dir, and
// we don't want that to break the embedded vendor dirs.
wd := path.Join(base, "vendor", imp.Name)
vdir := path.Join(base, "vendor")
if err := ensureDir(wd); err != nil {
Warn("Skipped getting %s (vendor/ error): %s\n", imp.Name, err)
continue
}
if VcsExists(imp, wd) {
Info("Updating project %s (%s)\n", imp.Name, wd)
if err := VcsUpdate(imp, vdir, force); err != nil {
// We can still go on just fine even if this fails.
Warn("Skipped update %s: %s\n", imp.Name, err)
continue
}
} else {
Info("Importing %s to project %s\n", imp.Name, base)
if err := VcsGet(imp, wd); err != nil {
Warn("Skipped getting %s: %v\n", imp.Name, err)
continue
}
}
// If a revision has been set use it.
err = VcsVersion(imp, vdir)
if err != nil {
Warn("Problem setting version on %s: %s\n", imp.Name, err)
}
//recDepResolve(conf, path.Join(wd, "vendor"))
}
recDepResolve(conf, path.Join(base, "vendor"), godep, gpm, force)
return nil
}
func ensureDir(dirpath string) error {
if fi, err := os.Stat(dirpath); err == nil && fi.IsDir() {
return nil
}
return os.MkdirAll(dirpath, 0755)
}
func needsGlideUp(dir string) bool {
stat, err := os.Stat(path.Join(dir, "glide.yaml"))
if err != nil || stat.IsDir() {
return false
}
// Should probably see if vendor is there and non-empty.
return true
}
func importGodep(dir, pkg string) error {
Info("Looking in %s/Godeps/ for a Godeps.json file.\n", dir)
d, err := parseGodepGodeps(dir)
if err != nil {
Warn("Looking for Godeps: %s\n", err)
return err
}
return quickDirtyYAMLWrite(dir, d, pkg)
}
func importGPM(dir, pkg string) error {
d, err := parseGPMGodeps(dir)
if err != nil {
return err
}
return quickDirtyYAMLWrite(dir, d, pkg)
}
func quickDirtyYAMLWrite(dir string, d []*Dependency, pkg string) error {
if len(d) == 0 {
return nil
}
c := &Config{Name: pkg, Imports: d}
node := c.ToYaml()
data := yaml.Render(node)
f := path.Join(dir, "glide.yaml")
Info("Writing new glide.yaml file in %s\n", dir)
return ioutil.WriteFile(f, []byte(data), 0755)
}