Skip to content

Commit 2118019

Browse files
authored
[pkg-config] Add bin sym links and add to path (#257)
## Summary This PR does two things: * Adds `.devbox/conf/bin` to path * Creates sym links for any files in `.devbox/conf/[pkg]/bin` ## How was it tested? Using dummy package config
1 parent 944ff28 commit 2118019

File tree

6 files changed

+100
-38
lines changed

6 files changed

+100
-38
lines changed

devbox.go

+5-1
Original file line numberDiff line numberDiff line change
@@ -240,7 +240,11 @@ func (d *Devbox) Shell() error {
240240
if err != nil {
241241
return err
242242
}
243-
opts = append(opts, nix.WithEnvVariables(env))
243+
opts = append(
244+
opts,
245+
nix.WithEnvVariables(env),
246+
nix.WithPKGCOnfigDir(filepath.Join(d.srcDir, ".devbox/conf/bin")),
247+
)
244248
}
245249

246250
shell, err := nix.DetectShell(opts...)

nix/shell.go

+14-2
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ const (
3737
type Shell struct {
3838
name name
3939
binPath string
40+
pkgConfigDir string
4041
env []string
4142
userShellrcPath string
4243
planInitHook string
@@ -123,6 +124,12 @@ func WithEnvVariables(envVariables map[string]string) ShellOption {
123124
}
124125
}
125126

127+
func WithPKGCOnfigDir(pkgConfigDir string) ShellOption {
128+
return func(s *Shell) {
129+
s.pkgConfigDir = pkgConfigDir
130+
}
131+
}
132+
126133
// rcfilePath returns the absolute path for an rcfile, which is usually in the
127134
// user's home directory. It doesn't guarantee that the file exists.
128135
func rcfilePath(basename string) string {
@@ -278,19 +285,24 @@ func (s *Shell) writeDevboxShellrc() (path string, err error) {
278285
}
279286
}()
280287

288+
pathPrepend := s.profileDir + "/bin"
289+
if s.pkgConfigDir != "" {
290+
pathPrepend = s.pkgConfigDir + ":" + pathPrepend
291+
}
292+
281293
err = shellrcTmpl.Execute(shellrcf, struct {
282294
OriginalInit string
283295
OriginalInitPath string
284296
UserHook string
285297
PlanInitHook string
286-
ProfileBinDir string
298+
PathPrepend string
287299
HistoryFile string
288300
}{
289301
OriginalInit: string(bytes.TrimSpace(userShellrc)),
290302
OriginalInitPath: filepath.Clean(s.userShellrcPath),
291303
UserHook: strings.TrimSpace(s.UserInitHook),
292304
PlanInitHook: strings.TrimSpace(s.planInitHook),
293-
ProfileBinDir: s.profileDir + "/bin",
305+
PathPrepend: pathPrepend,
294306
HistoryFile: strings.TrimSpace(s.historyFile),
295307
})
296308
if err != nil {

nix/shellrc.tmpl

+1-1
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ content readable.
2828

2929
# Begin Devbox Post-init Hook
3030

31-
PATH="{{ .ProfileBinDir }}:$PATH"
31+
PATH="{{ .PathPrepend }}:$PATH"
3232

3333
{{- if .HistoryFile }}
3434
HISTFILE={{.HistoryFile}}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
echo "I get installed if go_1_19 is installed"
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
{
2+
"name": "dummy config for go_1_19",
3+
"version": "1.0.0",
4+
"env": {
5+
"FOO": "bar",
6+
"DEVBOX_HELP": "true that"
7+
},
8+
"create_files": {
9+
".devbox/conf/go_1_19/bin/test-echo": "echo.sh"
10+
}
11+
}

pkgcfg/pkgcfg.go

+68-34
Original file line numberDiff line numberDiff line change
@@ -12,36 +12,11 @@ import (
1212
const localPkgConfigPath = "DEVBOX_LOCAL_PKG_CONFIG"
1313

1414
type config struct {
15-
Name string `json:"name"`
16-
Version string `json:"version"`
17-
CreateFiles map[string]string `json:"create_files"`
18-
Env map[string]string `json:"env"`
19-
}
20-
21-
func get(pkg string) (*config, error) {
22-
if configPath := os.Getenv(localPkgConfigPath); configPath != "" {
23-
debug.Log("Using local package config at %q", configPath)
24-
return getLocalConfig(configPath, pkg)
25-
}
26-
return &config{}, nil
27-
}
28-
29-
func getLocalConfig(configPath, pkg string) (*config, error) {
30-
configPath = filepath.Join(configPath, pkg+".json")
31-
if _, err := os.Stat(configPath); errors.Is(err, os.ErrNotExist) {
32-
// We don't need config for all packages and that's fine
33-
return &config{}, nil
34-
}
35-
debug.Log("Reading local package config at %q", configPath)
36-
content, err := os.ReadFile(configPath)
37-
if err != nil {
38-
return nil, errors.WithStack(err)
39-
}
40-
cfg := &config{}
41-
if err = json.Unmarshal(content, cfg); err != nil {
42-
return nil, errors.WithStack(err)
43-
}
44-
return cfg, nil
15+
Name string `json:"name"`
16+
Version string `json:"version"`
17+
CreateFiles map[string]string `json:"create_files"`
18+
Env map[string]string `json:"env"`
19+
localConfigPath string `json:"-"`
4520
}
4621

4722
func CreateFiles(pkg, basePath string) error {
@@ -51,16 +26,19 @@ func CreateFiles(pkg, basePath string) error {
5126
}
5227
for name, contentPath := range cfg.CreateFiles {
5328
filePath := filepath.Join(basePath, name)
54-
if _, err := os.Stat(filePath); err == nil {
55-
continue
56-
}
57-
content, err := os.ReadFile(filepath.Join(basePath, contentPath))
29+
content, err := os.ReadFile(filepath.Join(cfg.localConfigPath, contentPath))
5830
if err != nil {
5931
return errors.WithStack(err)
6032
}
33+
if err = createDir(filepath.Dir(filePath)); err != nil {
34+
return err
35+
}
6136
if err := os.WriteFile(filePath, content, 0744); err != nil {
6237
return errors.WithStack(err)
6338
}
39+
if err := createSymlink(basePath, filePath); err != nil {
40+
return err
41+
}
6442
}
6543
return nil
6644
}
@@ -78,3 +56,59 @@ func Env(pkgs []string) (map[string]string, error) {
7856
}
7957
return env, nil
8058
}
59+
60+
func get(pkg string) (*config, error) {
61+
if configPath := os.Getenv(localPkgConfigPath); configPath != "" {
62+
debug.Log("Using local package config at %q", configPath)
63+
return getLocalConfig(configPath, pkg)
64+
}
65+
return &config{}, nil
66+
}
67+
68+
func getLocalConfig(configPath, pkg string) (*config, error) {
69+
pkgConfigPath := filepath.Join(configPath, pkg+".json")
70+
if _, err := os.Stat(pkgConfigPath); errors.Is(err, os.ErrNotExist) {
71+
// We don't need config for all packages and that's fine
72+
return &config{}, nil
73+
}
74+
debug.Log("Reading local package config at %q", pkgConfigPath)
75+
content, err := os.ReadFile(pkgConfigPath)
76+
if err != nil {
77+
return nil, errors.WithStack(err)
78+
}
79+
cfg := &config{localConfigPath: configPath}
80+
if err = json.Unmarshal(content, cfg); err != nil {
81+
return nil, errors.WithStack(err)
82+
}
83+
return cfg, nil
84+
}
85+
func createDir(path string) error {
86+
if path == "" {
87+
return nil
88+
}
89+
if err := os.MkdirAll(path, 0755); err != nil {
90+
return errors.WithStack(err)
91+
}
92+
return nil
93+
}
94+
95+
func createSymlink(root, filePath string) error {
96+
name := filepath.Base(filePath)
97+
newname := filepath.Join(root, ".devbox/conf/bin", name)
98+
99+
// Create bin path just in case it doesn't exist
100+
if err := os.MkdirAll(filepath.Join(root, ".devbox/conf/bin"), 0755); err != nil {
101+
return errors.WithStack(err)
102+
}
103+
104+
if _, err := os.Stat(newname); err == nil {
105+
if err = os.Remove(newname); err != nil {
106+
return errors.WithStack(err)
107+
}
108+
}
109+
110+
if err := os.Symlink(filePath, newname); err != nil {
111+
return errors.WithStack(err)
112+
}
113+
return nil
114+
}

0 commit comments

Comments
 (0)