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
|
package fhelp
import (
"os"
"path/filepath"
"go.wit.com/log"
)
// This defines the "default" behavior for forge when doing GO lang development
//
// Since this code is common, it's in a seperate package so it can be used elsewhere
//
// The default behavior is:
//
// * If your current directory or parent directory has a go.work file, make that your default spot
// * Otherwise, set the default to ~/go/src
//
// This routine ensures the following ENV vars are set:
//
// FORGE_CONFIG == where forge's configs are stored (normally ~/.config/forge)
// FORGE_REPOPB == where the repos.pb protobuf cache file is stored (normally ~/.cache/forge/repos.pb)
// FORGE_GOSRC == based on the path, what the user probably want for developing in GO (Defaults to ~/go/src)
// FORGE_GOWORK == true or false depending on the GOSRC result
//
// returns:
// string # ~/go/src or the path to the go.work file
// bool # true if the user is using a go.work file
// err # if everything goes wrong, the error
//
func ConfigureVerboseENV() error {
err := ConfigureENV()
log.Printf("FORGE_CONFIG = %s\n", os.Getenv("FORGE_CONFIG"))
log.Printf("FORGE_GOSRC = %s\n", os.Getenv("FORGE_GOSRC"))
log.Printf("FORGE_GOWORK = %v\n", os.Getenv("FORGE_GOWORK"))
log.Printf("FORGE_REPOPB = %s\n", os.Getenv("FORGE_REPOPB"))
log.Printf("FORGE_URL = %s\n", os.Getenv("FORGE_URL"))
log.Printf("FORGE_PATCHDIR = %s\n", os.Getenv("FORGE_PATCHDIR"))
log.Printf("HOSTNAME = %s\n", os.Getenv("HOSTNAME"))
return err
}
// set the ENV vars
// always set them to _something_ even when everything seems to be failing
func ConfigureENV() error {
var anyerr error
// setup the forge config dir
if os.Getenv("FORGE_CONFIG") == "" {
homeDir, err := os.UserHomeDir()
if err == nil {
fullpath := filepath.Join(homeDir, ".config/forge")
os.MkdirAll(fullpath, os.ModePerm)
os.Setenv("FORGE_CONFIG", fullpath)
} else {
log.Info("user home dir error", err)
os.Setenv("FORGE_CONFIG", "/tmp")
anyerr = err
}
}
// setting FORGE_URL
if os.Getenv("FORGE_URL") == "" {
os.Setenv("FORGE_URL", "https://forge.wit.com/")
}
// hostname is needed. allow ENV to pass it in
if os.Getenv("HOSTNAME") == "" {
if hname, err := os.Hostname(); err == nil {
os.Setenv("HOSTNAME", hname)
} else {
os.Setenv("HOSTNAME", "unconfigured.hostname.forge")
}
}
// if this env is already set, just use what is there
if os.Getenv("FORGE_GOSRC") != "" {
// always use this ENV if it is set
os.Setenv("FORGE_REPOPB", os.Getenv("FORGE_GOSRC")) // store repos.pb in the same dir
if goWorkExists(os.Getenv("FORGE_GOSRC")) {
os.Setenv("FORGE_GOWORK", "true")
}
if os.Getenv("FORGE_PATCHDIR") == "" {
os.Setenv("FORGE_PATCHDIR", os.Getenv("FORGE_GOSRC"))
}
return anyerr
}
// if a go.work file is found, use that location
if gowork, ok := findGoWork(); ok {
os.Setenv("FORGE_GOSRC", gowork)
if os.Getenv("FORGE_GOSRC") == "" {
// everything went wrong. use /tmp maybe ?
os.Setenv("FORGE_GOSRC", "/tmp")
}
os.Setenv("FORGE_REPOPB", os.Getenv("FORGE_GOSRC")) // store repos.pb in the same dir
os.Setenv("FORGE_GOWORK", "true")
if os.Getenv("FORGE_PATCHDIR") == "" {
os.Setenv("FORGE_PATCHDIR", os.Getenv("FORGE_GOSRC"))
}
return anyerr
} else {
// log.Info("fhelp.findGoWork() didn't find a go.work file")
}
// there are no go.work files, use the default ~/go/src behavior
if gosrc, err := useGoSrc(); err == nil {
os.Setenv("FORGE_GOSRC", gosrc)
os.Unsetenv("FORGE_GOWORK")
}
// set to user home dir unless this is already set
if os.Getenv("FORGE_REPOPB") == "" {
homeDir, err := os.UserHomeDir()
if err == nil {
fullpath := filepath.Join(homeDir, ".cache/forge")
if err := os.MkdirAll(fullpath, os.ModePerm); err == nil {
os.Setenv("FORGE_REPOPB", fullpath)
} else {
log.Warn("mkdir failed", fullpath, err)
os.Setenv("FORGE_REPOPB", os.Getenv("FORGE_GOSRC")) // store repos.pb in the same dir
anyerr = err
}
} else {
log.Info("user home dir error", err)
os.Setenv("FORGE_REPOPB", "/tmp")
anyerr = err
}
}
if os.Getenv("FORGE_PATCHDIR") == "" {
os.Setenv("FORGE_PATCHDIR", os.Getenv("FORGE_REPOPB"))
}
return anyerr
}
// this is the 'old way" and works fine for me. I use it because I like the ~/go/src directory
// because I know exactly what is in it: GO stuff & nothing else
func useGoSrc() (string, error) {
homeDir, err := os.UserHomeDir()
if err != nil {
return "", err
}
pwd := filepath.Join(homeDir, "go/src")
err = os.MkdirAll(pwd, os.ModePerm)
return pwd, err
}
func goWorkExists(dir string) bool {
var err error
workFilePath := filepath.Join(dir, "go.work")
if _, err = os.Stat(workFilePath); err == nil {
// log.Info("f.goWorkExists() found", workFilePath)
return true
} else if !os.IsNotExist(err) {
// log.Info("f.goWorkExists() missing", workFilePath)
return false
}
// probably false, but some other error
// log.Info("f.goWorkExists() os.Stat() error", err, workFilePath)
return false
}
// findGoWork searches for a "go.work" file starting from the current directory
// and moving up the directory tree. It returns the path to the directory containing
// the file and a boolean indicating whether the file was found.
func findGoWork() (string, bool) {
dir, err := os.Getwd()
if err != nil {
return "", false
}
for {
workFilePath := filepath.Join(dir, "go.work")
if _, err := os.Stat(workFilePath); err == nil {
return dir, true
}
parent := filepath.Dir(dir)
if parent == dir {
break // Reached root
}
dir = parent
}
return "", false
}
|