-
Notifications
You must be signed in to change notification settings - Fork 49
/
install_cmd.go
109 lines (100 loc) 路 2.79 KB
/
install_cmd.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
package app
import (
"fmt"
"os"
"github.com/pkg/errors"
"github.com/cashapp/hermit"
"github.com/cashapp/hermit/envars"
"github.com/cashapp/hermit/manifest"
"github.com/cashapp/hermit/shell"
"github.com/cashapp/hermit/state"
"github.com/cashapp/hermit/ui"
)
type installCmd struct {
Packages []string `arg:"" optional:"" name:"package" help:"Packages to install (<name>[-<version>]). Version can be a glob to find the latest version with." predictor:"package"`
}
func (i *installCmd) Help() string {
return `
Add the specified set of packages to the environment. If no packages are specified, all existing packages linked
into the environment will be downloaded and installed. Packages will be pinned to the version resolved at install time.
`
}
func (i *installCmd) Run(l *ui.UI, env *hermit.Env, state *state.State) error {
installed, err := env.ListInstalledReferences()
if err != nil {
return errors.WithStack(err)
}
pkgs := map[string]*manifest.Package{}
packages := i.Packages
err = env.Sync(l, false)
if err != nil {
return errors.WithStack(err)
}
if len(packages) == 0 {
// Checking that all the packages are downloaded and unarchived
for _, ref := range installed {
task := l.Task(ref.String())
pkg, err := env.Resolve(l, manifest.ExactSelector(ref), false)
if err != nil {
return errors.WithStack(err)
}
err = state.CacheAndUnpack(task, pkg)
pkg.LogWarnings(l)
task.Done()
if err != nil {
return errors.WithStack(err)
}
}
return nil
}
selectors := make([]manifest.Selector, len(packages))
// Check that we are not installing an already existing package
for i, search := range packages {
selector, err := manifest.GlobSelector(search)
if err != nil {
return errors.WithStack(err)
}
selectors[i] = selector
for _, ref := range installed {
if selector.Matches(ref) {
return errors.Errorf("%s cannot be installed as %s is already installed", selector.String(), ref)
}
}
}
for i, search := range packages {
err := env.ResolveWithDeps(l, installed, selectors[i], pkgs)
if err != nil {
return errors.Wrap(err, search)
}
}
changes := shell.NewChanges(envars.Parse(os.Environ()))
w := l.WriterAt(ui.LevelInfo)
defer w.Sync() // nolint
for _, pkg := range pkgs {
// Skip possible dependencies that have already been installed
exists := false
for _, ref := range installed {
if ref.String() == pkg.Reference.String() {
exists = true
break
}
}
if exists {
continue
}
c, err := env.Install(l, pkg)
if err != nil {
return errors.WithStack(err)
}
messages, err := env.TriggerForPackage(l, manifest.EventInstall, pkg)
if err != nil {
return errors.WithStack(err)
}
for _, message := range messages {
fmt.Fprintln(w, message)
}
changes = changes.Merge(c)
pkg.LogWarnings(l)
}
return nil
}