Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

I and others have brought this up with the dirs Rust crate maintainer but they refuse to see it this way: https://codeberg.org/dirs/dirs-rs/issues/64. It's very frustrating.

I now use a combination of xdg + known-folders manually:

    [target.'cfg(windows)'.dependencies]
    known-folders = "1.2.0"

    [target.'cfg(not(windows))'.dependencies]
    xdg = "2.5.2"
to get the config directory:

    use anyhow::{Context, Result};

    #[cfg(windows)]
    fn get_config_base_dir() -> Result<PathBuf> {
        use known_folders::{KnownFolder, get_known_folder_path};
        get_known_folder_path(KnownFolder::RoamingAppData).context("unable to get config dir")
    }

    #[cfg(not(windows))]
    fn get_config_base_dir() -> Result<PathBuf> {
        let base_dirs = xdg::BaseDirectories::new().context("unable to get config dir")?;
        Ok(base_dirs.get_config_home())
    }


It seems like `etcetera` has better defaults: https://docs.rs/etcetera/latest/etcetera/#native-strategy

> `choose_base_strategy()` and `choose_app_strategy()` will use the XDG strategy on Linux & macOS, and the Windows strategy on Windows. This is used by most CLI tools & some GUI tools on each platform.


Sounds like it's time to make a fork of dirs-rs that actually follows the rules.

Most libraries that use dirs-rs are doing so because they don't want to have to think about those things. So if there were a library that did it right, you'd probably have decent adoption if it's a simple crate replacement.


The maintainer of dirs-rs IS the one following the rules here…


Where do I store my files is never a simple replacement. At the very least you need to write a migration routine and maintain it for a very long time.


This has been a solved problem forever. It is very simple, very easy, very short, extremely maintainable code.

When writing the files, check the old location first, fall back to the new one. When reading, check check the new location first, fall back to the old one.

The app does not need to migrate anything. Using the algorithm described above, new installations will automatically use the new paths, old installations will continue using the old paths, but can optionally be migrated at the user’s convenience.


But how do you find the old location? Do you need to build against both libraries, call old_lib.get_path(), check if it exists, then call new_lib.get_path(), copy the files, delete the old dir, them and then read from the new one. What if it's a symlink? What if copying fails mid-way? Does the library or the program handle all of this? Can you even compile against both libraries if one is a fork of the other (namespace issues)?


The app doesn't migrate the files, so no worrying about copying. Don't bother even checking if it's a symlink. A symlink is a file. Just open it and read it.


> But how do you find the old location? Do you need to build against both libraries, call old_lib.get_path(), check if it exists, then call new_lib.get_path() […] Can you even compile against both libraries if one is a fork of the other (namespace issues)?

You are really making this more complicated than it needs to be. Just do it yourself, to be honest. It’s like 3–5 lines of code. Introducing a library just complicates it.

> copy the files, delete the old dir, them and then read from the new one. […] What if copying fails mid-way?

As I said: You don’t need to copy, delete, or move any files. Just support both modern and legacy paths, and let the user take care of the migration, if they choose to.

> What if it's a symlink?

Again, why are you making this so complicated? Just try to read the file. If it fails, check the next location.


The maintainer's advice is correct, on mac you should store configs and other stuff in Library/Application Support, that's the mac convention to use on mac, just like xdg is linux convention to use on linux.


From my previous recollection, there's an issue for this in just about every rust crate that handles these dirs. The right way to fix this is fix the spec, then make the libs adhere to the spec.


How would you fix the spec? Add a line explicitly stating the /Library/Application Support dir is only for applications with a bundle ID, instead of just implying it?


For clarity, is this what you're referring to as "the spec"? https://developer.apple.com/library/archive/documentation/Fi...


No the xdg base directories spec. If you want to be able to opt in to dry on a system which doesn’t canonically use xdg vars, then you need some config.


XDG is cross-distribution for Linux, but it's not cross-platform. MacOS doesn't use XDG.


That’s my point. MacOS doesn’t use it, but many expect it to do so, so make this explicitly opt in so that a user’s preference is respected over the canonical configuration. To do that the best place to define the setting is in the spec.


