@@ -14,6 +14,7 @@ import (
1414
1515 "github.com/pkg/errors"
1616 "go.jetpack.io/devbox/internal/cmdutil"
17+ "go.jetpack.io/devbox/internal/debug"
1718 "go.jetpack.io/devbox/internal/fileutil"
1819 "go.jetpack.io/devbox/internal/nix"
1920 "go.jetpack.io/devbox/internal/plugin"
@@ -31,6 +32,10 @@ type devboxer interface {
3132var wrapper string
3233var wrapperTemplate = template .Must (template .New ("wrapper" ).Parse (wrapper ))
3334
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+
3439// CreateWrappers creates wrappers for all the executables in nix paths
3540func CreateWrappers (ctx context.Context , devbox devboxer ) error {
3641 shellEnvHash , err := devbox .ShellEnvHash (ctx )
@@ -51,8 +56,7 @@ func CreateWrappers(ctx context.Context, devbox devboxer) error {
5156 if err != nil {
5257 return err
5358 }
54- devboxSymlinkPath , err := CreateDevboxSymlink ()
55- if err != nil {
59+ if err := CreateDevboxSymlinkIfPossible (); err != nil {
5660 return err
5761 }
5862
@@ -62,7 +66,7 @@ func CreateWrappers(ctx context.Context, devbox devboxer) error {
6266 BashPath : bashPath ,
6367 Command : bin ,
6468 ShellEnvHash : shellEnvHash ,
65- DevboxSymlinkDir : filepath . Dir ( devboxSymlinkPath ) ,
69+ DevboxSymlinkDir : devboxSymlinkDir ,
6670 destPath : filepath .Join (destPath , filepath .Base (bin )),
6771 }); err != nil {
6872 return errors .WithStack (err )
@@ -72,7 +76,7 @@ func CreateWrappers(ctx context.Context, devbox devboxer) error {
7276 return createSymlinksForSupportDirs (devbox .ProjectDir ())
7377}
7478
75- // CreateDevboxSymlink creates a symlink to the devbox binary
79+ // CreateDevboxSymlinkIfPossible creates a symlink to the devbox binary.
7680//
7781// Needed because:
7882//
@@ -88,29 +92,44 @@ func CreateWrappers(ctx context.Context, devbox devboxer) error {
8892//
8993// So, the bin-wrappers need to use a symlink to the latest devbox binary. This
9094// 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
9599 }
96- currentDevboxSymlinkPath := filepath .Join (curDir , "devbox" )
100+ currentDevboxSymlinkPath := filepath .Join (devboxSymlinkDir , "devbox" )
97101
98- devboxBinaryPath , err := os .Executable ()
102+ // Get the path to the devbox binary.
103+ execPath , err := os .Executable ()
99104 if err != nil {
100- return "" , errors .WithStack (err )
105+ return errors .WithStack (err )
101106 }
107+ devboxBinaryPath , evalSymlinkErr := filepath .EvalSymlinks (execPath )
108+ // we check the error below, because we always want to remove the symlink
102109
103110 // We will always re-create this symlink to ensure correctness.
104111 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
106125 }
107126
108127 // Don't return error if error is os.ErrExist to protect against race conditions.
109128 if err := os .Symlink (devboxBinaryPath , currentDevboxSymlinkPath ); err != nil && ! errors .Is (err , os .ErrExist ) {
110- return "" , errors .WithStack (err )
129+ return errors .WithStack (err )
111130 }
112131
113- return currentDevboxSymlinkPath , nil
132+ return nil
114133}
115134
116135type createWrapperArgs struct {
0 commit comments