Skip to content

Commit fa0521c

Browse files
author
Horacio Duran
committed
Refactored use of paths.
1 parent 73992e7 commit fa0521c

File tree

8 files changed

+217
-113
lines changed

8 files changed

+217
-113
lines changed

actions/actions.go

Lines changed: 81 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -3,18 +3,50 @@ package actions
33
import (
44
"os"
55
"path/filepath"
6+
"regexp"
67
"strings"
78

89
"github.com/perrito666/goworkon/environment"
910
"github.com/perrito666/goworkon/goinstalls"
1011
"github.com/perrito666/goworkon/goswitch"
12+
"github.com/perrito666/goworkon/paths"
1113
"github.com/pkg/errors"
1214
)
1315

14-
func configGet(basePath, name string) (environment.Config, error) {
16+
func globalBins() ([]string, error) {
17+
basePath, err := paths.XdgDataConfig()
18+
if err != nil {
19+
return nil, errors.Wrap(err, "retrieving config files")
20+
}
1521
cfgs, err := environment.LoadConfig(basePath)
1622
if err != nil {
17-
return environment.Config{}, errors.WithStack(err)
23+
return nil, errors.Wrap(err, "loading configs")
24+
}
25+
globalBin := []string{}
26+
for _, cfg := range cfgs {
27+
if cfg.GlobalBin {
28+
globalBin = append(globalBin, paths.GoPathBin(cfg.GoPath))
29+
}
30+
}
31+
return globalBin, nil
32+
33+
}
34+
35+
var notFoundRe = regexp.MustCompile("evironment .* not found")
36+
37+
func isNotFound(err error) bool {
38+
err = errors.Cause(err)
39+
return notFoundRe.MatchString(err.Error())
40+
}
41+
42+
func configGet(name string) (environment.Config, error) {
43+
basePath, err := paths.XdgDataConfig()
44+
if err != nil {
45+
return environment.Config{}, errors.Wrapf(err, "retrieving config for %q", name)
46+
}
47+
cfgs, err := environment.LoadConfig(basePath)
48+
if err != nil {
49+
return environment.Config{}, errors.Wrapf(err, "loading config for %q", name)
1850
}
1951
env, ok := cfgs[name]
2052
if !ok {
@@ -25,46 +57,52 @@ func configGet(basePath, name string) (environment.Config, error) {
2557

2658
// Switch changes the environment to the specified one
2759
// if it exists, otherwise its a noop and returns error.
28-
func Switch(basePath, installName string) error {
29-
cfgs, err := environment.LoadConfig(basePath)
60+
func Switch(installName string) error {
61+
basePath, err := paths.XdgData()
3062
if err != nil {
31-
return errors.WithStack(err)
63+
return errors.Wrapf(err, "retrieving config for %q", installName)
3264
}
33-
env, err := configGet(basePath, installName)
65+
66+
env, err := configGet(installName)
3467
if err != nil {
35-
return errors.WithStack(err)
68+
return errors.Wrapf(err, "loading config to switch to %q", installName)
3669
}
3770

3871
settings, err := environment.LoadSettings(basePath)
3972
if err != nil {
40-
return errors.Wrap(err, "loading settings")
73+
return errors.Wrapf(err, "loading settings to switch to %q", installName)
4174
}
4275

43-
extraBins := []string{}
44-
for _, cfg := range cfgs {
45-
if cfg.GlobalBin {
46-
extraBins = append(extraBins, filepath.Join(cfg.GoPath, "bin"))
47-
}
76+
extraBins, err := globalBins()
77+
if err != nil {
78+
return errors.Wrap(err, "determining global bin paths")
4879
}
49-
goswitch.Switch(basePath, env, installName == settings.Default, extraBins)
50-
51-
return nil
80+
return errors.Wrapf(goswitch.Switch(env, installName == settings.Default, extraBins),
81+
"switching to environment %q", installName)
5282
}
5383

5484
// Reset will try toreturn the env to its original state.
5585
func Reset() error {
5686
return goswitch.Reset()
5787
}
5888

59-
func ensureVersionInstalled(goVersion, basePath, goroot string) (goinstalls.Version, error) {
60-
installFolder := filepath.Join(basePath, "installs")
61-
goFolder := filepath.Join(installFolder, goVersion)
89+
func ensureVersionInstalled(goVersion, goroot string) (goinstalls.Version, error) {
90+
goFolder, err := paths.XdgDataGoInstallsBinForVerson(goVersion)
91+
if err != nil {
92+
return goinstalls.Version{}, errors.Wrapf(err, "determining if %q exists", goVersion)
93+
}
94+
// if the bin folder is not there, the version is not properly
95+
// installed.
6296
if _, err := os.Stat(goFolder); err == nil {
6397
return goinstalls.VersionFromString(goVersion)
6498
}
6599
versions, err := goinstalls.OnlineAvailableVersions()
66100
if err != nil {
67-
return goinstalls.Version{}, errors.WithStack(err)
101+
return goinstalls.Version{}, errors.Wrap(err, "retrieving available online versions")
102+
}
103+
installFolder, err := paths.XdgDataGoInstalls()
104+
if err != nil {
105+
return goinstalls.Version{}, errors.Wrapf(err, "determining go installs folder to install %q", goVersion)
68106
}
69107
for k, v := range versions {
70108
if k.CommonVersionString() == goVersion {
@@ -73,7 +111,7 @@ func ensureVersionInstalled(goVersion, basePath, goroot string) (goinstalls.Vers
73111
return k, nil
74112
}
75113
err = goinstalls.InstallVersion(k, v, installFolder, goroot)
76-
return k, errors.WithStack(err)
114+
return k, errors.Wrapf(err, "installing go %q", goVersion)
77115
}
78116
}
79117
return goinstalls.Version{}, errors.Errorf("go version %q not found", goVersion)
@@ -83,25 +121,26 @@ func ensureVersionInstalled(goVersion, basePath, goroot string) (goinstalls.Vers
83121
// Create creates the an environment with the passed name
84122
// in the passed go version, if it exists its a noop and
85123
// returns an error.
86-
func Create(installName, goVersion, basePath, goPath string, settings environment.Settings) error {
87-
cfgs, err := environment.LoadConfig(basePath)
88-
if err != nil {
89-
return errors.WithStack(err)
90-
}
91-
if _, ok := cfgs[installName]; ok {
92-
return nil
124+
func Create(installName, goVersion, goPath string, settings environment.Settings) error {
125+
_, err := configGet(installName)
126+
if err != nil && !isNotFound(err) {
127+
return errors.Wrapf(err, "determining if environment %q exists", installName)
93128
}
94-
v, err := ensureVersionInstalled(goVersion, basePath, settings.Goroot)
129+
v, err := ensureVersionInstalled(goVersion, settings.Goroot)
95130
if err != nil {
96-
return errors.WithStack(err)
131+
return errors.Wrapf(err, "installing go %q to create %q environment", goVersion, installName)
97132
}
98133
c := environment.Config{
99134
Name: installName,
100135
GoVersion: v.String(),
101136
GoPath: goPath,
102137
}
103-
if err := c.Save(basePath); err != nil {
104-
return errors.WithStack(err)
138+
configPath, err := paths.XdgDataConfig()
139+
if err != nil {
140+
return errors.Wrapf(err, "getting config folder to save %q config", installName)
141+
}
142+
if err := c.Save(configPath); err != nil {
143+
return errors.Wrapf(err, "saving %q config", installName)
105144
}
106145
return nil
107146
}
@@ -119,25 +158,29 @@ func extractEnvironment(attribute string) (string, string, error) {
119158
}
120159

121160
// Set sets <attribute> to <value> in the correct setting or returns an error.
122-
func Set(attribute, value, baseFolder string) error {
161+
func Set(attribute, value string) error {
123162
environmentName, attribute, err := extractEnvironment(attribute)
124163
if err != nil {
125164
return errors.Errorf("setting %q to %q", attribute, value)
126165
}
127166
if environmentName != "" {
128-
cfg, err := configGet(baseFolder, environmentName)
167+
cfg, err := configGet(environmentName)
129168
if err != nil {
130-
return errors.WithStack(err)
169+
return errors.Wrapf(err, "finding config for %q", environmentName)
131170
}
132-
return errors.Wrapf(cfg.Set(attribute, value, baseFolder), "stting %q to %q", attribute, value)
171+
return errors.Wrapf(cfg.Set(attribute, value), "setting %q to %q", attribute, value)
133172

134173
return errors.New("setting environment attributes is not implemented")
135174
}
136175

137-
settings, err := environment.LoadSettings(baseFolder)
176+
settingsFolder, err := paths.XdgData()
177+
if err != nil {
178+
return errors.Wrapf(err, "determining settings folder to set %q", attribute)
179+
}
180+
settings, err := environment.LoadSettings(settingsFolder)
138181
if err != nil {
139182
return errors.Wrap(err, "loading settings")
140183
}
141184

142-
return errors.Wrapf(settings.Set(attribute, value, baseFolder), "setting %q to %q", attribute, value)
185+
return errors.Wrapf(settings.Set(attribute, value), "setting %q to %q", attribute, value)
143186
}

commands.go

Lines changed: 3 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -47,11 +47,7 @@ func (c Create) Validate() error {
4747

4848
// Run implements Command.
4949
func (c Create) Run() error {
50-
installFolder, err := xdgData()
51-
if err != nil {
52-
return errors.WithStack(err)
53-
}
54-
err = actions.Create(c.environmentName, c.goVersion, installFolder, c.goPath, c.settings)
50+
err := actions.Create(c.environmentName, c.goVersion, c.goPath, c.settings)
5551
if err != nil {
5652
return errors.WithStack(err)
5753
}
@@ -78,14 +74,10 @@ func (s Switch) Validate() error {
7874

7975
// Run implements Command.
8076
func (s Switch) Run() error {
81-
installFolder, err := xdgData()
82-
if err != nil {
83-
return errors.WithStack(err)
84-
}
8577
if s.environmentName == "" {
8678
return actions.Reset()
8779
}
88-
err = actions.Switch(installFolder, s.environmentName)
80+
err := actions.Switch(s.environmentName)
8981
if err != nil {
9082
return errors.WithStack(err)
9183
}
@@ -149,10 +141,5 @@ func (s Set) Validate() error {
149141

150142
// Run implements Command.
151143
func (s Set) Run() error {
152-
dataDir, err := xdgData()
153-
if err != nil {
154-
return errors.Wrap(err, "getting xdg data dir for \"Set\" command")
155-
}
156-
157-
return errors.WithStack(actions.Set(s.attribute, s.value, dataDir))
144+
return errors.WithStack(actions.Set(s.attribute, s.value))
158145
}

environment/config.go

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,9 @@ type Config struct {
2929
GlobalBin bool `json:"globalbin"`
3030
// GoPath
3131
GoPath string `json:"gopath"`
32+
33+
// filePath holds the path for this config file.
34+
filePath string
3235
}
3336

3437
func maybeEnsureFolderExists(folder string) error {
@@ -52,7 +55,6 @@ func maybeEnsureFolderExists(folder string) error {
5255
// Save serializes and writes the Config in a file in the
5356
// passed folder.
5457
func (c *Config) Save(baseFolder string) error {
55-
baseFolder = filepath.Join(baseFolder, "configs")
5658
if err := maybeEnsureFolderExists(baseFolder); err != nil {
5759
return errors.WithStack(err)
5860
}
@@ -75,7 +77,6 @@ func (c *Config) Save(baseFolder string) error {
7577

7678
// LoadConfig will load Config files in the given location
7779
func LoadConfig(baseFolder string) (map[string]Config, error) {
78-
baseFolder = filepath.Join(baseFolder, "configs")
7980
if err := maybeEnsureFolderExists(baseFolder); err != nil {
8081
return nil, errors.WithStack(err)
8182
}
@@ -94,6 +95,7 @@ func LoadConfig(baseFolder string) (map[string]Config, error) {
9495
if err = json.Unmarshal(contents, &c); err != nil {
9596
return errors.WithStack(err)
9697
}
98+
c.filePath = baseFolder
9799
allConfigs[c.Name] = c
98100
return nil
99101
}()
@@ -106,7 +108,11 @@ func LoadConfig(baseFolder string) (map[string]Config, error) {
106108

107109
// Set will set the value of <attribute> to <value> if attribute is a valid
108110
// member of Config.
109-
func (c Config) Set(attribute, value, baseFolder string) error {
111+
func (c Config) Set(attribute, value string) error {
112+
if c.filePath == "" {
113+
return errors.New("this config neds to be saved before Set can be used.")
114+
}
115+
110116
switch strings.ToLower(attribute) {
111117
case "globalbin":
112118
if strings.ToLower(value) == "true" {
@@ -119,5 +125,5 @@ func (c Config) Set(attribute, value, baseFolder string) error {
119125
default:
120126
return errors.Errorf("%q is not a valid setting", attribute)
121127
}
122-
return errors.WithStack(c.Save(baseFolder))
128+
return errors.WithStack(c.Save(c.filePath))
123129
}

environment/settings.go

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,9 @@ type Settings struct {
1919
// Default is the default environment to set, this will behave
2020
// a bit differently since its for general use.
2121
Default string `json:"default"`
22+
23+
// filePath holds the path for this settings file.
24+
filePath string
2225
}
2326

2427
// Save serializes and writes the Settings in a file in the
@@ -46,7 +49,11 @@ func (s Settings) Save(baseFolder string) error {
4649

4750
// Set will set the value of <attribute> to <value> if attribute is a valid
4851
// member of Settings.
49-
func (s Settings) Set(attribute, value, baseFolder string) error {
52+
func (s Settings) Set(attribute, value string) error {
53+
if s.filePath == "" {
54+
return errors.New("these settings neds to be saved before Set can be used")
55+
}
56+
5057
switch strings.ToLower(attribute) {
5158
case "goroot":
5259
s.Goroot = value
@@ -55,7 +62,7 @@ func (s Settings) Set(attribute, value, baseFolder string) error {
5562
default:
5663
return errors.Errorf("%q is not a valid setting", attribute)
5764
}
58-
return errors.WithStack(s.Save(baseFolder))
65+
return errors.WithStack(s.Save(s.filePath))
5966
}
6067

6168
// LoadSettings will load Settings files in the given location
@@ -78,5 +85,6 @@ func LoadSettings(baseFolder string) (Settings, error) {
7885
if err := json.Unmarshal(contents, &s); err != nil {
7986
return Settings{}, errors.WithStack(err)
8087
}
88+
s.filePath = baseFolder
8189
return s, nil
8290
}

goswitch/goswitch.go

Lines changed: 8 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,11 @@ package goswitch
33
import (
44
"fmt"
55
"os"
6-
"path/filepath"
76
"strings"
87

98
"github.com/perrito666/goworkon/environment"
9+
"github.com/perrito666/goworkon/paths"
10+
"github.com/pkg/errors"
1011
)
1112

1213
const (
@@ -30,7 +31,7 @@ func setenv(varName, varValue string) string {
3031

3132
// Switch will set the proper environment variables to set an environment
3233
// as the current running one.
33-
func Switch(basePath string, cfg environment.Config, isDefault bool, extraBin []string) error {
34+
func Switch(cfg environment.Config, isDefault bool, extraBin []string) error {
3435
pgopath := os.Getenv(PREVGOPATH)
3536
ppath := os.Getenv(PREVPATH)
3637
pps1 := os.Getenv(PREVPS1)
@@ -41,27 +42,22 @@ func Switch(basePath string, cfg environment.Config, isDefault bool, extraBin []
4142
if pgopath == "" && !isDefault {
4243
envVars = append(envVars, setenv(PREVGOPATH, gopath))
4344
}
44-
envVars = append(envVars, setenv(GOPATH, cfg.GoPath))
4545
if ppath == "" && !isDefault {
4646
envVars = append(envVars, setenv(PREVPATH, path))
4747
}
4848
if pps1 == "" && !isDefault {
4949
envVars = append(envVars, setenv(PREVPS1, fmt.Sprintf("\"%s\"", ps1)))
5050
}
51-
// TODO(perrito) go throught the environment and remove the path section
52-
// that holds the current go install.
53-
// Also threat default as a special cookie and make it leave no trace.
5451
envVars = append(envVars, setenv(GOPATH, cfg.GoPath))
5552
if len(extraBin) > 0 {
5653
extraBin = append(extraBin, path)
5754
path = strings.Join(extraBin, ":")
5855
}
59-
newPath := strings.Join([]string{filepath.Join(cfg.GoPath, "bin"),
60-
// TODO(perrito) this implies heavy out of band knowledge, lets
61-
// store these things somewhere instead or build a unique source
62-
// of truth for paths.
63-
filepath.Join(basePath,"installs", cfg.GoVersion, "go", "bin"),
64-
path}, ":")
56+
goInstallsPath, err := paths.XdgDataGoInstallsBinForVerson(cfg.GoVersion)
57+
if err != nil {
58+
return errors.Wrapf(err, "trying to determine go installs path to switch to %q", cfg.Name)
59+
}
60+
newPath := paths.PATHInsert(path, paths.GoPathBin(cfg.GoPath), goInstallsPath)
6561
envVars = append(envVars, setenv(PATH, newPath))
6662
// Default env will
6763
if !isDefault {

0 commit comments

Comments
 (0)