I think there should be two crates in rust-land. The answer by @soc makes sense for apps, as the article discusses. Many (most?) people building Rust programs aren't making apps and so shouldn't be using this crate, which clearly and definitively only supports MacOS "Apps".


It sounds like https://docs.rs/etcetera/0.3.2/etcetera/index.html provides sufficient flexibility for apps that want this.


What does making a different choice for GUI and CLI apps achieve, other than making it impossible to ever have a single coherent place to look/synchronise/etc?

XDG's spec doesn't make such a distinction, so you’re advocating for a new competing standard.

I don't think Apple’s documentation intends to cover command line programs, but… in the absence of any concrete rule, putting your files where most programs on the system do is a reasonable choice, and that place will never be ~/.config/ on macOS.

Apps like homebrew that default to the library but support XDG_CONFIG_HOME if explicitly set, are a decent compromise, though.


A CLI app is an app.


Not in Apple's nomenclature, it isn't. An App specifically refers to a folder named ".app" with an info.plist and a binary inside of it. It can also contain a bunch of other metadata and application data. To apple, a "CLI app" as you call it is just the binary (a single file).

But the real distinction is that the "Apple App" manages its preferences in-app. The "CLI app" does not, the user is expected to manage this configuration themselves.


What you are talking about is an application bundle.


Why is that soc guy so angry and rude about it?


I assume they've made up their mind and are now just tired of discussing it. I don't know why they refuse to even consider an option for it.


The library addresses your use case: provides location to store configs. You're asking for your personal feature.


Imagine having built some software, abiding to a standard that to your understanding is the standard to abide to. Then comes people who ask you to break that standard and change your software. Again and again they come. Others ridicule your stance on social media and forums like these. It's burning out.

It's free and open-source for heaven's sake! If you don't like it, fork it, patch it, make your own custom version. But stop pestering maintainers with demands.


> But stop pestering maintainers with demands.

I don’t see any “pestering” in the linked issues. They’re polite and well-written with supporting links.

This is how it’s supposed to be done. Suggestions for improvements or issues noticed go into issue requests for discussion. If the maintainer doesn’t want to do it, a polite and concise explanation is typical.

The refrain of “just fork it!” is a cop-out. Forking software so you can maintain a fork forever isn’t a trivial decision. It’s not helpful to the community to have to choose between a lot of different forks that have minor differences.

I agree that open source maintainers don’t owe anyone anything, but I think this mentality is being taken too far when with the “maintainer is always right” mentality combined with blaming the issue starter for the maintainer’s behavior.


I used pestering for OP's "I and others have brought this up (...) but they refuse to see it this way (...). It's very frustrating."

Suggest it once, discuss it, get refused, move on. Instead there are tens of comments and above is a complaint about an additional ticket for the same issue.

I am not saying that maintainers are necessarily right, but they are in their right to build their project how they like it. It is a bad pressure and force if people continue to ask for things that a maintainer has already ruled out. What's the goal otherwise, caving in due to pressure and stress?


Then maintainer will stop maintaining and you will have to fork anyway. So it's lose-lose for everybody.

Fork and move on with your life.


I don’t think it’s unreasonable to be demanding when this refusal negatively affects a lot of other rust software


It's not an official package. Developers of other Rust software can always build the same functionality on their own or fork.


But the effect trickles down to many end users


[flagged]


It's unkind to publicly speculate on this in this particular way, IMO.


Kindness is reciprocal, IMO. But I will concede speculation is unproductive.


Certainly doesn't make me want to become a Rust contributors.


dirs is a library project not part of Rust the language’s stdlib. You’ll find just as surly responses in many libraries across many languages. It feels a bit absurd to judge the language ecosystem by the maintainer of a single library.


I've also been eyeing Rust, but coming from Go where you can build more or less complete cli tools with just the standard library I'm not overtly exited by occurrences like this.

From what I've seen Rust projects seem more or less node-esque in the sense that people just keep pulling all kinds of dependencies, not necessarily even understanding them that much. Like apparently serde the library is responsible for most of the slow compile times people associate with Rust, because deserialization/serialization is kind of a common thing to do in an app.

Happy to be corrected on my statements, not 100% on anything.

edit: apparently the behaviour in Go std library is the same, heh https://news.ycombinator.com/item?id=45022680


