11// SPDX-FileCopyrightText: Copyright The Lima Authors
22// SPDX-License-Identifier: Apache-2.0
33
4- package usrlocalsharelima
4+ package usrlocal
55
66import (
77 "errors"
@@ -10,7 +10,7 @@ import (
1010 "os"
1111 "os/exec"
1212 "path/filepath"
13- "runtime "
13+ "strings "
1414 "sync"
1515
1616 "github.com/sirupsen/logrus"
@@ -73,61 +73,57 @@ func SelfDirs() []string {
7373 return selfPaths
7474}
7575
76- // Dir returns the location of the <PREFIX>/lima/share directory, relative to the location
77- // of the current executable. It checks for multiple possible filesystem layouts and returns
78- // the first candidate that contains the native guest agent binary.
79- func Dir () (string , error ) {
80- selfDirs := SelfDirs ()
76+ func delveDebugExe () string {
77+ exe , err := os .Executable ()
78+ if err != nil {
79+ return ""
80+ }
81+ exeBase := filepath .Base (exe )
82+ if strings .HasPrefix (exeBase , "__debug_bin" ) {
83+ return exe
84+ }
85+ return ""
86+ }
8187
82- ostype := limatype . NewOS ( "linux" )
83- arch := limatype . NewArch ( runtime . GOARCH )
84- if arch == "" {
85- return "" , fmt . Errorf ( "failed to get arch for %q" , runtime . GOARCH )
88+ func delveWorkspace () string {
89+ self := delveDebugExe ( )
90+ if self == "" {
91+ return ""
8692 }
93+ // https://github.com/lima-vm/lima/pull/2651/commits/644c11373cb79aaebd8520706f7d51bd3ee5fbe4
94+ // launched by `~/go/bin/dlv dap`
95+ // - self: ${workspaceFolder}/cmd/limactl/__debug_bin_XXXXXX
96+ return filepath .Dir (filepath .Dir (filepath .Dir (self )))
97+ }
8798
88- gaCandidates := []string {}
99+ // ShareLima returns the <PREFIX>/share/lima directories.
100+ func ShareLima () ([]string , error ) {
101+ var candidates []string
102+ selfDirs := SelfDirs ()
89103 for _ , selfDir := range selfDirs {
90104 // selfDir: /usr/local/bin
91- selfDirDir := filepath .Dir (selfDir )
92- gaCandidates = append (gaCandidates ,
93- // candidate 0:
94- // - self: /Applications/Lima.app/Contents/MacOS/limactl
95- // - agent: /Applications/Lima.app/Contents/MacOS/lima-guestagent.Linux-x86_64
96- // - dir: /Applications/Lima.app/Contents/MacOS
97- filepath .Join (selfDir , "lima-guestagent." + ostype + "-" + arch ),
98- // candidate 1:
99- // - self: /usr/local/bin/limactl
100- // - agent: /usr/local/share/lima/lima-guestagent.Linux-x86_64
101- // - dir: /usr/local/share/lima
102- filepath .Join (selfDirDir , "share/lima/lima-guestagent." + ostype + "-" + arch ),
103- // TODO: support custom path
104- )
105- if debugutil .Debug {
106- // candidate 2: launched by `~/go/bin/dlv dap`
105+ // prefix: /usr/local
106+ // candidate: /usr/local/share/lima
107+ prefix := filepath .Dir (selfDir )
108+ candidate := filepath .Join (prefix , "share" , "lima" )
109+ if ents , err := os .ReadDir (candidate ); err == nil && len (ents ) > 0 {
110+ candidates = append (candidates , candidate )
111+ }
112+ }
113+ if debugutil .Debug {
114+ if workspace := delveWorkspace (); workspace != "" {
115+ // https://github.com/lima-vm/lima/pull/2651/commits/644c11373cb79aaebd8520706f7d51bd3ee5fbe4
116+ // launched by `~/go/bin/dlv dap`
107117 // - self: ${workspaceFolder}/cmd/limactl/__debug_bin_XXXXXX
108118 // - agent: ${workspaceFolder}/_output/share/lima/lima-guestagent.Linux-x86_64
109119 // - dir: ${workspaceFolder}/_output/share/lima
110- candidateForDebugBuild := filepath .Join (filepath .Dir (selfDirDir ), "_output/share/lima/lima-guestagent." + ostype + "-" + arch )
111- gaCandidates = append (gaCandidates , candidateForDebugBuild )
112- logrus .Infof ("debug mode detected, adding more guest agent candidates: %v" , candidateForDebugBuild )
113- }
114- }
115-
116- for _ , gaCandidate := range gaCandidates {
117- if _ , err := os .Stat (gaCandidate ); err == nil {
118- return filepath .Dir (gaCandidate ), nil
119- } else if ! errors .Is (err , os .ErrNotExist ) {
120- return "" , err
121- }
122- if _ , err := os .Stat (gaCandidate + ".gz" ); err == nil {
123- return filepath .Dir (gaCandidate ), nil
124- } else if ! errors .Is (err , os .ErrNotExist ) {
125- return "" , err
120+ candidate := filepath .Join (workspace , "_output" , "share" , "lima" )
121+ if ents , err := os .ReadDir (candidate ); err == nil && len (ents ) > 0 {
122+ candidates = append (candidates , candidate )
123+ }
126124 }
127125 }
128-
129- return "" , fmt .Errorf ("failed to find \" lima-guestagent.%s-%s\" binary for %v, attempted %v" ,
130- ostype , arch , selfDirs , gaCandidates )
126+ return candidates , nil
131127}
132128
133129// GuestAgentBinary returns the absolute path of the guest agent binary, possibly with ".gz" suffix.
@@ -138,18 +134,26 @@ func GuestAgentBinary(ostype limatype.OS, arch limatype.Arch) (string, error) {
138134 if arch == "" {
139135 return "" , errors .New ("arch must be set" )
140136 }
141- dir , err := Dir ()
137+ shareLimaDirs , err := ShareLima ()
142138 if err != nil {
143139 return "" , err
144140 }
145- uncomp := filepath .Join (dir , "lima-guestagent." + ostype + "-" + arch )
146- comp := uncomp + ".gz"
147- res , err := chooseGABinary ([]string {comp , uncomp })
148- if err != nil {
149- logrus .Debug (err )
150- return "" , fmt .Errorf ("guest agent binary could not be found for %s-%s: %w (Hint: try installing `lima-additional-guestagents` package)" , ostype , arch , err )
141+ for _ , dir := range shareLimaDirs {
142+ uncomp := filepath .Join (dir , "lima-guestagent." + ostype + "-" + arch )
143+ comp := uncomp + ".gz"
144+ var res string
145+ res , err = chooseGABinary ([]string {comp , uncomp })
146+ if err != nil {
147+ logrus .Debug (err )
148+ continue
149+ }
150+ return res , nil
151+ }
152+ if err == nil {
153+ // caller expects err to be comparable to fs.ErrNotExist
154+ err = fs .ErrNotExist
151155 }
152- return res , nil
156+ return "" , fmt . Errorf ( "guest agent binary could not be found for %s-%s: %w (Hint: try installing `lima-additional-guestagents` package)" , ostype , arch , err )
153157}
154158
155159func chooseGABinary (candidates []string ) (string , error ) {
@@ -194,12 +198,20 @@ func LibexecLima() ([]string, error) {
194198 // candidate: /opt/homebrew/lib/lima
195199 //
196200 // Note that there is no /opt/homebrew/libexec directory,
197- // as Homebrew preserves libexec for private use.
201+ // as Homebrew reserves libexec for private use.
198202 // https://github.com/lima-vm/lima/issues/4295#issuecomment-3490680651
199203 candidate = filepath .Join (prefix , "lib" , "lima" )
200204 if ents , err := os .ReadDir (candidate ); err == nil && len (ents ) > 0 {
201205 candidates = append (candidates , candidate )
202206 }
203207 }
208+ if debugutil .Debug {
209+ if workspace := delveWorkspace (); workspace != "" {
210+ candidate := filepath .Join (workspace , "_output" , "libexec" , "lima" )
211+ if ents , err := os .ReadDir (candidate ); err == nil && len (ents ) > 0 {
212+ candidates = append (candidates , candidate )
213+ }
214+ }
215+ }
204216 return candidates , nil
205217}
0 commit comments