@@ -6,17 +6,27 @@ import (
66 "fmt"
77 "os/exec"
88 "runtime"
9+ "slices"
910 "strings"
1011
1112 "github.com/loft-sh/devpod/pkg/command"
1213 "github.com/loft-sh/log"
1314 "github.com/skratchdot/open-golang/open"
1415)
1516
16- func Open (ctx context.Context , workspace , folder string , newWindow bool , flavor Flavor , log log.Logger ) error {
17+ const (
18+ FlatpakStable string = "com.visualstudio.code"
19+ FlatpakInsiders string = "com.visualstudio.code.insiders"
20+ FlatpakCodium string = "com.vscodium.codium"
21+ FlatpakCodiumInsiders string = "com.vscodium.codium-insiders"
22+ )
23+
24+ func Open (ctx context.Context , workspace , folder string , newWindow bool , flavor Flavor , sshConfigPath string , log log.Logger ) error {
1725 log .Infof ("Starting %s..." , flavor .DisplayName ())
18- cliErr := openViaCLI (ctx , workspace , folder , newWindow , flavor , log )
19- if cliErr == nil {
26+ cliErr := openViaCLI (ctx , workspace , folder , newWindow , flavor , sshConfigPath , log )
27+ if cliErr != nil {
28+ log .Debugf ("Error opening %s via cli: %v" , flavor , cliErr )
29+ } else {
2030 return nil
2131 }
2232
@@ -41,6 +51,8 @@ func openViaBrowser(workspace, folder string, newWindow bool, flavor Flavor, log
4151 protocol = `positron://`
4252 case FlavorCodium :
4353 protocol = `codium://`
54+ case FlavorCodiumInsiders :
55+ protocol = `codium-insiders://`
4456 }
4557
4658 openURL := protocol + `vscode-remote/ssh-remote+` + workspace + `.devpod/` + folder
@@ -58,20 +70,44 @@ func openViaBrowser(workspace, folder string, newWindow bool, flavor Flavor, log
5870 return nil
5971}
6072
61- func openViaCLI (ctx context.Context , workspace , folder string , newWindow bool , flavor Flavor , log log.Logger ) error {
73+ func openViaCLI (ctx context.Context , workspace , folder string , newWindow bool , flavor Flavor , sshConfigPath string , log log.Logger ) error {
6274 // try to find code cli
63- codePath := findCLI (flavor )
64- if codePath == "" {
75+ codePath := findCLI (flavor , log )
76+ if codePath == nil {
6577 return fmt .Errorf ("couldn't find the %s binary" , flavor )
6678 }
6779
80+ if codePath [0 ] == "flatpak" {
81+ log .Debugf ("Running with Flatpak suing the package %s." , codePath [2 ])
82+ out , err := exec .Command (codePath [0 ], "ps" , "--columns=application" ).Output ()
83+ if err != nil {
84+ return command .WrapCommandError (out , err )
85+ }
86+ splitted := strings .Split (string (out ), "\n " )
87+ foundRunning := false
88+ // Ignore the header
89+ for _ , str := range splitted [1 :] {
90+ if strings .TrimSpace (str ) == codePath [2 ] {
91+ foundRunning = true
92+ break
93+ }
94+ }
95+
96+ if foundRunning {
97+ log .Warnf ("The IDE is already running via Flatpak. If you are encountering SSH connectivity issues, make sure to give read access to your SSH config file (e.g flatpak override %s --filesystem=%s) and restart your IDE." , codePath [2 ], sshConfigPath )
98+ }
99+
100+ codePath = slices .Insert (codePath , 2 , fmt .Sprintf ("--filesystem=%s:ro" , sshConfigPath ))
101+ }
102+
68103 sshExtension := "ms-vscode-remote.remote-ssh"
69- if flavor == FlavorCodium {
104+ if flavor == FlavorCodium || flavor == FlavorCodiumInsiders {
70105 sshExtension = "jeanp413.open-remote-ssh"
71106 }
72107
73108 // make sure ms-vscode-remote.remote-ssh is installed
74- out , err := exec .Command (codePath , "--list-extensions" ).Output ()
109+ listArgs := append (codePath , "--list-extensions" )
110+ out , err := exec .Command (listArgs [0 ], listArgs [1 :]... ).Output ()
75111 if err != nil {
76112 return command .WrapCommandError (out , err )
77113 }
@@ -88,9 +124,9 @@ func openViaCLI(ctx context.Context, workspace, folder string, newWindow bool, f
88124
89125 // install remote-ssh extension
90126 if ! found {
91- args := [] string { "--install-extension" , sshExtension }
92- log .Debugf ("Run vscode command %s %s" , codePath , strings .Join (args , " " ))
93- out , err := exec .CommandContext (ctx , codePath , args ... ).Output ()
127+ args := append ( codePath , "--install-extension" , sshExtension )
128+ log .Debugf ("Run vscode command %s %s" , args [ 0 ] , strings .Join (args [ 1 :] , " " ))
129+ out , err := exec .CommandContext (ctx , args [ 0 ] , args [ 1 :] ... ).Output ()
94130 if err != nil {
95131 return fmt .Errorf ("install ssh extension: %w" , command .WrapCommandError (out , err ))
96132 }
@@ -108,66 +144,56 @@ func openViaCLI(ctx context.Context, workspace, folder string, newWindow bool, f
108144 }
109145 // Needs to be separated by `=` because of windows
110146 folderUriArg := fmt .Sprintf ("--folder-uri=vscode-remote://ssh-remote+%s.devpod/%s" , workspace , folder )
147+ args = append (codePath , args ... )
111148 args = append (args , folderUriArg )
112- log .Debugf ("Run %s command %s %s" , flavor .DisplayName (), codePath , strings .Join (args , " " ))
113- out , err = exec .CommandContext (ctx , codePath , args ... ).CombinedOutput ()
149+ log .Debugf ("Run %s command %s %s" , flavor .DisplayName (), args [ 0 ] , strings .Join (args [ 1 :] , " " ))
150+ out , err = exec .CommandContext (ctx , args [ 0 ] , args [ 1 :] ... ).CombinedOutput ()
114151 if err != nil {
115152 return command .WrapCommandError (out , err )
116153 }
117154
118155 return nil
119156}
120157
121- func findCLI (flavor Flavor ) string {
122- if flavor == FlavorStable {
123- if command .Exists ("code" ) {
124- return "code"
125- } else if runtime .GOOS == "darwin" && command .Exists ("/Applications/Visual Studio Code.app/Contents/Resources/app/bin/code" ) {
126- return "/Applications/Visual Studio Code.app/Contents/Resources/app/bin/code"
127- }
128-
129- return ""
158+ func existsInFlatpak (packageName string , log log.Logger ) bool {
159+ if err := exec .Command ("flatpak" , "info" , packageName ).Run (); err == nil {
160+ return true
161+ } else {
162+ log .Debugf ("Flatpak command for %s returned: %s" , packageName , err )
130163 }
164+ return false
165+ }
131166
132- if flavor == FlavorInsiders {
133- if command .Exists ("code-insiders" ) {
134- return "code-insiders"
135- } else if runtime .GOOS == "darwin" && command .Exists ("/Applications/Visual Studio Code - Insiders.app/Contents/Resources/app/bin/code" ) {
136- return "/Applications/Visual Studio Code - Insiders.app/Contents/Resources/app/bin/code"
137- }
138-
139- return ""
167+ func getCommandArgs (execName , macOSPath , flatpakPackage string , log log.Logger ) []string {
168+ if command .Exists (execName ) {
169+ return []string {execName }
140170 }
141171
142- if flavor == FlavorCursor {
143- if command .Exists ("cursor" ) {
144- return "cursor"
145- } else if runtime .GOOS == "darwin" && command .Exists ("/Applications/Cursor.app/Contents/Resources/app/bin/cursor" ) {
146- return "/Applications/Cursor.app/Contents/Resources/app/bin/cursor"
147- }
148-
149- return ""
172+ if runtime .GOOS == "darwin" && command .Exists (macOSPath ) {
173+ return []string {macOSPath }
150174 }
151175
152- if flavor == FlavorPositron {
153- if command .Exists ("positron" ) {
154- return "positron"
155- } else if runtime .GOOS == "darwin" && command .Exists ("/Applications/Positron.app/Contents/Resources/app/bin/positron" ) {
156- return "/Applications/Positron.app/Contents/Resources/app/bin/positron"
157- }
158-
159- return ""
176+ if runtime .GOOS == "linux" && flatpakPackage != "" && command .Exists ("flatpak" ) && existsInFlatpak (flatpakPackage , log ) {
177+ return []string {"flatpak" , "run" , flatpakPackage }
160178 }
161179
162- if flavor == FlavorCodium {
163- if command .Exists ("codium" ) {
164- return "codium"
165- } else if runtime .GOOS == "darwin" && command .Exists ("/Applications/Codium.app/Contents/Resources/app/bin/codium" ) {
166- return "/Applications/Codium.app/Contents/Resources/app/bin/codium"
167- }
180+ return nil
181+ }
168182
169- return ""
183+ func findCLI (flavor Flavor , log log.Logger ) []string {
184+ switch flavor {
185+ case FlavorStable :
186+ return getCommandArgs ("code" , "/Applications/Visual Studio Code.app/Contents/Resources/app/bin/code" , FlatpakStable , log )
187+ case FlavorInsiders :
188+ return getCommandArgs ("code-insiders" , "/Applications/Visual Studio Code - Insiders.app/Contents/Resources/app/bin/code" , FlatpakInsiders , log )
189+ case FlavorCursor :
190+ return getCommandArgs ("cursor" , "/Applications/Cursor.app/Contents/Resources/app/bin/cursor" , "" , log )
191+ case FlavorPositron :
192+ return getCommandArgs ("positron" , "/Applications/Positron.app/Contents/Resources/app/bin/positron" , "" , log )
193+ case FlavorCodium :
194+ return getCommandArgs ("codium" , "/Applications/Codium.app/Contents/Resources/app/bin/codium" , FlatpakCodium , log )
195+ case FlavorCodiumInsiders :
196+ return getCommandArgs ("codium-insiders" , "/Applications/CodiumInsiders.app/Contents/Resources/app/bin/codium-insiders" , FlatpakCodiumInsiders , log )
170197 }
171-
172- return ""
198+ return nil
173199}
0 commit comments