@@ -85,13 +85,23 @@ func runShim() error {
8585 execPath = adjustExecutablePath (execPath , shimName , runtimeName )
8686 ui .Debug ("Final executable path: %s" , execPath )
8787
88+ // Get provider-specific environment variables (e.g., LD_LIBRARY_PATH for Ruby)
89+ providerEnv , err := provider .GetEnvironment (version )
90+ if err != nil {
91+ ui .Debug ("Failed to get provider environment: %v" , err )
92+ providerEnv = map [string ]string {}
93+ }
94+ for k , v := range providerEnv {
95+ ui .Debug ("Provider env: %s=%s" , k , v )
96+ }
97+
8898 // Check if this command should trigger a reshim after execution
8999 needsReshim := provider .ShouldReshimAfter (shimName , os .Args [1 :])
90100
91101 // Execute the actual binary
92102 if needsReshim {
93103 // Need to run code after execution, so use exec.Command
94- exitCode := executeCommandWithWait (execPath , os .Args [1 :])
104+ exitCode := executeCommandWithWait (execPath , os .Args [1 :], providerEnv )
95105
96106 // If command succeeded, prompt for reshim
97107 if exitCode == 0 {
@@ -101,7 +111,7 @@ func runShim() error {
101111 os .Exit (exitCode )
102112 } else {
103113 // Normal execution - use syscall.Exec on Unix for efficiency
104- if err := executeCommand (execPath , os .Args [1 :]); err != nil {
114+ if err := executeCommand (execPath , os .Args [1 :], providerEnv ); err != nil {
105115 return fmt .Errorf ("failed to execute %s: %w" , execPath , err )
106116 }
107117 }
@@ -123,8 +133,8 @@ func handleNoConfiguredVersion(shimName, runtimeName string, provider runtime.Sh
123133 ui .Info ("Or see available versions: dtvem list-all %s" , runtimeName )
124134 fmt .Fprintln (os .Stderr ) // Empty line for spacing
125135
126- // Execute the system version
127- if err := executeCommand (systemPath , os .Args [1 :]); err != nil {
136+ // Execute the system version (no provider env needed for system installations)
137+ if err := executeCommand (systemPath , os .Args [1 :], nil ); err != nil {
128138 return fmt .Errorf ("failed to execute system %s: %w" , shimName , err )
129139 }
130140 return nil
@@ -243,13 +253,13 @@ func adjustExecutablePath(execPath, shimName, runtimeName string) string {
243253 return execPath
244254}
245255
246- // executeCommand executes a command with the given arguments
247- func executeCommand (execPath string , args []string ) error {
256+ // executeCommand executes a command with the given arguments and provider environment
257+ func executeCommand (execPath string , args []string , providerEnv map [ string ] string ) error {
248258 // Build full args (executable name + arguments)
249259 fullArgs := append ([]string {execPath }, args ... )
250260
251- // Get current environment
252- env := os .Environ ()
261+ // Get current environment and apply provider overrides
262+ env := mergeEnvironment ( os .Environ (), providerEnv )
253263
254264 // On Unix systems, use Exec to replace the current process
255265 // On Windows, Exec is not available, so we use StartProcess
@@ -280,12 +290,12 @@ func executeCommand(execPath string, args []string) error {
280290}
281291
282292// executeCommandWithWait executes a command and waits for it to complete, returning the exit code
283- func executeCommandWithWait (execPath string , args []string ) int {
293+ func executeCommandWithWait (execPath string , args []string , providerEnv map [ string ] string ) int {
284294 // Build full args (executable name + arguments)
285295 fullArgs := append ([]string {execPath }, args ... )
286296
287- // Get current environment
288- env := os .Environ ()
297+ // Get current environment and apply provider overrides
298+ env := mergeEnvironment ( os .Environ (), providerEnv )
289299
290300 // Use exec.Command to run the command and wait for completion
291301 cmd := & exec.Cmd {
@@ -310,6 +320,43 @@ func executeCommandWithWait(execPath string, args []string) int {
310320 return 0
311321}
312322
323+ // mergeEnvironment merges provider environment variables into the base environment.
324+ // Provider variables are prepended to existing values (for PATH-like variables) or set directly.
325+ func mergeEnvironment (baseEnv []string , providerEnv map [string ]string ) []string {
326+ if len (providerEnv ) == 0 {
327+ return baseEnv
328+ }
329+
330+ // Build a map of existing environment variables for easy lookup
331+ envMap := make (map [string ]string )
332+ for _ , e := range baseEnv {
333+ if idx := strings .Index (e , "=" ); idx != - 1 {
334+ key := e [:idx ]
335+ value := e [idx + 1 :]
336+ envMap [key ] = value
337+ }
338+ }
339+
340+ // Apply provider environment variables
341+ // For PATH-like variables (LD_LIBRARY_PATH, DYLD_LIBRARY_PATH), prepend the new value
342+ for key , value := range providerEnv {
343+ if existing , ok := envMap [key ]; ok && existing != "" {
344+ // Prepend new value to existing (for PATH-like variables)
345+ envMap [key ] = value + string (filepath .ListSeparator ) + existing
346+ } else {
347+ envMap [key ] = value
348+ }
349+ }
350+
351+ // Convert back to slice format
352+ result := make ([]string , 0 , len (envMap ))
353+ for key , value := range envMap {
354+ result = append (result , key + "=" + value )
355+ }
356+
357+ return result
358+ }
359+
313360// promptReshim prompts the user to run reshim after installing global packages
314361func promptReshim () {
315362 fmt .Fprintln (os .Stderr ) // Empty line for spacing
0 commit comments