It doesn't have very large standard library. It's just running on a different philosophy on not making the Standard Library "Batteries included". But I find you get less dependencies than npm. Not so many tiny left-pad like microlibraries.

The main cost of compile times is Generics. Rust generics use "Monomorphization" which generate different binary code for every use of a generic type.

serde leverages generics everywhere and it generates the serialization code for every type you make serializable. So when you use `serde_json::to_string(MyType::new())` it follows calls a code path just for serializing MyType to a json string.

The upshot: It's incredibly fast, there's a lot of inlining and other compiler optimisations that can used because of it. No runtime reflection (Which is how Go does a lot of it).

The downsides: Takes a long time to compile cause of all the extra it's generating. Also can inflate binary sizes at bit.

Other languages like Go mostly use run time reflection for Json. Rust doesn't have much runtime reflection so doing it here wouldn't be possible


If you’re allergic to external dependencies then one of the batteries-included languages is better for you.

In practice, there are a lot of well known and well maintained Rust crates for core functionality. It has also inspired some good competition among different crates to serve different purposes, such as the different command line arg parsing libraries.

I don’t find it to be a problem at all, but I know some people get triggered when they install a package and see it download different dependencies.


> From what I've seen Rust projects seem more or less node-esque in the sense that people just keep pulling all kinds of dependencies, not necessarily even understanding them that much.

My experiences as well. Try to "cargo build" any projects, and you will immediately see the node-esque problems. It does not fill me with hope.


Oh yes... I am building Zed.

  Building [=>                      ] 154/1473
Amazing, 1473 dependencies!

Why is this normalized?


1968 dependencies when building with --release. :|


> I'm not writing an app, just a CLI tool

but CLI tools are applications


No, they are not. Those two are very different in macOS, where the word ‘app’ means an Application Bundle, which is a directory with a .app extension, Info.plist file, a bundle identifier, have an expected directory structure per Apple guidelines, should be installed in /Applications or ~/Applications, and so on and so forth.

CLI tools, including ones that Apple ships or makes, are not apps on macOS.

I’m sorry, this is my pet peeve as well and it’s very frustrating to see this ‘CLI tools are apps’ argument from developers who are not familiar with the Apple guidelines, and then argue about on an ideological basis.


That is covered in the article. An “App” on Mac is a specific thing with certain characteristics that CLI tools don’t have.


dirs maintainer is bit unhinge, maybe the high usage of crate has gotten to their head.

If I ever have time, I would love to fork this repository, patch it to support XDG_*, and actively work to advertise it across the rust ecosystem. If user wants to use different location on file system to store configuration files, then let them. Stop trying to dictate what users want.


The spec from Apple could be clearer, you have to read the tea leaves and both sides have enough ammo to argue for their interpretation. But as someone who doesn’t care either way where these are stored I think that makes me a bit more objective than people who strongly have an opinion that they are looking to justify.

I think the Application support people have a stronger argument. Nowhere does it say store it in ~/.config for CLI tools. Also it seems weird to store user preferences in two different locations based on if it’s a CLI app or a GUI app. What if you have both interfaces?

I’m not saying that Application Support is the better solution, and if people feel that there should be a distinction between CLI apps and GUI apps they should push for Apple to update their standards. Repeatedly harassing an open source maintainer to relitigate an issue they’ve already decided on is counter productive and a waste of the maintainer’s time. I would be frustrated if I was him as well.


From the same person: https://soc.me/standards/defending-home

I'm aware it mentions Linux specifically, but this is golden:

> From this point on, the number of dot-files and dot-directories can only shrink as the remaining applications get fixed and start conforming to the XDG base directory spec, while no new dot-files and dot-directories can be added to your home directory.

As is original reasoning for not using ~/.config from https://github.com/dirs-dev/directories-rs/issues/62#issueco...

> As Apple keeps tightening its after-sale ownership of macOS appliances, it's becoming increasingly unlikely that randomly dumping stuff in $HOME will keep working.

I get the feel he just does not like macOS?


That hyperlink redirects back to HN. There's JS on the site that redirects 'undesirables' like HN, formerly Reddit, and lobste.rs.


