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