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