Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Sandbox commands should temporarily add .cabal-sandbox/bin to PATH #1120

Closed
23Skidoo opened this issue Nov 17, 2012 · 19 comments · Fixed by #1122
Closed

Sandbox commands should temporarily add .cabal-sandbox/bin to PATH #1120

23Skidoo opened this issue Nov 17, 2012 · 19 comments · Fixed by #1122
Assignees

Comments

@23Skidoo
Copy link
Member

Some libraries (e.g. wx) use custom preprocessors during the build process. When such libraries are installed into the sandbox, the build fails because the required executables are missing.

We will need to add a cross-platform setEnv to Compat, because it's missing from System.Environment. We can use an existing implementation by @sol, which he proposed for inclusion in base.

@ghost ghost assigned 23Skidoo Nov 17, 2012
@sol
Copy link
Member

sol commented Nov 17, 2012

BTW: The existing implementation for setEnv from the unix package uses putEnv on some (exotic?) systems, and putEnv is severely broken (see GHC #7342).

@sol
Copy link
Member

sol commented Nov 17, 2012

I haven't looked at any code, but I think if it works to just pass a modified environment when forking the process, then this would be preferable.

@23Skidoo
Copy link
Member Author

I haven't looked at any code, but I think if it works to just pass a modified environment when forking the process, then this would be preferable.

Since we don't have a Shell monad yet, this will be much more intrusive than just calling setEnv once.

@23Skidoo
Copy link
Member Author

BTW: The existing implementation for setEnv from the unix package uses putEnv on some (exotic?) systems

I removed the dependency on unix and am calling setenv directly:

foreign import ccall unsafe "setenv"
   c_setenv :: CString -> CString -> CInt -> IO CInt

Do you know which systems don't support setenv?

@sol
Copy link
Member

sol commented Nov 17, 2012

Hm, not sure. I think the type is also different on some systems.

@23Skidoo
Copy link
Member Author

I think the type is also different on some systems.

This is how setEnv is defined in the unix package:

setEnv :: String -> String -> Bool {-overwrite-} -> IO ()
#ifdef HAVE_SETENV
setEnv key value ovrwrt = do
  withFilePath key $ \ keyP ->
    withFilePath value $ \ valueP ->
      throwErrnoIfMinus1_ "setenv" $
        c_setenv keyP valueP (fromIntegral (fromEnum ovrwrt))

foreign import ccall unsafe "setenv"
   c_setenv :: CString -> CString -> CInt -> IO CInt
#else
setEnv key value True = putEnv (key++"="++value)
setEnv key value False = do
  res <- getEnv key
  case res of
    Just _  -> return ()
    Nothing -> putEnv (key++"="++value)
#endif

@sol
Copy link
Member

sol commented Nov 17, 2012

Yes, I think you are right. Only unsetEnv has a different type on some systems.

@sol
Copy link
Member

sol commented Nov 17, 2012

Here is what Git uses: https://github.com/git/git/blob/master/compat/setenv.c

The only "ugly" thing with this implementation is that it leaks memory, but I think this is of no practical importance.

@tibbe
Copy link
Member

tibbe commented Nov 17, 2012

I'm a bit uncomfortable adding with adding things to the system path and not removing them again (see my comment on the pull request). What if some non-sandbox code that runs some time later during the cabal process' lifetime executes some other command? That command might now look for binaries in the wrong place.

@23Skidoo
Copy link
Member Author

@tibbe OK, I'll fix that.

@23Skidoo
Copy link
Member Author

What if some non-sandbox code that runs some time later during the cabal process' lifetime executes some other command? That command might now look for binaries in the wrong place.

Fixed.

@23Skidoo
Copy link
Member Author

@sol

Here is what Git uses: https://github.com/git/git/blob/master/compat/setenv.c

Git is LGPL, so, IIUC, we can't just copy their code.

@sol
Copy link
Member

sol commented Nov 17, 2012

I think that code is broken. AFAIK, getSearchPath looks at PATH.

Personally, I'd always write tests to ensure that my code behaves as expected.

@23Skidoo
Copy link
Member Author

@sol

AFAIK, getSearchPath looks at PATH.

Yes.

-- | Get a list of filepaths in the $PATH.
getSearchPath :: IO [FilePath]
getSearchPath = fmap splitSearchPath (getEnv "PATH")

I think that code is broken.

Why?

@sol
Copy link
Member

sol commented Nov 17, 2012

@23Skidoo Oh, sorry. I really missed the delete while skimming over the code. I think you can still trim it down to something like (untested):

withSandboxBinDirOnSearchPath :: FilePath -> IO a -> IO a
withSandboxBinDirOnSearchPath sandboxDir action = bracket addBinDir (setEnv "PATH") (const action)
  where
    addBinDir :: IO ()
    addBinDir = do
      let sandboxBin = sandboxDir </> "bin"
      oldPath <- getEnv "PATH"
      let newPath = sandboxBin ++ (searchPathSeparator:oldPath)
      setEnv "PATH" newPath
      return oldPath

This does not have the exact same semantics, though. The result is different if action modifies the path (which it hopefully does not).

@23Skidoo
Copy link
Member Author

The result is different if action modifies the path.

Yes, that's why I implemented it this way.

@sol
Copy link
Member

sol commented Nov 17, 2012

@23Skidoo But shouldn't that be delete (sandboxDir </> "bin") ? Or did I miss something else?

@23Skidoo
Copy link
Member Author

@sol Nice catch, thanks!

23Skidoo added a commit to 23Skidoo/cabal that referenced this issue Nov 17, 2012
@sol
Copy link
Member

sol commented Nov 17, 2012

@23Skidoo My point was really about testing. Once you have a proper testing infrastructure in place writing a test for that function takes almost no time, guarantees correctness and spares you from wrong accusations ;).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants