Make Cargo obey platform-specific directory standards #2127

Closed
wants to merge 4 commits into
from

Projects

None yet
@tbu-
Contributor
tbu- commented Nov 9, 2015

Strategy for backward-compatiblity:

When checking for the relevant Cargo directories, check in the following
order of preference:

  1. Use the environment variable CARGO_HOME.
  2. Use the platform-specific directories if they exist.
  3. Use the legacy location (~/.cargo) if it exists.
  4. Fall back to the platform-specific directories if everything else fails.

The new platform-specific directories are as follows:

On Windows, use AppData\Local\Temp\Cargo for cache files (obtained via
GetTempPath), AppData\Roaming\Cargo for the config files
(FOLDERID_RoamingAppData) and AppData\Local\Programs\Cargo for
installed binaries (FOLDERID_UserProgramFiles).

On Unixy systems, use the XDG spec: ~/.cache/cargo for cache files,
~/.config/cargo for config, ~/.local/bin for installed binaries.

http://standards.freedesktop.org/basedir-spec/basedir-spec-0.8.html
http://www.freedesktop.org/software/systemd/man/file-hierarchy.html

On OS X, use ~/Library/Caches/Cargo for cache files, ~/Library/Cargo
for config files and ~/Library/Cargo/bin for binary files.

Fixes #1734. Fixes #1976.

@huonw huonw was assigned by rust-highfive Nov 9, 2015
@rust-highfive

Thanks for the pull request, and welcome! The Rust team is excited to review your changes, and you should hear from @huonw (or someone else) soon.

If any changes to this PR are deemed necessary, please add them as extra commits. This ensures that the reviewer can see what has changed since they last reviewed the code. The way Github handles out-of-date commits, this should also make it reasonably obvious what issues have or haven't been addressed. Large or tricky changes may require several passes of review and changes.

Please see the contribution instructions for more information.

@tbu-
Contributor
tbu- commented Nov 9, 2015

Probably doesn't compile on Windows, because the xdg crate probably doesn't: whitequark/rust-xdg#5.

@tbu-
Contributor
tbu- commented Nov 11, 2015

Passes all tests now, ready to get merged!

@steveklabnik
Contributor

Since XDG is higher priority than the original one, isn't that going to cause issues? People who work on systems which follow XDG are gonna see their existing ~/.cargo dissapear... no?

@tbu-
Contributor
tbu- commented Nov 11, 2015

The XDG only has higher priority if it exists (~/.cache/cargo). This could help with deprecating ~/.cargo completely in the future.

EDIT: Systems which follow XDG might have ~/.cache, but they won't have ~/.cache/cargo.

@alexcrichton alexcrichton assigned alexcrichton and unassigned huonw Nov 12, 2015
@alexcrichton
Member

Thanks for the PR @tbu-! It looks like there was also quite a bit of legwork in getting everything to work across all platforms, so thanks for that as well! Some thoughts of mine:

  • If we're going to knock this out, then I think it may be good to take care of #1976 along the way as well.
  • Is it standard to use XDG on systems like OSX and FreeBSD? I'm mostly worry about OSX, but this seems like a very Linux-specific concept. Although it works on OSX, I'm not sure if it's idiomatic.
  • I'm worried about the fragmentation this causes across platforms. It's no longer easy given an arbitrary system to find out where Cargo has placed its cache directory or where you should place configuration.
  • It looks like we'd be one of the first package managers to do something like this. None of bundler, npm, pypi, or rubygems seem to do anything related to this. Our target audience isn't always experienced linux folks who expect this behavior but often newbies who may not know where to probe to find Cargo-related files.
  • It'd be much nicer to use if cfg!(windows) instead of #[cfg(windows)] and it looks like the xdg crate only has one unix-specific import.
  • The xdg crate is a bit too eager to panic.

I wonder if it would be possible to have this still be opt-in, but perhaps have the opt-in to be very easy to set?

@tbu-
Contributor
tbu- commented Nov 12, 2015

Thanks for looking over the pull request!

If we're going to knock this out, then I think it may be good to take care of #1976 along the way as well.

I suppose, but I don't have a Windows machine right now.

Is it standard to use XDG on systems like OSX and FreeBSD? I'm mostly worry about OSX, but this seems like a very Linux-specific concept. Although it works on OSX, I'm not sure if it's idiomatic.

Yea, the points about OS X and *BSD are fair, I haven't researched the situation there yet.

I'm worried about the fragmentation this causes across platforms. It's no longer easy given an arbitrary system to find out where Cargo has placed its cache directory or where you should place configuration.

Fragmentation isn't really worse, you can find the configuration in ~/.config/cargo and the cache in ~/.cache/cargo, unless you set environment values, like before.

It looks like we'd be one of the first package managers to do something like this. None of bundler, npm, pypi, or rubygems seem to do anything related to this. Our target audience isn't always experienced linux folks who expect this behavior but often newbies who may not know where to probe to find Cargo-related files.

Update the tutorials to point to ~/.config/cargo instead of ~/.cargo/config (With a mention that the legacy location ~/.cargo/config is still supported).

I wonder if it would be possible to have this still be opt-in, but perhaps have the opt-in to be very easy to set?

