@@ -23,32 +23,42 @@ import (
2323// It will also append the file extension on Windows, if necessary.
2424// This function is different from os.Executable(), which will use /proc/self/exe on Linux
2525// and therefore will resolve any symlink used to locate the executable. This function will
26- // return the symlink instead because we want to locate ../share/lima relative to the location
27- // of the symlink, and not the actual executable. This is important when using Homebrew.
28- //
29- // If os.Args[0] is invalid, this function still falls back on os.Executable().
26+ // return the symlink instead because we want to be able to locate ../share/lima relative
27+ // to the location of the symlink, and not the actual executable. This is important when
28+ // using Homebrew.
3029var executableViaArgs0 = sync .OnceValues (func () (string , error ) {
3130 if os .Args [0 ] == "" {
32- logrus .Warn ("os.Args[0] has not been set" )
33- } else {
34- executable , err := exec .LookPath (os .Args [0 ])
35- if err == nil {
36- // LookPath() will add the `.exe` file extension on Windows, but will not return an
37- // absolute path if the argument contained any of `:/\` (or just `/` on Unix).
38- return filepath .Abs (executable )
39- }
40- logrus .Warnf ("os.Args[0] is invalid: %v" , err )
31+ return "" , errors .New ("os.Args[0] has not been set" )
32+ }
33+ executable , err := exec .LookPath (os .Args [0 ])
34+ if err == nil {
35+ executable , err = filepath .Abs (executable )
36+ }
37+ if err != nil {
38+ return "" , fmt .Errorf ("os.Args[0] is invalid: %w" , err )
4139 }
42- return os .Executable ()
40+
41+ return executable , nil
4342})
4443
4544// Dir returns the location of the <PREFIX>/lima/share directory, relative to the location
4645// of the current executable. It checks for multiple possible filesystem layouts and returns
4746// the first candidate that contains the native guest agent binary.
4847func Dir () (string , error ) {
49- self , err := executableViaArgs0 ()
48+ selfPaths := []string {}
49+
50+ selfViaArgs0 , err := executableViaArgs0 ()
5051 if err != nil {
51- return "" , err
52+ logrus .WithError (err ).Warn ("failed to find executable from os.Args[0]" )
53+ } else {
54+ selfPaths = append (selfPaths , selfViaArgs0 )
55+ }
56+
57+ selfViaOS , err := os .Executable ()
58+ if err != nil {
59+ logrus .WithError (err ).Warn ("failed to find os.Executable()" )
60+ } else if len (selfPaths ) == 0 || selfViaOS != selfPaths [0 ] {
61+ selfPaths = append (selfPaths , selfViaOS )
5262 }
5363
5464 ostype := limayaml .NewOS ("linux" )
@@ -57,31 +67,35 @@ func Dir() (string, error) {
5767 return "" , fmt .Errorf ("failed to get arch for %q" , runtime .GOARCH )
5868 }
5969
60- // self: /usr/local/bin/limactl
61- selfDir := filepath .Dir (self )
62- selfDirDir := filepath .Dir (selfDir )
63- gaCandidates := []string {
64- // candidate 0:
65- // - self: /Applications/Lima.app/Contents/MacOS/limactl
66- // - agent: /Applications/Lima.app/Contents/MacOS/lima-guestagent.Linux-x86_64
67- // - dir: /Applications/Lima.app/Contents/MacOS
68- filepath .Join (selfDir , "lima-guestagent." + ostype + "-" + arch ),
69- // candidate 1:
70- // - self: /usr/local/bin/limactl
71- // - agent: /usr/local/share/lima/lima-guestagent.Linux-x86_64
72- // - dir: /usr/local/share/lima
73- filepath .Join (selfDirDir , "share/lima/lima-guestagent." + ostype + "-" + arch ),
74- // TODO: support custom path
75- }
76- if debugutil .Debug {
77- // candidate 2: launched by `~/go/bin/dlv dap`
78- // - self: ${workspaceFolder}/cmd/limactl/__debug_bin_XXXXXX
79- // - agent: ${workspaceFolder}/_output/share/lima/lima-guestagent.Linux-x86_64
80- // - dir: ${workspaceFolder}/_output/share/lima
81- candidateForDebugBuild := filepath .Join (filepath .Dir (selfDirDir ), "_output/share/lima/lima-guestagent." + ostype + "-" + arch )
82- gaCandidates = append (gaCandidates , candidateForDebugBuild )
83- logrus .Infof ("debug mode detected, adding more guest agent candidates: %v" , candidateForDebugBuild )
70+ gaCandidates := []string {}
71+ for _ , self := range selfPaths {
72+ // self: /usr/local/bin/limactl
73+ selfDir := filepath .Dir (self )
74+ selfDirDir := filepath .Dir (selfDir )
75+ gaCandidates = append (gaCandidates ,
76+ // candidate 0:
77+ // - self: /Applications/Lima.app/Contents/MacOS/limactl
78+ // - agent: /Applications/Lima.app/Contents/MacOS/lima-guestagent.Linux-x86_64
79+ // - dir: /Applications/Lima.app/Contents/MacOS
80+ filepath .Join (selfDir , "lima-guestagent." + ostype + "-" + arch ),
81+ // candidate 1:
82+ // - self: /usr/local/bin/limactl
83+ // - agent: /usr/local/share/lima/lima-guestagent.Linux-x86_64
84+ // - dir: /usr/local/share/lima
85+ filepath .Join (selfDirDir , "share/lima/lima-guestagent." + ostype + "-" + arch ),
86+ // TODO: support custom path
87+ )
88+ if debugutil .Debug {
89+ // candidate 2: launched by `~/go/bin/dlv dap`
90+ // - self: ${workspaceFolder}/cmd/limactl/__debug_bin_XXXXXX
91+ // - agent: ${workspaceFolder}/_output/share/lima/lima-guestagent.Linux-x86_64
92+ // - dir: ${workspaceFolder}/_output/share/lima
93+ candidateForDebugBuild := filepath .Join (filepath .Dir (selfDirDir ), "_output/share/lima/lima-guestagent." + ostype + "-" + arch )
94+ gaCandidates = append (gaCandidates , candidateForDebugBuild )
95+ logrus .Infof ("debug mode detected, adding more guest agent candidates: %v" , candidateForDebugBuild )
96+ }
8497 }
98+
8599 for _ , gaCandidate := range gaCandidates {
86100 if _ , err := os .Stat (gaCandidate ); err == nil {
87101 return filepath .Dir (gaCandidate ), nil
@@ -95,8 +109,8 @@ func Dir() (string, error) {
95109 }
96110 }
97111
98- return "" , fmt .Errorf ("failed to find \" lima-guestagent.%s-%s\" binary for %q , attempted %v" ,
99- ostype , arch , self , gaCandidates )
112+ return "" , fmt .Errorf ("failed to find \" lima-guestagent.%s-%s\" binary for %v , attempted %v" ,
113+ ostype , arch , selfPaths , gaCandidates )
100114}
101115
102116// GuestAgentBinary returns the absolute path of the guest agent binary, possibly with ".gz" suffix.
0 commit comments