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