-
Notifications
You must be signed in to change notification settings - Fork 17.7k
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
proposal: os: add UserConfigDir #29960
Comments
Forgot to mention: happy to work on this myself early in the 1.13 cycle if the proposal gets accepted. |
The directory on Plan 9 is $home/lib. |
I was referring to how |
@mvdan, yes but Rob's point is that the config dir is just $home/lib (not $home/lib/config). There's not an obvious cache dir on Plan 9 and I abused $home/lib by making a cache subdirectory. Anyway... We chatted about this at proposal review, and UserConfigDir seems fine. None of us can explain what UserDataDir would mean or be appropriate for vs $HOME, so let's be sure not to do that one. :-) Marking approved for UserConfigDir. |
Ah, I understand now. I guess we could always use
I personally tend to not find I'll send a CL shortly, so that it can be reviewed early during the cycle. |
Change https://golang.org/cl/160877 mentions this issue: |
FWIW, there's not much to discuss. The idea of a user config dir is well-defined on Plan 9 and is |
One important detail of the XDG directory spec is that it permits a list of other search directories specified in There is precedence for having multiple search locations on non-Linux platforms, too (e.g. /Library/Preferences on Mac). |
@zombiezen note that we're not implementing XDG, and that the existing UserCacheDir doesn't use directory lists either. This is not to say they'll never be supported, but this proposal is simply about mirroring UserCacheDir with its config counterpart. |
I understand, but I think the situation is slightly different. Cache directories are typically written to by the application, where as configuration directories are typically read from by the application. As such, it seems reasonable to me to surface the directories as a sequence of paths instead of just a single path. |
Sure, feel free to file a separate issue or proposal once the current proposal has been implemented. If we were to follow XDG more closely, I presume we'd want to do so consistently, so the change doesn't belong with this proposal. I also presume there'll be some discussion for and against the feature, and I don't think this accepted proposal is the right place. |
I'm not against this feature (apologies if my remarks came across that way). I wrote the My concern here is that if this function only returns one directory that most Go applications won't bother to call a second function to read the other directories, and thus continue to propagate a common issue in XDG support I've seen (e.g. Git's support) where they only consult a single directory. This would also affect non-Linux OSes like macOS which should also read from @mvdan, how would you envision multiple configuration directories being surfaced? |
@zombiezen do Mac users generally obey XDG? If not, how can Mac have multiple config dirs? In my current CL, all platforms use exactly one directory, and as far as I'm aware, that's correct (ignoring I envision multiple configuration directories not to be surfaced. Surfacing multiple directories would make the API more complex, and it would break consistency with You can argue that this is encouraging developers to not implement XDG properly, and I disagree; see the last part of my original post. For example, one could imagine a more complex wrapper to better support XDG, like:
But at the end of the day, Go is cross-platform, and XDG isn't. And most users and developers want a directory, not a file. I personally think uncluttering That being said, I'm happy to add a bit of context to the func's godoc. A short note could point out that, on systems supporting XDG like Linux, the data directory is usually separate from the config directory, and that search directories might also be configured by the user. |
I'm specifically referring to the Library folder conventions on iOS/macOS. See the |
This is an API to find the place to write your own files, though, not where to read other programs' files. So we don't need to search. As a bad analogy, GOPATH is also a list, and we use the list for searching, but when you use |
I'm not sure if it is the right decision to add One of the reason is documentation, as an example as it is done by https://github.com/shibukawa/configdir. One other reason is that the base directories should be configurable. On UNIX systems that support XDG Base directory configuration is done by setting the XDG_ environment variables, but with a portable API an interface should probably be used, e.g. type BaseDir interface {
DataDir() (string, error)
ConfigDir() (string, error)
StateDir() (string, error)
CacheDir() (string, error)
RuntimeDir() (string, error)
} |
We could make this arbitrarily more complex. Or we could add os.UserConfigDir. The latter is what we decided to do. (Note in particular we explicitly rejected UserDataDir above. The point is not to implement XDG in full generality. The point is to provide a useful cross-platform functionality that happens to make reference to XDG on some Unix-like systems.) |
I was not proposing to implement XDG, since XDG is UNIX specific and not designed for other operating systems. I mentioned XDG since it is the only pseudo standard that I know that tries to solve the problem of where to store application data. Thanks. |
If a user has two or more valid config directories on their platform and manually adds or moves a config file to one that Go does not look at, they would not know why it did not work because they're following the convention of their platform. If they figure out what's going on, they will consider it a bug in the program invoking
A separate That's as much of an argument against |
I don't know how I feel about It would be very unexpected for me if the software that I develop on Unix, for Unix (no macOS-specific functionality) would behave this differently between other Unix-like systems and macOS.
|
@4ad my experience with Mac is very limited, so I was only following what I could find online. Do you have a better suggestion? I presume looking at XDG (i.e. a default of |
I don't know what to suggest. For better or worse, "real" mac apps and "unix apps" (for the lack of better terms) behave very differently on macOS, and people can and should be able to use Go to write both (albeit, I'd expect very few people write GUI mac apps in Go...). |
If But, IMHO, as I wrote in a previous comment, base directories are not trivial to define and there is a need of a separate package if you want the API to be useful for all kind of Go applications. |
That's exactly why. CLI programs tend to be UNIX programs, so they follow UNIX conventions ( Native Mac apps are supposed to ask the system where to put their stuff (so they get the correct path whether they're sandboxed or not), and the default is
Sounds perfectly reasonable. It's certainly important to use |
For the record: In reference to macOS. Since the ~/Library is by default hidden on Mac, the XDG should be used by command line applications leaving the ~/Library to native macOS applications . |
@philoserf that ship has sailed, in the sense that UserCacheDir already shipped one or two Go releases ago. We also need to pick one directory. We ended up going for the directories that Apple documents well. If a program doesn't like that choice, they can easily override that with XDG or another standard on Mac. |
Why on Mac (Darwin) can't UserConfigDir behave similarly to Unix? Meaning, first check to see if Admittedly most mac users probably don't have the XDG environment variables set up on their machines but those that do would probably be surprised that UserConfigDir ignores them entirely in favor of |
@jimdoescode see #29960 (comment). If you want to follow XDG, you should use an XDG library. We can't change the behavior now even if we wanted to, anyway. |
On non-English area, the
So if that API(UserConfigPath) returns a non-localized text and accesses it, it should fail. |
@mattn if you're saying that there is a bug in UserConfigDir, please open a new issue. |
@mvdan Not a bug. Just for the note. If Go team will add new APIs to return specific path to the directory (ex XDG_DESKTOP_DIR), it have to look |
Ah, gotcha. Yeah, proper XDG support was never part of the proposal :) |
@mvdan thanks for the response. To be clear I was only proposing that the UserConfigDir behavior change if the But I do understand the concern that existing systems might break as a result and I certainly can't speak for all Mac users on this. |
Yeah, existing users of this API could break, and we can't do that. There has been an extensive discussion about what to do on Mac on this issue, and we decided to go with what Apple documents well. I don't think doing a mix of Apple and XDG would have been a good idea, because it could have been pretty confusing for the end user, and it would have violated both Apple docs and the XDG spec. |
There is no one "right" directory for macOS, imo. Expected behaviour (from a user's perspective) is generally that command-line programs will behave in a UNIX-like way and put their stuff in Given this dichotomy that the stdlib can't solve, I think the right solution is to return the platform's recommended location (i.e. |
@deanishe I agree there's not really a "right" place and the UserConfigDir documentation clearly defines what on a Mac it returns so expected behavior should be what's documented. It was just disappointing to see that I had no control over it like a UNIX user might. Especially since I have taken the time to set up XDG and attempted, as best I could, to clean up both the I guess making XDG PRs for the go apps that I use regularly is my current path forward. I'm sorry for being late to the boat on this one and I appreciate the discussion and consideration you all put into this. |
Seems the best solution. An XDG library might be useful, but full XDG support is undesirable on macOS, imo. It's better to use FWIW, I always use |
Go 1.11 added
os.UserCacheDir
in #22536, and 1.12 is addingos.UserHomeDir
in #26463. This is great, and it covers plenty of common use cases.UserCacheDir
is particularly interesting, as its behavior changes greatly between platforms. For example, on Unix-y systems it tries$XDG_CACHE_HOME
and falls back to$HOME/.cache
, and on Windows it uses%LocalAppData%
.With those two functions, I believe there's only one piece missing; a configuration directory. Too many applications write "dot files" under the user's home directory, and that's bad practice. Some others hard-code
$HOME/.config
, which is only marginally better as it doesn't do the right thing on Windows/Mac.Relying on XDG base directory vars like
$XDG_CONFIG_HOME
is no good either, as those don't exist on most systems.We're only left with third-party libraries like https://github.com/shibukawa/configdir, which are moderately popular. In practice, popular software tends to write their own implementations. Below are some examples:
I propose adding
func UserConfigDir() (string, error)
, which would return:$XDG_CONFIG_HOME
or$HOME/.config
on Unix-y systems%APPDATA%
on Windows, which is described as "Contains the full path to the Application Data directory of the logged-in user" (unlike%LOCALAPPDATA%
, it's not for temporary files)$HOME/Library/Preferences
on MacI don't know about plan9, but given that the cache dir is
$home/lib/cache
, perhaps$home/lib/config
would work.Please note that I'm not suggesting adding support for XDG base directories into the
os
package. Most notably, addingUserConfigDir
might lead to some users requestingUserDataDir
. However, I can think of multiple reasons why they're not equally important:XDG_DATA_HOME
The only disadvantage I see with adding this API is that one could say we'd be encouraging users to store data files into
XDG_CONFIG_HOME
instead ofXDG_DATA_HOME
on XDG systems. However, those few programs that wish to differentiate their data directory from their config directory could simply do:/cc @kolyshkin @bradfitz @rsc @ianlancetaylor @stapelberg @robpike
The text was updated successfully, but these errors were encountered: