-
Notifications
You must be signed in to change notification settings - Fork 203
/
filesystem.go
144 lines (115 loc) · 3.33 KB
/
filesystem.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
package client
import (
"bytes"
"encoding/json"
"fmt"
"io/ioutil"
"path/filepath"
"get.porter.sh/porter/pkg/config"
"get.porter.sh/porter/pkg/context"
"get.porter.sh/porter/pkg/pkgmgmt"
"github.com/pkg/errors"
)
var _ pkgmgmt.PackageManager = &FileSystem{}
type PackageMetadataBuilder func() pkgmgmt.PackageMetadata
func NewFileSystem(config *config.Config, pkgType string) *FileSystem {
return &FileSystem{
Config: config,
PackageType: pkgType,
BuildMetadata: func() pkgmgmt.PackageMetadata { return pkgmgmt.Metadata{} },
}
}
type FileSystem struct {
*config.Config
// PackageType is the type of package managed by this instance of the
// package manager. It must also correspond to the directory name in
// PORTER_HOME.
PackageType string
// PreRun is executed before commands are run against a package, giving
// consumers a chance to tweak the command first.
PreRun pkgmgmt.PreRunHandler
// BuildMetadata allows mixins/plugins to supply the proper struct that
// represents its package metadata.
BuildMetadata PackageMetadataBuilder
}
func (fs *FileSystem) List() ([]string, error) {
parentDir, err := fs.GetPackagesDir()
files, err := fs.FileSystem.ReadDir(parentDir)
if err != nil {
return nil, errors.Wrapf(err, "could not list the contents of the %s directory %q", fs.PackageType, parentDir)
}
names := make([]string, 0, len(files))
for _, file := range files {
if !file.IsDir() {
continue
}
names = append(names, file.Name())
}
return names, nil
}
func (fs *FileSystem) GetMetadata(name string) (pkgmgmt.PackageMetadata, error) {
pkgDir, err := fs.GetPackageDir(name)
if err != nil {
return nil, err
}
r := NewRunner(name, pkgDir, false)
// Copy the existing context and tweak to pipe the output differently
jsonB := &bytes.Buffer{}
var pkgContext context.Context
pkgContext = *fs.Context
pkgContext.Out = jsonB
if !fs.Debug {
pkgContext.Err = ioutil.Discard
}
r.Context = &pkgContext
cmd := pkgmgmt.CommandOptions{Command: "version --output json", PreRun: fs.PreRun}
err = r.Run(cmd)
if err != nil {
return nil, err
}
result := fs.BuildMetadata()
err = json.Unmarshal(jsonB.Bytes(), &result)
if err != nil {
return nil, err
}
return result, nil
}
func (fs *FileSystem) Run(pkgContext *context.Context, name string, commandOpts pkgmgmt.CommandOptions) error {
pkgDir, err := fs.GetPackageDir(name)
if err != nil {
return err
}
r := NewRunner(name, pkgDir, commandOpts.Runtime)
r.Context = pkgContext
err = r.Validate()
if err != nil {
return err
}
commandOpts.PreRun = fs.PreRun
return r.Run(commandOpts)
}
func (fs *FileSystem) GetPackagesDir() (string, error) {
home, err := fs.GetHomeDir()
if err != nil {
return "", err
}
return filepath.Join(home, fs.PackageType), nil
}
func (fs *FileSystem) GetPackageDir(name string) (string, error) {
parentDir, err := fs.GetPackagesDir()
if err != nil {
return "", err
}
pkgDir := filepath.Join(parentDir, name)
dirExists, err := fs.FileSystem.DirExists(pkgDir)
if err != nil {
return "", errors.Wrapf(err, "%s %s not accessible at %s", fs.PackageType, name, pkgDir)
}
if !dirExists {
return "", fmt.Errorf("%s %s not installed", fs.PackageType, name)
}
return pkgDir, nil
}
func (fs *FileSystem) BuildClientPath(pkgDir string, name string) string {
return filepath.Join(pkgDir, name) + pkgmgmt.FileExt
}