@@ -6,16 +6,24 @@ 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 )
26+ cliErr := openViaCLI (ctx , workspace , folder , newWindow , flavor , sshConfigPath , log )
1927 if cliErr == nil {
2028 return nil
2129 }
@@ -41,6 +49,8 @@ func openViaBrowser(workspace, folder string, newWindow bool, flavor Flavor, log
4149 protocol = `positron://`
4250 case FlavorCodium :
4351 protocol = `codium://`
52+ case FlavorCodiumInsiders :
53+ protocol = `codium-insiders://`
4454 }
4555
4656 openURL := protocol + `vscode-remote/ssh-remote+` + workspace + `.devpod/` + folder
@@ -58,20 +68,44 @@ func openViaBrowser(workspace, folder string, newWindow bool, flavor Flavor, log
5868 return nil
5969}
6070
61- func openViaCLI (ctx context.Context , workspace , folder string , newWindow bool , flavor Flavor , log log.Logger ) error {
71+ func openViaCLI (ctx context.Context , workspace , folder string , newWindow bool , flavor Flavor , sshConfigPath string , log log.Logger ) error {
6272 // try to find code cli
63- codePath := findCLI (flavor )
64- if codePath == "" {
73+ codePath := findCLI (flavor , log )
74+ if codePath == nil {
6575 return fmt .Errorf ("couldn't find the %s binary" , flavor )
6676 }
6777
78+ if codePath [0 ] == "flatpak" {
79+ log .Debugf ("Running with Flatpak suing the package %s." , codePath [2 ])
80+ out , err := exec .Command (codePath [0 ], "ps" , "--columns=application" ).Output ()
81+ if err != nil {
82+ return command .WrapCommandError (out , err )
83+ }
84+ splitted := strings .Split (string (out ), "\n " )
85+ foundRunning := false
86+ // Ignore the header
87+ for _ , str := range splitted [1 :] {
88+ if strings .TrimSpace (str ) == codePath [2 ] {
89+ foundRunning = true
90+ break
91+ }
92+ }
93+
94+ if foundRunning {
95+ 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 )
96+ }
97+
98+ codePath = slices .Insert (codePath , 2 , fmt .Sprintf ("--filesystem=%s:ro" , sshConfigPath ))
99+ }
100+
68101 sshExtension := "ms-vscode-remote.remote-ssh"
69- if flavor == FlavorCodium {
102+ if flavor == FlavorCodium || flavor == FlavorCodiumInsiders {
70103 sshExtension = "jeanp413.open-remote-ssh"
71104 }
72105
73106 // make sure ms-vscode-remote.remote-ssh is installed
74- out , err := exec .Command (codePath , "--list-extensions" ).Output ()
107+ listArgs := append (codePath , "--list-extensions" )
108+ out , err := exec .Command (listArgs [0 ], listArgs [1 :]... ).Output ()
75109 if err != nil {
76110 return command .WrapCommandError (out , err )
77111 }
@@ -88,9 +122,9 @@ func openViaCLI(ctx context.Context, workspace, folder string, newWindow bool, f
88122
89123 // install remote-ssh extension
90124 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 ()
125+ args := append ( codePath , "--install-extension" , sshExtension )
126+ log .Debugf ("Run vscode command %s %s" , args [ 0 ] , strings .Join (args [ 1 :] , " " ))
127+ out , err := exec .CommandContext (ctx , args [ 0 ] , args [ 1 :] ... ).Output ()
94128 if err != nil {
95129 return fmt .Errorf ("install ssh extension: %w" , command .WrapCommandError (out , err ))
96130 }
@@ -108,66 +142,56 @@ func openViaCLI(ctx context.Context, workspace, folder string, newWindow bool, f
108142 }
109143 // Needs to be separated by `=` because of windows
110144 folderUriArg := fmt .Sprintf ("--folder-uri=vscode-remote://ssh-remote+%s.devpod/%s" , workspace , folder )
145+ args = append (codePath , args ... )
111146 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 ()
147+ log .Debugf ("Run %s command %s %s" , flavor .DisplayName (), args [ 0 ] , strings .Join (args [ 1 :] , " " ))
148+ out , err = exec .CommandContext (ctx , args [ 0 ] , args [ 1 :] ... ).CombinedOutput ()
114149 if err != nil {
115150 return command .WrapCommandError (out , err )
116151 }
117152
118153 return nil
119154}
120155
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 ""
156+ func existsInFlatpak (packageName string , log log.Logger ) bool {
157+ if err := exec .Command ("flatpak" , "info" , packageName ).Run (); err == nil {
158+ return true
159+ } else {
160+ log .Debugf ("Flatpak command for %s returned: %s" , packageName , err )
130161 }
162+ return false
163+ }
131164
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 ""
165+ func getCommandArgs (execName , macOSPath , flatpakPackage string , log log.Logger ) []string {
166+ if command .Exists (execName ) {
167+ return []string {execName }
140168 }
141169
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 ""
170+ if runtime .GOOS == "darwin" && command .Exists (macOSPath ) {
171+ return []string {macOSPath }
150172 }
151173
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 ""
174+ if runtime .GOOS == "linux" && flatpakPackage != "" && command .Exists ("flatpak" ) && existsInFlatpak (flatpakPackage , log ) {
175+ return []string {"flatpak" , "run" , flatpakPackage }
160176 }
161177
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- }
178+ return nil
179+ }
168180
169- return ""
181+ func findCLI (flavor Flavor , log log.Logger ) []string {
182+ switch flavor {
183+ case FlavorStable :
184+ return getCommandArgs ("code" , "/Applications/Visual Studio Code.app/Contents/Resources/app/bin/code" , FlatpakStable , log )
185+ case FlavorInsiders :
186+ return getCommandArgs ("code-insiders" , "/Applications/Visual Studio Code - Insiders.app/Contents/Resources/app/bin/code" , FlatpakInsiders , log )
187+ case FlavorCursor :
188+ return getCommandArgs ("cursor" , "/Applications/Cursor.app/Contents/Resources/app/bin/cursor" , "" , log )
189+ case FlavorPositron :
190+ return getCommandArgs ("positron" , "/Applications/Positron.app/Contents/Resources/app/bin/positron" , "" , log )
191+ case FlavorCodium :
192+ return getCommandArgs ("codium" , "/Applications/Codium.app/Contents/Resources/app/bin/codium" , FlatpakCodium , log )
193+ case FlavorCodiumInsiders :
194+ return getCommandArgs ("codium-insiders" , "/Applications/CodiumInsiders.app/Contents/Resources/app/bin/codium-insiders" , FlatpakCodiumInsiders , log )
170195 }
171-
172- return ""
196+ return nil
173197}
0 commit comments