haskell / directory

Platform-independent library for basic file system operations
https://hackage.haskell.org/package/directory
Other
58 stars 47 forks source link

Add support for `~/.local/bin` #124

Closed trskop closed 2 years ago

trskop commented 3 years ago

Proposed implementation for XdgBin based on the discussion in #119.

What makes ~/.local/bin different from others is that it doesn't have an environment variable associated with it. Not everyone is happy with that gitlab.freedesktop.org/xdg/xdg-specs/-/issues/14 and it is possible that the situation will change in the future. Notable example is ghcup, which uses XDG_BIN_HOME.

I've looked into tests that are available for XDG stuff and they don't seem to need any changes. Please, let me know if that's not true.

Rufflewind commented 3 years ago

Thank you for the PR!

trskop commented 3 years ago

Thanks for your reply @Rufflewind

I have some concerns regarding the use of %APPDATA% on Windows. Normally, programs expect to be able to drop a binary (.exe on Windows) into ~/.local/bin but on Windows putting .exe directly into %APPDATA% is not very idiomatic.

Similar argument can be made regarding other Windows defaults for XDG directories. The semantics do not match precisely as the XDG standard wasn't intended to have Windows alternatives.

My reasoning for choosing a default for ~/.loca/bin on Windows is that getXdgDirectory XdgBin will most commonly be used for installing binaries. User interaction with executables installed in ~/.local/bin is more about being it being in PATH. Systems that are XDG Base Directory specification compatible should (yes, the specification uses the word "should") ensure that ~/.local/bin is in PATH, when appropriate, however, Windows is not such system. To be honest it was mostly a toss between %APPDATA% and %LocalAppData%\Programs, which can be considered a better alternative for installing executables. What I like more about %APPDATA% is that it is not machine specific directory, i.e. shared in domain, which seems to be an assumption for ~/.local/bin too.

If aforementioned reasoning is not acceptable then I think that for those XDG directories that do not fit the pattern of XdgDirectory we may need to use a different approach. I'm not entirely convinced that OptXdgDirectory is it though. It seems very ad-hoc and it would produce Nothing iff os is Windows. Better UX for library users would be to suggest checking current OS and decide appropriately, e.g. by using os from System.Info. In which case it is possible to tell users to treat getXdgDirectory XdgBin as /opt-style directory when on Windows instead of /bin-style one.

For edge cases like XDG_RUNTIME_DIR it may make sense to have a separate function instead of trying to fit it into an existing pattern or a new pattern. For example:

getXdgRuntimeDir
  :: FilePath
  -- ^ Default value of runtime directory if @XDG_RUNTIME_DIR@ is not defined.
  -> FilePath
  -> IO FilePath

Similar approach can be taken for ~/.local/bin if we agree on it not fitting with the most common pattern.

Minor issue: It would be great to have a test case to cover this new feature on both POSIX and Windows.

I was looking at tests and hadn't seen anything appropriate that can be tested. Only thing that came to my mind is to test the definition, which is not a good unit test. Any suggestions on what should be tested?

Minor issue: changelog.md could be updated too.

That I can definitely do once we agree on an approach.

Rufflewind commented 3 years ago

I am fine with just providing a separate function:

getXdgBinDir :: IO (Maybe FilePath)

I don't think FilePath {-default-} -> IO FilePath is ideal. For the user it is strictly less flexible than IO (Maybe FilePath).

Rufflewind commented 2 years ago

Is there still interest in continuing this PR?

Rufflewind commented 2 years ago

Thanks for the PR. Closing due to inactivity. Let me know if you wish to reopen the PR.