github.com/goguardian/glide@v0.0.0-20160311175917-84255172e124/action/get.go (about) 1 package action 2 3 import ( 4 "fmt" 5 "path/filepath" 6 "strings" 7 8 "github.com/Masterminds/glide/cfg" 9 "github.com/Masterminds/glide/msg" 10 gpath "github.com/Masterminds/glide/path" 11 "github.com/Masterminds/glide/repo" 12 "github.com/Masterminds/glide/util" 13 ) 14 15 // Get fetches one or more dependencies and installs. 16 // 17 // This includes resolving dependency resolution and re-generating the lock file. 18 func Get(names []string, installer *repo.Installer, insecure, skipRecursive bool) { 19 base := gpath.Basepath() 20 EnsureGopath() 21 EnsureVendorDir() 22 conf := EnsureConfig() 23 glidefile, err := gpath.Glide() 24 if err != nil { 25 msg.Die("Could not find Glide file: %s", err) 26 } 27 28 // Add the packages to the config. 29 if count, err := addPkgsToConfig(conf, names, insecure); err != nil { 30 msg.Die("Failed to get new packages: %s", err) 31 } else if count == 0 { 32 msg.Warn("Nothing to do") 33 return 34 } 35 36 // Fetch the new packages. Can't resolve versions via installer.Update if 37 // get is called while the vendor/ directory is empty so we checkout 38 // everything. 39 installer.Checkout(conf, false) 40 41 // Prior to resolving dependencies we need to start working with a clone 42 // of the conf because we'll be making real changes to it. 43 confcopy := conf.Clone() 44 45 if !skipRecursive { 46 // Get all repos and update them. 47 // TODO: Can we streamline this in any way? The reason that we update all 48 // of the dependencies is that we need to re-negotiate versions. For example, 49 // if an existing dependency has the constraint >1.0 and this new package 50 // adds the constraint <2.0, then this may re-resolve the existing dependency 51 // to be between 1.0 and 2.0. But changing that dependency may then result 52 // in that dependency's dependencies changing... so we sorta do the whole 53 // thing to be safe. 54 err = installer.Update(confcopy) 55 if err != nil { 56 msg.Die("Could not update packages: %s", err) 57 } 58 } 59 60 // Set Reference 61 if err := repo.SetReference(confcopy); err != nil { 62 msg.Err("Failed to set references: %s", err) 63 } 64 65 // VendoredCleanup 66 if installer.UpdateVendored { 67 repo.VendoredCleanup(confcopy) 68 } 69 70 // Write YAML 71 if err := conf.WriteFile(glidefile); err != nil { 72 msg.Die("Failed to write glide YAML file: %s", err) 73 } 74 if !skipRecursive { 75 // Write lock 76 writeLock(conf, confcopy, base) 77 } else { 78 msg.Warn("Skipping lockfile generation because full dependency tree is not being calculated") 79 } 80 } 81 82 func writeLock(conf, confcopy *cfg.Config, base string) { 83 hash, err := conf.Hash() 84 if err != nil { 85 msg.Die("Failed to generate config hash. Unable to generate lock file.") 86 } 87 lock := cfg.NewLockfile(confcopy.Imports, hash) 88 if err := lock.WriteFile(filepath.Join(base, gpath.LockFile)); err != nil { 89 msg.Die("Failed to write glide lock file: %s", err) 90 } 91 } 92 93 // addPkgsToConfig adds the given packages to the config file. 94 // 95 // Along the way it: 96 // - ensures that this package is not in the ignore list 97 // - checks to see if this is already in the dependency list. 98 // - splits version of of package name and adds the version attribute 99 // - separates repo from packages 100 // - sets up insecure repo URLs where necessary 101 // - generates a list of subpackages 102 func addPkgsToConfig(conf *cfg.Config, names []string, insecure bool) (int, error) { 103 104 msg.Info("Preparing to install %d package.", len(names)) 105 106 numAdded := 0 107 for _, name := range names { 108 var version string 109 parts := strings.Split(name, "#") 110 if len(parts) > 1 { 111 name = parts[0] 112 version = parts[1] 113 } 114 115 root, subpkg := util.NormalizeName(name) 116 if len(root) == 0 { 117 return 0, fmt.Errorf("Package name is required for %q.", name) 118 } 119 120 if conf.HasDependency(root) { 121 122 // Check if the subpackage is present. 123 if subpkg != "" { 124 dep := conf.Imports.Get(root) 125 if dep.HasSubpackage(subpkg) { 126 msg.Warn("Package %q is already in glide.yaml. Skipping", name) 127 } else { 128 dep.Subpackages = append(dep.Subpackages, subpkg) 129 msg.Info("Adding sub-package %s to existing import %s", subpkg, root) 130 numAdded++ 131 } 132 } else { 133 msg.Warn("Package %q is already in glide.yaml. Skipping", root) 134 } 135 continue 136 } 137 138 if conf.HasIgnore(root) { 139 msg.Warn("Package %q is set to be ignored in glide.yaml. Skipping", root) 140 continue 141 } 142 143 dep := &cfg.Dependency{ 144 Name: root, 145 } 146 147 if version != "" { 148 dep.Reference = version 149 } 150 151 // When retriving from an insecure location set the repo to the 152 // insecure location. 153 if insecure { 154 dep.Repository = "http://" + root 155 } 156 157 if len(subpkg) > 0 { 158 dep.Subpackages = []string{subpkg} 159 } 160 161 if dep.Reference != "" { 162 msg.Info("Importing %s with the version %s", dep.Name, dep.Reference) 163 } else { 164 msg.Info("Importing %s", dep.Name) 165 } 166 167 conf.Imports = append(conf.Imports, dep) 168 numAdded++ 169 } 170 return numAdded, nil 171 }