@@ -14,6 +14,7 @@ import (
14
14
15
15
"github.com/pkg/errors"
16
16
"go.jetpack.io/devbox/internal/cmdutil"
17
+ "go.jetpack.io/devbox/internal/debug"
17
18
"go.jetpack.io/devbox/internal/fileutil"
18
19
"go.jetpack.io/devbox/internal/nix"
19
20
"go.jetpack.io/devbox/internal/plugin"
@@ -31,6 +32,10 @@ type devboxer interface {
31
32
var wrapper string
32
33
var wrapperTemplate = template .Must (template .New ("wrapper" ).Parse (wrapper ))
33
34
35
+ // devboxSymlinkDir is the directory that has the symlink to the devbox binary,
36
+ // which is used by the bin-wrappers
37
+ var devboxSymlinkDir = xdg .CacheSubpath (filepath .Join ("devbox" , "bin" , "current" ))
38
+
34
39
// CreateWrappers creates wrappers for all the executables in nix paths
35
40
func CreateWrappers (ctx context.Context , devbox devboxer ) error {
36
41
shellEnvHash , err := devbox .ShellEnvHash (ctx )
@@ -51,8 +56,7 @@ func CreateWrappers(ctx context.Context, devbox devboxer) error {
51
56
if err != nil {
52
57
return err
53
58
}
54
- devboxSymlinkPath , err := CreateDevboxSymlink ()
55
- if err != nil {
59
+ if err := CreateDevboxSymlinkIfPossible (); err != nil {
56
60
return err
57
61
}
58
62
@@ -62,7 +66,7 @@ func CreateWrappers(ctx context.Context, devbox devboxer) error {
62
66
BashPath : bashPath ,
63
67
Command : bin ,
64
68
ShellEnvHash : shellEnvHash ,
65
- DevboxSymlinkDir : filepath . Dir ( devboxSymlinkPath ) ,
69
+ DevboxSymlinkDir : devboxSymlinkDir ,
66
70
destPath : filepath .Join (destPath , filepath .Base (bin )),
67
71
}); err != nil {
68
72
return errors .WithStack (err )
@@ -72,7 +76,7 @@ func CreateWrappers(ctx context.Context, devbox devboxer) error {
72
76
return createSymlinksForSupportDirs (devbox .ProjectDir ())
73
77
}
74
78
75
- // CreateDevboxSymlink creates a symlink to the devbox binary
79
+ // CreateDevboxSymlinkIfPossible creates a symlink to the devbox binary.
76
80
//
77
81
// Needed because:
78
82
//
@@ -88,29 +92,44 @@ func CreateWrappers(ctx context.Context, devbox devboxer) error {
88
92
//
89
93
// So, the bin-wrappers need to use a symlink to the latest devbox binary. This
90
94
// symlink is updated when devbox is updated.
91
- func CreateDevboxSymlink () ( string , error ) {
92
- curDir := xdg . CacheSubpath ( filepath . Join ( "devbox" , "bin" , "current" ))
93
- if err := fileutil .EnsureDirExists (curDir , 0755 , false /*chmod*/ ); err != nil {
94
- return "" , err
95
+ func CreateDevboxSymlinkIfPossible () error {
96
+ // Get the symlink path; create the symlink directory if it doesn't exist.
97
+ if err := fileutil .EnsureDirExists (devboxSymlinkDir , 0755 , false /*chmod*/ ); err != nil {
98
+ return err
95
99
}
96
- currentDevboxSymlinkPath := filepath .Join (curDir , "devbox" )
100
+ currentDevboxSymlinkPath := filepath .Join (devboxSymlinkDir , "devbox" )
97
101
98
- devboxBinaryPath , err := os .Executable ()
102
+ // Get the path to the devbox binary.
103
+ execPath , err := os .Executable ()
99
104
if err != nil {
100
- return "" , errors .WithStack (err )
105
+ return errors .WithStack (err )
101
106
}
107
+ devboxBinaryPath , evalSymlinkErr := filepath .EvalSymlinks (execPath )
108
+ // we check the error below, because we always want to remove the symlink
102
109
103
110
// We will always re-create this symlink to ensure correctness.
104
111
if err := os .Remove (currentDevboxSymlinkPath ); err != nil && ! errors .Is (err , os .ErrNotExist ) {
105
- return "" , errors .WithStack (err )
112
+ return errors .WithStack (err )
113
+ }
114
+
115
+ if evalSymlinkErr != nil {
116
+ // This may return an error due to symlink loops. But we don't stop the
117
+ // process for this reason, so the bin-wrappers can still be created.
118
+ //
119
+ // Once the symlink loop is fixed, and the bin-wrappers
120
+ // will start working without needing to be re-created.
121
+ //
122
+ // nolint:nilerr
123
+ debug .Log ("Error evaluating symlink: %v" , evalSymlinkErr )
124
+ return nil
106
125
}
107
126
108
127
// Don't return error if error is os.ErrExist to protect against race conditions.
109
128
if err := os .Symlink (devboxBinaryPath , currentDevboxSymlinkPath ); err != nil && ! errors .Is (err , os .ErrExist ) {
110
- return "" , errors .WithStack (err )
129
+ return errors .WithStack (err )
111
130
}
112
131
113
- return currentDevboxSymlinkPath , nil
132
+ return nil
114
133
}
115
134
116
135
type createWrapperArgs struct {
0 commit comments