> they refuse to see it this way

That's why the long-term future of app development is containers. It is not possible, on a human level, to convince people to lift even the lightest of fingers for the common good.

Consider https://specifications.freedesktop.org/basedir-spec/latest/

The XDG specification has been around for 22 years. It has real benefits for users. It's trivial to implement. Yet even in the year of our lord two thousand and twenty five I still see TypeScript developers complain that it's "too hard" to comply with "this BS" and just stick files in $HOME.

I've long given up on solving technical coordination problems by appealing to the universal goodness of humanity. The only thing that works is to sandbox applications at tightly as possible and direct all their access to the external world through narrow interfaces that do their best to limit shenanigans.


> That's why the long-term future of app development is containers.

That kind of "sweep under the rug" attitude is even more wrong than putting a file to wrong location. Containers are good for some stuff, but duplicating code and letting badly developed software to proliferate in its own enclave is a defeatist approach.

> I still see TypeScript developers complain that it's "too hard" to comply with "this BS" and just stick files in $HOME.

I normally use this phrase sarcastically, but this time they really deserve it. It's a skill issue, moreover, PEBKAC. If there's a standard, you SHALL obey it, esp. if you're a prominent programming language. I mean, even my small utilities obey that. But that's Microsoft...

> I've long given up on solving technical coordination problems by appealing to the universal goodness of humanity.

Thanks for the good fight, we can take the torch from here and continue the challenge. No hard feelings here.

> The only thing that works is to sandbox applications at tightly as possible

Don't be so defeatist, though.


If people have refused to do the right thing for 20 years, they're not about to start now just because you say so.

A mature technologist must be pragmatic if he wants to get anything done. Isolation technologies work. Scolding doesn't. We tried.


> If people have refused to do the right thing for 20 years...

From what I have seen, not every human being is same. Categorizing them as clones of each other is falling into a false dichotomy.

> they're not about to start now just because you say so.

There's a quote I'm quite fond of: "You don't have to cut with the sword of truth, you can point with it, too". I don't "say what to do" to people and expect them to obey me. I produce examples, and put them out, and tell them politely. If they take the example, that's good. If they leapfrog me and show me a better one, that's great. If they ignore me, that's OK.

Not everyone will follow, and that's OK. Even I get upset by some people who doesn't do the correct thing. That's OK too.

We should be different, try different things, and find the correct way by mistake, or reach dead ends by doing everything right. My experience says both is possible, and even though the process is infuriating, that's OK too. This is called life. We can't control and know everything.

> A mature technologist must be pragmatic if he wants to get anything done.

There are places to be pragmatic, and there are places to experiment. Again, another false dichotomy. I did go great lengths by mixing the two, for example.

> Isolation technologies work.

Yeah, I also use them in various use cases, but never to sweep my incompetence under a proverbial rug. Instead, I skill up, do better. Surpassing myself in every iteration is the best dopamine hit I can get.

> Scolding doesn't.

You shouldn't be scolding anyone over any mortal matter like programming though. There are better ways to communicate, again from my experience. YMMV, IANAL.

> We tried.

You may have tried and I deeply respect that. But I'm a dense person who doesn't understand sometimes and do as I please, and apparently it helped me go places. So, I'll continue to be a dense person.


>But that's Microsoft.

They do the same on windows. Recent microsoft tools are written linux-first, even dotnet.


Do they started to respect the standards and lore of the operating system they used to loathe*?

That'd be interesting, honestly.

*: I have seen it all. I don't buy the OpenWashed Microsoft of today.


Including the standard of little knowledge of windows.


How is it even common good though? The articles main argument is that the author didn't expect the files there, not that it was causing any kind of issue. The problem is that people disagree where a config file should go, and there's no compelling reason why either of them are right or why it even matters.


I have absolutely no opinion on "common good" or "standard" here.

I wholeheartedly agree about the containers part though, just have everything within a folder in a container somewhere so I don't have to keep googling where X stores Y and still failing half the time.


I've been using macos for years, I just learned .config was a standard in this thread, because damn nearly everything shoves files in ~ so I just assumed that is where config files go.

Don't blame people for doing what 90% of apps do and assuming everyone else is correct.