I think making standard compliance an opt-in is basically not having standard compliance at all. The standards exist to give common behavior across many different programs, and if you have to configure each of them anyway, then the benefit of having that standard is lost.

The issues with the XDG crate (cfg!(windows) vs #[cfg(windows)] and the panic) can certainly be fixed.

@steveklabnik
Contributor

Yea, the points about OS X and *BSD are fair, I haven't researched the situation there yet.

I can't tell you about BSD, but for OSX: https://developer.apple.com/library/mac/documentation/FileManagement/Conceptual/FileSystemProgrammingGuide/FileSystemOverview/FileSystemOverview.html

TL;DR: very much not XDG.

@huonw
Member
huonw commented Nov 12, 2015
@alexcrichton
Member

@tbu-

Ah yeah sorry to be clear I'm not worried about fragmentation within a platform, but rather across platforms. For example we can't really just update the tutorials to list different paths because now it's a different path for every platform. In that sense I think the fragmentation gets worse because as someone who works across OSX/Windows/Linux I've now got to always be conscious of where I'm at if I want to find these directories.

@bors
Contributor
bors commented Nov 19, 2015

☔️ The latest upstream changes (presumably #2154) made this pull request unmergeable. Please resolve the merge conflicts.

@tbu-
Contributor
tbu- commented Nov 24, 2015

So, I researched a little and found out that the BSDs should probably get XDG handling, OS X caches go into ~/Library/Caches/Cargo and config into ~/Library/Cargo/. On Windows it'll be AppData\Roaming for the config and AppData\Local for the caches. What I'm still trying to figure out is where we should put the executables on OS X and Windows. Do you have ideas for that?

@alexcrichton
Member

I'm personally still worried about the fragmentation problem. It looks like this is basically going to end up with almost a different location for directories per OS rather than "windows" and "non windows", and at some point it seems like the benefit perhaps isn't that large?

This is why I was thinking that an opt-in may suffice for now in some form.

@tbu-
Contributor
tbu- commented Nov 30, 2015

@alexcrichton I guess if we want non-fragmentation, we should probably go for XDG on unixy systems (including Mac), and for AppData on Windows.

This would give us a pretty consistent story that interacts well with the OSs, as well as separating caches from configs.

@alexcrichton
Member

That seems like not a great situation to be in though, unfortunately. There's still fragmentation between Windows and non-Windows, and Cargo would be favoring Linux/Windows over all other OSes by saying they need to be slotted into one of those buckets. Overall it seems like it doesn't really reduce the net number of issues?

@tbu-
Contributor
tbu- commented Dec 1, 2015

Let's collect a list of advantages and disadvantages:

  1. ~/.cargo/ everywhere:
+ Cross-platform consistency
- Very unexpected for Windows users
  1. XDG on Unix, AppData on Windows
+ Cross-platform consistency among unixes
+ Clearly separates cache from config, helps backup tools
+ Uses the XDG standard on Unixes
+ Uses an expected directory on Windows
- Not the current solution -> needs code to maintain backward compatiblity for some time
- Not the preferred solution on Mac (but only on Mac, on BSDs, this is fine)
  1. XDG on Unixes, Apple-specific on Mac, AppData on Windows
Essentially same as 2)
- Less cross-platform consistency among unixes, might be weird when ssh'ing from machine to machine
+ Uses the preferred solution on Mac

So by just looking at the advantages/disadvantage (tell me if I missed any!), I'd say that 2) and 3) are both favorable to 1). In fact, the only advantage of 1) over 2) seems to be that there is cross-platform consistency between Windows and unixy operating systems, which I'd argue is very much not expected for Windows users.

@bluss
bluss commented Dec 2, 2015

Thanks for working on this! Following XDG is a huge win and it would be much nicer if all applications did this. Primarily the clean separation of cache vs user data (config and data). Especially since cargo does not clean up its old caches, having them separated out for easy & confident removal is a win for the user. (The user will be safer to know it's only cache).

@alexcrichton
Member

I think that if we take this route we'd want to do the "best thing for the platform" in each case, so I wouldn't take the route of XDG everywhere on Unix (ignoring what OSX conventions are). To me any fragmentation is just as bad as lots of fragmentation, so I'm not worried about the degree of fragmentation along those lines.

I also think that it may not quite be as black-and-white as listing out pros/cons and seeing which bucket is bigger. The existence of fragmentation can have a multiplicative effect where all of Cargo's decisions affect downstream users and such. For example anyone wanting to write a tool against Cargo's directory layout or something like that would end up having to work with all this logic somehow as well to work across platforms.

I'd be curious on some other opinions from @rust-lang/tools as well, I have a feeling that @wycats in particular may have thoughts on this.

@whitequark
Contributor

For example anyone wanting to write a tool against Cargo's directory layout or something like that would end up having to work with all this logic somehow as well to work across platforms.

Unless Cargo's directory layout is considered a stable interface, wouldn't any such tool have to invoke Cargo or use it as a library anyway?

@tbu-
Contributor
tbu- commented Dec 4, 2015

@alexcrichton I didn't want to suggest to compare the number of pros and cons, as they can certainly be split up in different ways. I do however, still think that the benefits of 2) and 3) outweigh the solution for 1), especially 2) which is basically a pure improvement IMO (I think that 1) is consistency at the cost of Windows users, because there is virtually no program that stores its configuration in something like ~/.appname on Windows).

@alexcrichton
Member

@whitequark perhaps yeah, but it's not unheard of to write a tool that lives for a few weeks or so (e.g. doesn't live until the end of time) and Cargo's layout would be "stable" within that time frame.

@whitequark
Contributor

@alexcrichton to rephrase, I feel that this would be best addressed by allowing to reuse Cargo's persistency layer, if a consideration at all

@brson
Contributor
brson commented Dec 4, 2015

I've been skeptical of using XDG in the past since dotfiles work everywhere, and the spec doesn't provide any motivation. I'd be very curious to know what XDG adoption looks like these days, whether it's a winning or losing standard (I still have lots of dotfiles and no XDG_* variables defined here in Ubuntu 14.04).

A big downside of supporting XDG with dotfile fallback is that users won't know where their stuff is.

I've rejected XDG for multirust before.

My inclination is to keep waiting.

@whitequark
Contributor

@brson Note that you would normally not have the XDG_* variables set on Linux since the defaults per spec are what most people want anyway.

I can see that pretty much every standard desktop application I use (on Debian) respects XDG, as well as some 3rd-party applications (Sublime Text), although many other 3rd-party ones don't (most games) and of course non-GUI tool authors don't feel compelled to follow XDG at all...

@bluss
bluss commented Dec 4, 2015

@brson Look in ~/.config, ~/.cache, ~/.local/share and see if there's anything there 😄 A well behaved program should respect it in modern Linux IMO (this is my general opinion, nothing to do with cargo, something I held before cargo existed). I developed XDG-compliant programs more than 5 years ago, so I don't see the reason to wait.

@brson
Contributor
brson commented Dec 4, 2015

@bluss Ah. On a desktop I do have those directories. On my headless machine only ~/.cache exists with only one file in it.

@nrc
Contributor
nrc commented Dec 6, 2015

I'm mildly in favour of this - it seems like an improvement and I would expect each platform to differ in this way so I'm not too worried about the fragmentation effect (it is of course not ideal). I would also be interested to know whether XDG is 'winning' though.

@bluss
bluss commented Dec 6, 2015

Fedora has had a goal to make its desktop applications adhere to it: https://fedoraproject.org/wiki/Features/XdgConfigDirs

So Fedora & GNOME is the bastion of support I guess, even though many others support it too: XDG_Base_Directory_support / Arch Wiki

@brson Main benefit is the user experience. Separating config, user data and caches makes cache and backup management much simpler. Cargo has data of all these three kinds, and a pretty large cache that you don't want to backup

I think the “is it winning” is not the right question to ask for two reasons, 1) there is no alternative standard and 2) creating a better user experience doesn't really have any drawbacks. Separating cache from config and data is something that should be done anyway. The ~/.cache directory is normally automatically skipped in the default configuration of many backup tools.

Cache and backup management seems to be a thing that's common to all programs and not just desktop applications.

Cargo could also adhere to the CACHEDIR.TAG spec directly to have its cache exempted from backup that way. This spec is supported by for example GNU Tar, an ubiquitous utility. Adhering to XDG Config Dirs and using ~/.cache by default would relieve cargo of making cache directory tags itself.

@alexcrichton
Member

@bluss I don't think it's 100% accurate to say there are no downsides, the lack of consistency across platforms and not knowing how to find the directory on an arbitrary platform without probing is a downside to me.

@bluss
bluss commented Dec 8, 2015

Yes, I understand. I wanted to underline that there are clear benefits of a better user experience too.

@alexcrichton
Member

We chatted about this in the @rust-lang/tools triage meeting today, and the consensus was that we probably want to move forward with this. @nrc brought up an excellent point that in the long run most tools end up doing the most-platform-specific behavior as there's more and more pressure to do so. Additionally, it generally tends to mesh better with user's expectations.

@brson, curious what you think on that?


One part we did talk about though was that we'd want to see the OSX/Windows functionality here fleshed out before landing. @vadimcn I believe had a few more details on what we may want to do on Windows.

@tbu-
Contributor
tbu- commented Dec 16, 2015

That's great to hear.

My plan was to use ~/AppData/Roaming/Cargo/ for the config (this is the directory that gets shared when you log in on different computers on the same domain) and use ~/AppData/Local/Cargo/ for the caches.

On OS X I would use ~/Library/Cargo/ for the configs and ~/Library/Caches/Cargo/ for the caches.

What I couldn't figure out was where to place the executables on either Windows or OS X, so if you have ideas concerning this, please tell me!

@vadimcn
vadimcn commented Dec 16, 2015

Just want to note that on Windows you are supposed to use the SHGetKnownFolderPath API, rather than hard-coding a specific path.

The standard location for per-user executables is $(FOLDERID_UserProgramFiles) which currently resolves to %LOCALAPPDATA%\Programs. Before Windows 7 there was no standard location, most apps installed themselves somewhere under %LOCALAPPDATA%.

As for the cache directory, I wonder if %TEMP%\Cargo\Cache would be a better location, since it can be automatically cleaned-up by the Disk Cleanup Wizard upon running out of disk space.

@tbu-
Contributor
tbu- commented Dec 16, 2015

@vadimcn Sure, we're not hardcoding the path on Linux either. Thanks for the place for executables!

It seems that %TEMP% cannot be accessed via that API though. What does it typically resolve to? Is it user-specific or systemwide?

@vadimcn
vadimcn commented Dec 17, 2015

@tbu-: for that Windows provides GetTempPath. Normally, it's per-user, pointing to %APPDATA%\Local\Temp.

@tbu-
Contributor
tbu- commented Dec 17, 2015

Hm. I can't find anything regarding the lifetime of files placed there on the documentation page. Ideally it'd be preserved by reboots, ignored by backup tools and could be cleaned by the Disk Cleanup Wizard.

@vadimcn
vadimcn commented Dec 17, 2015

All of the above is true, in my experience.

@alexcrichton
Member

@tbu- for binaries on OSX using something like ~/Library/Cargo/bin seems like it should be fine as a fallback at least

@tbu- tbu- changed the title from Make Cargo XDG-compliant (on non-Windows systems) to Make Cargo obey platform-specific directory standards Dec 18, 2015
@tbu-
Contributor
tbu- commented Dec 18, 2015

@alexcrichton Factored out the platform-specific code into a library, added Windows and OS X support and rebased it onto master.

@alexcrichton
Member

In dirs, could the errors on Windows be propagated upwards instead of being thrown away?

I also had some concerns above about how the xdg crate is a little eager when panicking, could those be addressed as well?

@tbu- tbu- referenced this pull request in whitequark/rust-xdg Dec 19, 2015
Merged

Proposal for error propagation #11

@bors
Contributor
bors commented Dec 21, 2015

☔️ The latest upstream changes (presumably #2237) made this pull request unmergeable. Please resolve the merge conflicts.

@brson
Contributor
brson commented Dec 22, 2015

I'm still concerned about the confusion it will cause for minimal benefit. The story for cargo install is going to be more complicated in particular - there are three different places one must know to look depending on platform.

Is there going to be any upgrade path? What happens to the existing .cargo folders?

@nrc
Contributor
nrc commented Dec 22, 2015

there are three different places one must know to look

Can we guard against by having a way of finding out where Cargo installed? cargo install --where-did-you-put-my-binary. I much prefer being able to query stuff like this rather than having to know even a single thing.

Is there going to be any upgrade path? What happens to the existing .cargo folders?

Could questions, we should have answers!

@alexcrichton
Member

Cargo will inform you to add a directory to your PATH if it's not already in there during cargo install, so via that you can discover where everything's being installed (unless you already have it in your PATH in which case it may not be that relevant?).

I do agree though that this puts a lot more pressure on a feature where through the CLI you can learn about the home directory Cargo thinks it's using.

For an upgrade path, this PR currently prioritizes $HOME/.cargo if it exists (e.g. it keeps using it). Only if it doesn't already exist does a new home get used.

@brson
Contributor
brson commented Dec 30, 2015

Here's another problem. multirust/rustup.exe control $CARGO_HOME. With today's multirust, these new directories will not be used. That's fine.

With the design of rustup.exe though, we're expecting all Cargo's to share their metadata, and for rustup.exe to know where that is. This means that either rustup.exe is going to have to preinitialize ~/.cargo to force all cargos to use the old scheme, or that it will have to not be backwards compatible with cargos that don't support the new scheme.

Part of the rustup.exe plan was also to share the $CARGO_HOME directory, putting .rustup under $CARGO_HOME/.rustup (basically, everything Rusty was to go under $CARGO_HOME). With this scheme I no longer think this is a good idea, partly because it's harder and less reliable to find cargo's metadata, partly because it's split out by kind of metadata, so putting other programs dotfiles in one of the various metadata locations doesn't make sense.

@nrc
Contributor
nrc commented Dec 30, 2015

@brson I don't know enough about the rustup.exe plan to be sure, but it sounds to me that having "everything Rusty" in one place is not a viable long term plan. People will want strange configurations for all kinds of strange reasons and there will be strange platform-specific requirements which we don't know about yet.

IMO, a programming language should try to accommodate the platform it is running on, not try to layer it's own platform on top. Java tried this and despite being wildly successful, this was a pain point which hindered use and something they moved away from more and more as time went by.

@bluss
bluss commented Jan 1, 2016

Is there an alternative way to solve the cache directories issue? We want it to be simple to purge cargo cache and to exclude it from backups. For N applications it really is easier if they all use the same cache root than having to add N configuration items to your backup tool.

@matklad
Contributor
matklad commented Jan 1, 2016

For an upgrade path, this PR currently prioritizes $HOME/.cargo if it exists (e.g. it keeps using it).

This may make it difficult to remove ~/.cargo eventually. Another option is to move stuff from ~/.cargo to ~/.cache / ~/.config on the first launch and add some symbolic links for backwards compatibility.

@tbu-
Contributor
tbu- commented Jan 2, 2016

@matklad That's very intrusive. A better method would be to warn in future if you use ~/.cargo and deprecate it entirely one day.

@alexcrichton
Member

@brson

Hm yeah that's a good point thinking about rustup.exe plans. I think it may be able to mesh well here, however? For a brand new system, this basically means that Cargo's "home directory" would need to be discovered though the same logic that Cargo has (e.g. this dirs crate). I'd imagine that rustup could either use this or just always set CARGO_HOME whenever it delegates to a Cargo binary.

It may not be particularly crucial that rustup installs itself to a globally known location (e.g. ~/.foo unconditionally) because one of the main points of rustup.exe is "you don't have to worry about this". It'll add itself to PATH as necessary and such.

@nrc

While I agree that we should accomadate the platform at hand, I don't think that should ever come at the cost of user experience. Along those lines I wouldn't take that as an ironclad guiding principle. In this case with Cargo, however, and I think with rustup as well, we can get this kind of configuration with little-to-no cost in terms of experience.

@brson
Contributor
brson commented Jan 17, 2016

I'm not clear on how .cargo/config works in this scheme. Since .cargo/config is searched for up the tree, and used to override single projects, would the best practice be to use .cargo/config for override single projects, but use e.g. AppData\Roaming\Cargo\.config for overriding all projects?

How does AppData\Roaming\Cargo\.config behave? In the dotfile world doesn't this file override everything 'beneath' it in the file tree. I would imagine people don't do their development in AppData\Roaming.

If you don't want to deal with the platform-specific config and just put it in ~/.cargo/config is cargo going to get confused about whether it should use ~/.cargo for all its metadata, or will it ignore ~/.cargo/config when deciding which metadata format to use?

@tbu-
Contributor
tbu- commented Jan 18, 2016

Should I duplicate the path finding functions for the tests or should I make them less fine-grained?

@alexcrichton
Member

@brson we've actually already got some custom code to handle that case (e.g. the "home directory" is special).

If you put configuration in ~/.cargo/config Cargo will just use it if you're working anywhere under ~ which is pretty likely. That'll just have more precedent than Cargo's platform-specific home directory.

@alexcrichton
Member

@tbu- I'm not sure I understand? There are no tests here?

@tbu-
Contributor
tbu- commented Jan 19, 2016

The tests are still failing because they check for the old location, e.g. tests/test_cargo_install:48-49. I'm unsure how to fix this, should I call the paths function from the tests or should I replicate that functionality within the tests?

@alexcrichton
Member

It's fine to just set CARGO_HOME for those tests

@bors
Contributor
bors commented Jan 19, 2016

☔️ The latest upstream changes (presumably #2282) made this pull request unmergeable. Please resolve the merge conflicts.

@tbu-
Contributor
tbu- commented Jan 25, 2016

@alexcrichton I have rebased the pull request and fixed the tests. Should I squash the commits?

@bors
Contributor
bors commented Jan 25, 2016

☔️ The latest upstream changes (presumably #2297) made this pull request unmergeable. Please resolve the merge conflicts.

tbu- added some commits Nov 9, 2015
@tbu- tbu- Make Cargo obey platform-specific directory standards
Strategy for backward-compatiblity:

When checking for the relevant Cargo directories, check in the following
order of preference:

1) Use the environment variable `CARGO_HOME`.
2) Use the platform-specific directories if they exist.
3) Use the legacy location (~/.cargo) if it exists.
4) Fall back to the platform-specific directories if everything else fails.

The new platform-specific directories are as follows:

On Windows, use `AppData\Local\Temp\Cargo` for cache files (obtained via
`GetTempPath`), `AppData\Roaming\Cargo` for the config files
(`FOLDERID_RoamingAppData`) and `AppData\Local\Programs\Cargo` for
installed binaries (`FOLDERID_UserProgramFiles`).

On Unixy systems, use the XDG spec: `~/.cache/cargo` for cache files,
`~/.config/cargo` for config, `~/.local/bin` for installed binaries.

http://standards.freedesktop.org/basedir-spec/basedir-spec-0.8.html
http://www.freedesktop.org/software/systemd/man/file-hierarchy.html

On OS X, use `~/Library/Caches/Cargo` for cache files, `~/Library/Cargo`
for config files and `~/Library/Cargo/bin` for binary files.

Fixes #1734. Fixes #1976.
21416c5
@tbu- tbu- Add better error handling for the new directory locations ef7ba64
@tbu- tbu- Fix handling of `CARGO_HOME` 6cdef4a
@tbu- tbu- Use `CARGO_HOME` to test Cargo across different OSs
3139376
@alexcrichton
Member

Ah yes, sorry I meant to get back to this a little earlier. I had a chance to talk with @wycats about this recently and here were some thoughts we had (in addition to what's previously been mentioned here)

  • It's suspected that the "convention" of putting things in ~/Library on OSX is all-but-nonexistent, and this is likely to extend to other platforms where the "convention" here isn't necessarily universally adhered to because there unfortunately isn't necessarily a convention one way or another.
  • One very nice part about ~/.cargo is that it's very nice to know how to "blow everything away and start from scratch". With a scheme that puts directories in a few places this gets a little more questionable.
  • For external tooling, it's likely required to introduce a cargo home command in tandem with this. And something I also just realized is that on Linux there will no longer be a "home directory" for Cargo, right? It's sharded in a few locations? That would make this cargo home command a little more interesting...
  • Creation and usage of ~/.program-name is almost universal throughout various apps on Linux. This means that flavorful environments (e.g. things like Heroku, docker, qemu, stripped-down-scenarios, etc) which aren't your standard desktop will generally try to ensure that this sort of location "Just Works" to be maximally compatible with existing programs. By moving to a custom location, it becomes less likely that Cargo will work "out of the box" if it tries to put configuration or caches in a location that's, for example, read only, not mounted, etc.
  • It may not always be expected that the Cargo we ship adheres to these conventions. Arguably the Cargo shipped by Linux distros should be configured to support the various local configuration that is expected, but not necessarily what we ship ourselves. This would entail a variety of ./configure flags, perhaps along the lines of "choose this spec" or "always choose this location" or something like that.

Overall it sounded like @wycats was pretty hesitant to move forward on this, and I think some of the new points brought up here are also quite persuasive.

@tbu-
Contributor
tbu- commented Jan 25, 2016

I don't know about OS X.

One very nice part about ~/.cargo is that it's very nice to know how to "blow everything away and start from scratch". With a scheme that puts directories in a few places this gets a little more questionable.

One very nice part about putting the cache into the folders designated for caches means that existing tools (backup, etc.) work at all together with Cargo. It's true that restarting from scratch might get harder, but if we introduce a cargo home subcommand, then it's not really a problem anymore. Also, what would you use on Windows? Using .cargo is pretty much out of question there (IMO), because that's using a unixy paradigm on a foreign system.

Creation and usage of ~/.program-name is almost universal throughout various apps on Linux. This means that flavorful environments (e.g. things like Heroku, docker, qemu, stripped-down-scenarios, etc) which aren't your standard desktop will generally try to ensure that this sort of location "Just Works" to be maximally compatible with existing programs. By moving to a custom location, it becomes less likely that Cargo will work "out of the box" if it tries to put configuration or caches in a location that's, for example, read only, not mounted, etc.

I really see no reason why the XDG directories would work any less "out of the box" than "~/.cargo". Can you elaborate?

It may not always be expected that the Cargo we ship adheres to these conventions. Arguably the Cargo shipped by Linux distros should be configured to support the various local configuration that is expected, but not necessarily what we ship ourselves. This would entail a variety of ./configure flags, perhaps along the lines of "choose this spec" or "always choose this location" or something like that.

Yes, it's pretty much us ("the Cargo developers") who are expected to make Cargo adhere to standards. E.g.: https://wiki.archlinux.org/index.php/XDG_Base_Directory_support#Supported.

@alexcrichton
Member

Yeah we definitely agree that there are some benefits (like with backup solutions), but the question is whether it's worth the tradeoffs. If no one's really sure of what happens on OSX, then we should probably continue doing what we're doing today there. On Windows it sounds like we're also a little unsure? There doesn't seem to be a clear answer to "yes this is where the directories should be", but conversely there's also nothing saying "no, you should never put directories there".

I really see no reason why the XDG directories would work any less "out of the box" than "~/.cargo". Can you elaborate?

I think @wycats may be able to add more here, but my understanding is that it's just "one more layer" which may not be guaranteed to work. It's often difficult to imagine these sorts of situations, but there are so many embedded flavors of Linux around that any configuration is bound to exist somewhere, and there are bound to exist configurations where xdg doesn't work but just using the home directory does.

Put another way, the use of XDG only seems "clearly correct" for distributions themselves, not necessarily for any Cargo binary running on a linux kernel.

Yes, it's pretty much us ("the Cargo developers") who are expected to make Cargo adhere to standards. E.g.: https://wiki.archlinux.org/index.php/XDG_Base_Directory_support#Supported.

Unfortunately I don't think link does much to answer the question, though. There's nothing indicating that this shouldn't be an off-by-default but turned-on-by-packagers kind of behavior.

@whitequark
Contributor

and there are bound to exist configurations where xdg doesn't work but just using the home directory does

But, as used by cargo, both strategies "just use the home directory", at least for the user data. There's nothing special about ~/.local or ~/.config that fundamentally differentiates it from ~/.cargo.

@Alexander--

I feel, that this PR is missing a point. Standardized locations aren't used, because they are standard, but because they are convenient:

  • Windows standard directories aren't meant for human users (look at those horrific paths!), but for utilities (see previous comments) to manage caching, domains and app uninstallation. This is handy, but does not make users' lives much easier.
  • In contrast, XDG user directories aren't touched by package managers. They are meant for users themselves (e.g. they make it possible to quickly wipe ~/.cache and de-bloat HOME)
  • I am not very knowledgeable about Mac OS X, but the situation there is, probably, similar; nobody just puts things somewhere because that's standard.

As such, I do not see any reason to have distinct cargo_bin. A user-configurable CARGO_HOME is enough. Moving things to ~/.local/bin just makes them harder to find.

Anyway, what is there do disagree about? All systems, supported by Rust, have symbolic links.

IMO, it makes most sense to leave current layout in place, but replace some of dirs by symlinks to more fitting places (~/.config, ~/.cache etc).

If done, this should be clearly communicated to users and, probably, followed by creation of uninstaller to remove those directories (because simple rm -r ~/.cargo won't do anymore). For this reason, I do not thing, that anything besides cache directory should ever be moved by default or without notifying a user during installation.

@tbu-
Contributor
tbu- commented Jan 29, 2016

@alexcrichton I believe on Windows the situation is clearly: Don't put the application data (caches) into the home directory. AppData is the way to go there, and the added Temp (which might present the uncertainty), is just an extra to ensure that it can be cleaned by the disk something wizard.

@tbu-
Contributor
tbu- commented Jan 29, 2016

Unfortunately I don't think link does much to answer the question, though. There's nothing indicating that this shouldn't be an off-by-default but turned-on-by-packagers kind of behavior.

Well, since Arch Linux generally ships the exact upstream, it's clear that they want upstream to support XDG.

@tbu-
Contributor
tbu- commented Jan 29, 2016

I think @wycats may be able to add more here, but my understanding is that it's just "one more layer" which may not be guaranteed to work. It's often difficult to imagine these sorts of situations, but there are so many embedded flavors of Linux around that any configuration is bound to exist somewhere, and there are bound to exist configurations where xdg doesn't work but just using the home directory does.

I'd like to hear more about that, because currently this is pretty unclear to me. On a normal system, the "XDG" directories are just longer path names, namely "~/.cache/cargo", so it is supported exactly when the home directory is known.

@tbu-
Contributor
tbu- commented Jan 29, 2016

As such, I do not see any reason to have distinct cargo_bin. A user-configurable CARGO_HOME is enough. Moving things to ~/.local/bin just makes them harder to find.

If you have them in ~/.local/bin, you don't have to configure your path to include every programming language package manager you have.

Anyway, what is there do disagree about? All systems, supported by Rust, have symbolic links.

Except for Windows, where they can only be created by administrators.

IMO, it makes most sense to leave current layout in place, but replace some of dirs by symlinks to more fitting places (~/.config, ~/.cache etc).

This sounds like a good compromise to me (except that it still clutters the home directory with .cargo), but still, I really like that idea.

@retep998
Member

While we can't create symbolic links on Windows, we can create directory junctions, which as far as I can tell are just as good.

@tbu-
Contributor
tbu- commented Jan 29, 2016

Ah, didn't know these.

@Alexander--

If you have them in ~/.local/bin, you don't have to configure your path to include every programming language package manager you have.

Sigh. I am unaware of any part of XDG spec, that specifically suggests putting binaries somewhere. I am also unaware of any distribution, adding anything within HOME to default user PATH (please correct me if I am wrong).

Putting binaries in the same place under HOME may be convenient, but only as long as you do not make that into standard, and I would strongly oppose any such standard. It would be as insecure as adding . (e.g. the current directory) to PATH—too easy to screw up. Some well-meant app would cleverly put something there without my knowledge, and the next command I type leads to unpredictable results. There is a reason, why people kept using /usr/local/bin for binaries even when the threat of viruses etc. have been nearly non-existent.

For those reasons I would prefer Cargo to request elevation and put any executables under /usr/local/bin by default, and only symlink there from cargo/bin. If that is not possible/feasible, put them under cargo/bin, but please do not pick any directory path, too long to type with each command or too well hidden to quickly find in file manager.

@Alexander--

While we can't create symbolic links on Windows, we can create directory junctions, which as far as I can tell are just as good.

Yes, the exact type of link to use in this case seems irrelevant.

@bors
Contributor
bors commented Jan 30, 2016

☔️ The latest upstream changes (presumably #2339) made this pull request unmergeable. Please resolve the merge conflicts.

@tbu-
Contributor
tbu- commented Jan 31, 2016

@Alexander-- Not part of the XDG spec, but the second link in the PR: http://www.freedesktop.org/software/systemd/man/file-hierarchy.html.

@alexcrichton
Member

This is an example of possible breakage from following these sorts of environment variables. It could be the case that someone invokes cargo with a new HOME variable expecting output to go in that location, but other environment variables (not specific to cargo) can end up thwarting that.

@tbu-
Contributor
tbu- commented Feb 1, 2016

Mh, fair enough, that's definitely a breakage from starting to follow XDG specifications where you previously did not. "The sooner the better?" Your link might even provide some more motivation, even git is doing it (which definitely isn't a desktop application).

@brson
Contributor
brson commented Feb 5, 2016

To me, being able to backup your cargo folder without copying cache files is the best reason to want this, and that could be achieved by changing the cache location to be platform-specific, possibly optionally. There's less reason to care where cargo stores its internal cache than its configuration.

It would be as insecure as adding . (e.g. the current directory) to PATH—too easy to screw up. Some well-meant app would cleverly put something there without my knowledge, and the next command I type leads to unpredictable results.

@Alexander-- I like this point, that encouraging $PATH to include somewhere user-writable weakens security (probably, I'm not sure). I assume that there are precedents in dynamic language package managers that default to non-global installation, but don't know that.

We're definitely are encouraging $CARGO_HOME/bin to be part of the search path. Even if it's not, cargo will run anything there that starts with cargo-, and multirust installs binaries to user-writable places. There are several opportunities to inject code into Rust if you have local access.

@brson brson referenced this pull request in brson/multirust Feb 5, 2016
Open

Add support for the XDG Base Directory Specification #104

@andrewtj
andrewtj commented Feb 6, 2016

It'd be strange to use Cocoa conventions on OS X for something that isn't built with Cocoa and isn't pretending to be a native .app.

@Luthaf
Luthaf commented Mar 2, 2016

If no one's really sure of what happens on OSX, then we should probably continue doing what we're doing today there

It'd be strange to use Cocoa conventions on OS X for something that isn't built with Cocoa and isn't pretending to be a native .app.

Yeah, on OSX, ~Library is only used by graphical applications. Command-line applications usually use the same directory structure as on Linux. That is also what brew and brewed command-line tools do.

@MagaTailor

I've just discovered this PR; on Linux I like the old behaviour better (being able to wipe or backup a single directory) so hopefully it all ends up on an opt-in/opt-out basis.

A use case on an SD based ARM system - operate entirely in ramdisk after decompressing a cargo tarball (.cargo contains everything incl. overrides) then just wipe the directory. Much faster and doesn't trash the card.

@tbu-
Contributor
tbu- commented Mar 29, 2016

@petevine It's opt-out, you can use the environment variable CARGO_HOME.

@tbu-
Contributor
tbu- commented Mar 29, 2016

@alexcrichton What's the status of this pull request? It seems that there's quite some controversy on changing the Linux behavior. Could we land the Windows version? The situation there is worse than the Linux one: We use the standards from a different platform (dot directories, which don't even interact correctly with the Windows Explorer, e.g. you can't name a file with a leading dot, see below). See also https://internals.rust-lang.org/t/beta-testing-rustup-rs/3316/21.

@retep998
Member

@tbu- Of course you can name a file with a leading period, you just have to trick explorer into doing it by naming it .foo. and it'll automatically convert it to .foo and work just fine.

@tbu-
Contributor
tbu- commented Mar 29, 2016

@retep998 Oh, nice trick. I did not know that one when I tried to create .gitignores. :)

@brson brson referenced this pull request in rust-lang-nursery/rustup.rs Apr 5, 2016
Open

Consider moving to platform-specific configuration directories #247

@Screwtapello

Some people in this thread have wondered whether Cargo would be the first package-manager to follow the XDG spec for per-user installation, and whether that would cause user confusion. For what it's worth, Python has looked for installed libraries in ~/.local since Python 2.6 (2013), and the Python package manager ("pip") has a ticket for installing there by default. Although that change hasn't landed in the official tree, apparently Ubuntu have already patched their build and Debian will have the same change soon. Even without that change, pip stores its config in ~/.config and caches downloaded packages in ~/.cache (both since the end of 2014).

As for ~/.local/bin not being on the default $PATH, apparently it is in Fedora, there's a ticket to make the same change in Debian.

@notriddle

I think @wycats may be able to add more here, but my understanding is that it's just "one more layer" which may not be guaranteed to work. It's often difficult to imagine these sorts of situations, but there are so many embedded flavors of Linux around that any configuration is bound to exist somewhere, and there are bound to exist configurations where xdg doesn't work but just using the home directory does.

You expect people to be using Cargo, a program that exists to download source code and drive a compiler, on embedded controllers?

@tbu-
Contributor
tbu- commented Jul 16, 2016

@notriddle The standard uses a hardcoded directory .config unless an environment variable is set. It's unclear which of these steps shouldn't work on "embedded Linux".

@frewsxcv
Member
frewsxcv commented Jul 16, 2016 edited

On OS X, use ~/Library/Caches/Cargo for cache files, ~/Library/Cargo
for config files and ~/Library/Cargo/bin for binary files.

I'm on OS X. How is this an improvement? I don't really care where my cache files end up, but what's the justification for moving my config files out of ~/?

@notriddle

The standard uses a hardcoded directory .config unless an environment variable is set. It's unclear which of these steps shouldn't work on "embedded Linux".

I don't understand why people are concerned about cargo working on embedded Linux anyway. You need to be able to run the resulting binaries, but this won't affect them.

@tbu-
Contributor
tbu- commented Jul 16, 2016

@frewsxcv These paths would still be inside your home directory (note the ~, it stands for the home directory of the current user). But you should probably rather look at the RFC for discussion: rust-lang/rfcs#1615.

@frewsxcv
Member

These paths would still be inside your home directory

I meant directly in the home directory, not a subdirectory.

@jan-hudec

@frewsxcv,

I meant directly in the home directory, not a subdirectory.

Things are never installed directly in the home directory. Currently they are installed in subdirectory called ~/.cargo. That is the old Unix ad-hoc approach that lead to zillions of .something files and directories in your home. The proposal is to instead put them under ~/Library, which is where MacOS native applications put things for sake of consistency (with other applications on each platform rather than between platforms, because platforms are not consistent with each other anyway). and to avoid adding to that zillion of .something items.

@tbu-
Contributor
tbu- commented Jul 26, 2016

@jan-hudec Please go to rust-lang/rfcs#1615, the discussion is happening there.

@linkmauve linkmauve referenced this pull request in japaric/xargo Sep 26, 2016
Closed

Replace $HOME/.xargo with $XDG_DATA_HOME/xargo #46

@alexcrichton
Member

Closing in favor of the RFC for now (clearing out the queue)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment