-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathdiscover.go
More file actions
60 lines (52 loc) · 1.71 KB
/
Copy pathdiscover.go
File metadata and controls
60 lines (52 loc) · 1.71 KB
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
package config
import (
"fmt"
"os"
"path/filepath"
)
// WorkspaceFile is the marker filename that identifies a workspace root.
const WorkspaceFile = "workspace.yaml"
// ProjectFile is the per-repo project config filename.
const ProjectFile = "devstack.yaml"
// envWorkspace overrides discovery with an explicit workspace root.
const envWorkspace = "DEVSTACK_WORKSPACE"
// Discover finds the workspace root by walking up from start (git/go.mod style)
// until it finds a workspace.yaml, stopping at the filesystem root or $HOME
// (whichever comes first). The DEVSTACK_WORKSPACE env var, when set to a
// directory containing workspace.yaml, short-circuits the walk. Returns the
// absolute directory containing workspace.yaml.
func Discover(start string) (string, error) {
if env := os.Getenv(envWorkspace); env != "" {
dir, err := filepath.Abs(env)
if err != nil {
return "", fmt.Errorf("%s=%q: %w", envWorkspace, env, err)
}
if !fileExists(filepath.Join(dir, WorkspaceFile)) {
return "", fmt.Errorf("%s=%q does not contain %s", envWorkspace, dir, WorkspaceFile)
}
return dir, nil
}
dir, err := filepath.Abs(start)
if err != nil {
return "", fmt.Errorf("resolve start dir %q: %w", start, err)
}
home, _ := os.UserHomeDir()
for {
if fileExists(filepath.Join(dir, WorkspaceFile)) {
return dir, nil
}
if home != "" && dir == home {
break // do not walk above the user's home
}
parent := filepath.Dir(dir)
if parent == dir {
break // filesystem root
}
dir = parent
}
return "", fmt.Errorf("no %s found in %q or any parent directory (is this a devstack workspace?)", WorkspaceFile, start)
}
func fileExists(path string) bool {
info, err := os.Stat(path)
return err == nil && !info.IsDir()
}