It's a shame that MacOS doesn't have an equivalent for Boxxy.


> The XDG specification has been around for 22 years.

Indeed!

> It has real benefits for users.

I once believed this!

> It's trivial to implement.

Nope!

I ranted about this a while back (https://bsky.app/profile/str4d.xyz/post/3lsjbnpsbh22i) but the tl;dr is that the XDG specification is imprecisely written and internally inconsistent, and there has been confusion since at least as early as 2003 about what kind of data is meant to be stored in $XDG_CONFIG_HOME vs $XDG_DATA_HOME.

A plain reading of the XDG Base Directory Specification implies (but does not explicitly say, which is part of the problem!) that $XDG_DATA_HOME contains read-only user-specific application data files (like documentation).

But the spec is interpreted by many (source: I found a single blog post that seemed to be referenced in a variety of places, such as the Arch Linux wiki) as saying that $XDG_DATA_HOME contains mutable user-generated data (like password vaults).

Those have very different properties, and it's impossible as an app developer for me to predict which of those two directories a user (or the tooling installed on their OS) is assuming can be safely deleted without consequence, and which must always be backed up.

> Yet even in the year of our lord two thousand and twenty five I still see TypeScript developers complain that it's "too hard" to comply with "this BS" and just stick files in $HOME.

My earlier rant arose from me spending several days attempting to follow the XDG specification for an app where I need to store mutable user-generated data, being unable to find any supporting evidence that it was safe to store this in either $XDG_CONFIG_HOME or $XDG_DATA_HOME, and deciding on ~/.appname instead. I do allow all paths to be overridden in the config file, so individual users can use XDG paths at their own risk (and with knowledge of their OS environment's behaviour).


I'm confused.

$XDG_CONFIG_HOME is clearly meant for data that would otherwise be in a configuration style dotfile. This is the sort of configuration that that users may well want to sync between machines such that a dotfile manager should include them by default. (That said, there may be some data from some of the other XDG directories worth syncing too, but generally a dotfile manager should not include those other folders in full by default.)

Beyond that the spec defines $XDG_DATA_HOME as "base directory relative to which user-specific data files should be stored.". The default path ($HOME/.local/share) might suggest that this should be read-only data, but it actually is read-write.

The description of the $XDG_STATE_HOME makes it quite clear that $XDG_DATA_HOME read-write: "The $XDG_STATE_HOME contains state data that should persist between (application) restarts, but that is not important or portable enough to the user that it should be stored in $XDG_DATA_HOME". This makes it clear that important and portable data should be written to $XDG_DATA_HOME.

And thus we also have $XDG_STATE_HOME. The list of examples that follow the previously quoted sentence make it clear that this is stuff that gets persisted, but if it were omitted from a backup, the user will probably not care too much (i.e. stuff like logs, history, set of open files, undo history, etc.

$CDG_DATA_HOME does also include any read-only reference data, which should be searched for there, and in $XDG_DATA_DIRS (which defaults to "/usr/local/share/:/usr/share/").

It could certainly be argued that read-only reference data and read-write user data should not have been mixed. After all Unix does keep them separate that at the top level `/var` vs `/usr/share`, but the spec authors apparent felt this distinction was not necessary at the user level.


I'm not sure where you got that XDG_DATA_HOME has to be read-only, I couldn't find anything like that

> $XDG_DATA_HOME defines the base directory relative to which user-specific data files should be stored.

And really, the difference between XDG_DATA_HOME and XDG_CONFIG_HOME is subjective anyway, each application will have its own requirements, so I'm not convinced it's even possible to define these completely precisely.

Personally, I would pick between XDG_DATA_HOME vs XDG_CONFIG_HOME based on whether the application manages the files, or whether the user is expected to manage the files themself. This isn't based on any wording in the standard, but just a pattern I've commonly seen


The spec says

"There is a single base directory relative to which user-specific data files should be written. This directory is defined by the environment variable $XDG_DATA_HOME"

Where are you seeing "read-only"?

And why would it not be safe? What kind of user specific documentation did you think should go there and even if you did, why would you think it could be randomly removed by something else?


Just dumping everything in ~/.config instead of home will be a good start. It can be improved incrementally from there.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: