Skip to content

Respect $XDG_DATA_HOME#416

Merged
Schniz merged 6 commits intoSchniz:masterfrom
samhh:xdg-data
Dec 20, 2021
Merged

Respect $XDG_DATA_HOME#416
Schniz merged 6 commits intoSchniz:masterfrom
samhh:xdg-data

Conversation

@samhh
Copy link
Contributor

@samhh samhh commented Mar 25, 2021

WIP

I have to stop for the evening, but there's one problem left that may be easiest to solve with a better view of the higher-level architecture and/or with more experience with Rust.

Because base_dir_with_default is called twice below, the deprecation notice is printed twice.

Do let me know if you have a preferred means of addressing this, else I'll have a crack at it next chance I get.


Once the above is addressed this will close #357.

@vercel
Copy link

vercel bot commented Mar 25, 2021

This pull request is being automatically deployed with Vercel (learn more).
To see the status of your deployment, click below or on the icon next to each commit.

🔍 Inspect: https://vercel.com/schniz/fnm/GvmMFBV4NZo8YbsUVpbTQPwPUAbS
✅ Preview: https://fnm-git-fork-samhh-xdg-data-schniz.vercel.app

Copy link
Owner

@Schniz Schniz left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry I haven't commented. It's declared as a draft so I ignored it until it's ready to review.

Thanks for the PR!

  1. I wonder if we should migrate the directories in fnm itself instead of emitting a warning.
  2. that being said, the installation script installs fnm in ~/.fnm by default, so we might need to warn them to move the binary away, or to do something else.
  3. re: warns multiple times — https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=8caf91cddbb954cccbed08a188d69d42 the real concern is that it will emit the warning on every fnm call 😳 no? (I might be wrong because maybe fnm env sets the FNM_DIR env var, which will avoid going into the base_dir_with_default)

src/config.rs Outdated
Comment on lines +71 to +77
outln!(
self#Error,
"{} {} is deprecated. {} is now the default.",
"warning:".yellow().bold(),
"$HOME/.fnm".italic(),
"$XDG_DATA_HOME/fnm".italic()
);
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's use explicit directory paths in the warning so it will work on Windows as well. I think we should have a thorough explanation. Maybe even linking to the issue on GitHub?

warning:
  Looks like you have ${legacy} directory on your disk.
  fnm is migrating its default storage location from ${modern} to ${legacy}.
  Read more about it here: ${GH_ISSUE}

hint:
  You can use the following command to move the directory:
    mv ${legacy} ${modern}
  Please make sure your `fnm` binary is not stored in this directory and if it does, move it to ${A LOCATION WE NEED TO CHOOSE AND UPDATE THE INSTALLATION SCRIPT TO USE AS WELL} and update your shell profile accordingly.

@samhh
Copy link
Contributor Author

samhh commented Apr 1, 2021

I wonder if we should migrate the directories in fnm itself instead of emitting a warning.

If I'm following, my only concern as a user would be that it takes power away from me. What if I have scripts targeting ~/.fnm/ and I'm not ready yet for migration? And wouldn't that constitute a breaking change, in which case it's less a deprecation and more a hard change with a migration helper?

re: warns multiple times

Thanks for the REPL example! Not worked with Rust to this extent yet, and when I used it more heavily before I'm pretty sure this site didn't exist. 😄

I agree the unsafe example is more readable and the scope of the unsafety is very limited. I'll go with that approach.

@Schniz
Copy link
Owner

Schniz commented Apr 2, 2021

If I'm following, my only concern as a user would be that it takes power away from me. What if I have scripts targeting ~/.fnm/ and I'm not ready yet for migration? And wouldn't that constitute a breaking change, in which case it's less a deprecation and more a hard change with a migration helper?

You are correct. So the real question is whether we should deprecate or use it if it already exists. So:

  • if user provided a base dir, use what the user provided
  • if there's ~/.fnm/installations, use ~/.fnm
  • use ${data_dir}/fnm

This way, we don't break, and allow people to install fnm in ~/.fnm/fnm, but if they have Node installations then we use ~/.fnm as the base dir 😃

what do you think?

The issue here is less about code and more about how we don't break people. Most people don't care 😃

@samhh
Copy link
Contributor Author

samhh commented Apr 2, 2021

I've only really been thinking in terms of application data; for example, my data dir contains only aliases/ and node-versions/. Are you saying that some folks install fnm itself to ~/.fnm/fnm and/or ~/.fnm/installations/? Why? 😄

@ljharb
Copy link

ljharb commented Apr 2, 2021

Probably because XDG is a very niche feature that virtually nobody uses (not passing any judgement on using it, or on the concept itself). Few tools respect XDG vars, and even fewer users expect them to.

@Schniz
Copy link
Owner

Schniz commented Apr 2, 2021

Yup. As a Mac user, I really don't expect tools to use the "Application Support" or "Library" directories even though that's the "right place" for them to use

@samhh
Copy link
Contributor Author

samhh commented Apr 3, 2021

Looking on my Linux machine, it certainly doesn't look accurate to me that "virtually nobody uses [XDG]"; it looks like more than half of my applications favour the standard, and there's generally a push from folks like myself to increase adoption. I believe GHC for example has just implemented support.

I'm aware that (I think?) the majority of web devs are on macOS, so I've just opened up my work laptop to have a look at ~/Library/Application Support/. I can see a lot of directories in there, including from the likes of Alfred, VSCode, Docker, Electron, Firefox, Chrome, iTerm, Zoom, Slack. Only two of these have a presence directly in $HOME.

Where would you expect macOS data to go and why?

@ljharb
Copy link

ljharb commented Apr 3, 2021

That suggests more tools support it; it doesn’t speak to whether users set those variables in the first place.

Mac GUI applications certainly all follow those conventions; cli tools typically do not.

@samhh
Copy link
Contributor Author

samhh commented Apr 4, 2021

Okay. Let's step back a bit. Why would you manually delve into the fnm data directory in the first place?

My motivation is external in that I want a clean home directory to which end ecosystem support for XDG is helpful.

It looks like if users install without a package manager then the default installation directory is ~/.fnm/, so that's a reason to go in there (or add it to $PATH), but specifically for the binary rather than the application data.

Will macOS users even notice if the application data moves? I think that's all my PR would affect.

@Schniz
Copy link
Owner

Schniz commented Apr 4, 2021

Mac GUI applications certainly all follow those conventions; cli tools typically do not.

Let me give some examples:

So there is no real standard here aside from CLIs usually use ~/.config by default. We can go for ~/.fnm if it exists, or ~/.config/fnm if it doesn't. If you already have a directory for fnm in your root, using it makes sense to me. If not, we can use ~/.config/fnm so we won't add garbage to the home dir 😃

what do you think? how does that work out with XDG_?

@Schniz
Copy link
Owner

Schniz commented Apr 4, 2021

btw I totally agree with the move (and really thankful for your hard work and communication). most of what I did with using a directory in the home directory was for my convenience and derived from mostly ignorance. Downloading the binary to ~/.fnm/fnm made sense because it was easy. Where do you think we should download it? I really dislike downloading something directly to /usr/local/bin or similar (which is what Starship do, for instance). It feels insecure.

The config can go into ~/.config/fnm, but where do you think we can put the binary for the installation without a package manager?

@samhh
Copy link
Contributor Author

samhh commented Apr 4, 2021

My understanding of XDG is that $XDG_CONFIG_HOME (which defaults to $HOME/.config/) would be inappropriate for application data, it's really only intended to store configuration files, for example if fnm had something like a .fnmrc or config.json or whatever it might be. $XDG_DATA_HOME is where data files belong which is what things like Node versions and aliases are in my opinion.

This is why I'm questioning what users actually look at in ~/.fnm/; I'm not sure why users would ever be expected to poke around ~/.fnm/aliases/ or ~/.fnm/node-versions/.

The manually-installed binary is another matter. I can see some talk here and there of an $XDG_BIN_HOME, but it's notably absent from the formal specification at time of writing so I can only assume it's non-standard and probably best avoided.

How would we feel about adhering to XDG for application data but leaving the default installation location of the binary alone? I suspect most people who care about XDG are using a package manager anyway; my fnm lives in /usr/bin/. Likewise those who care about the location of the manually-installed binary probably don't care about the other contents of that directory.

@samhh
Copy link
Contributor Author

samhh commented Apr 10, 2021

I've updated it to only warn once per invocation. I've seen lots of CLI tools warn on each invocation, so that feels okay to me. Edit: Actually that's going to be really annoying if the user has their binary there, they won't be able to silence it...

I've also updated the warning. I've omitted the mv hint for now for two reasons:

  1. We won't necessarily have a path to the new location because data_dir can technically fail (like home_dir can). We could instead panic if we can't find it, which is the future-bound behaviour anyway. But then it's into breaking change territory, maybe? Probably not? I don't know. 😄
  2. If users wish to keep using $HOME/.fnm/ for the binary then we don't actually want them moving the entire directory, only some of its contents. Although the move is quite trivial I'm not sure how to distill this into a single digestible command for less advanced users.

@Absolucy
Copy link

Absolucy commented Sep 2, 2021

I'd be willing to try to pick up this PR if anyone would like me to. I'm always an advocate for using OS-standard directories.

@samhh
Copy link
Contributor Author

samhh commented Sep 2, 2021

I'm still here and active, but feel free to branch off or otherwise start a separate PR if you think that'd help drive this to completion. I think the main challenge is still figuring out exactly what the behaviour should be rather than the technical implementation thereof.

@Absolucy
Copy link

Absolucy commented Sep 2, 2021

Oh, alright. Sorry, was kinda just looking through the home folder of my macbook to see if there was anything I could help move to the proper directories.

@Schniz
Copy link
Owner

Schniz commented Sep 5, 2021

I understand the concerns and would probably choose to use https://docs.rs/dirs/ if I had deeper thoughts about it. The issue is that it is not the case right now and there are some apps that do the same:

My ~/.config dir has:

  • Fish
  • Starship
  • Neovim
  • GitHub CLI
  • & more

My ~ directory has:

  • oh-my-zsh
  • npm
  • Rust's cargo & rustup
  • kubectl
  • docker
  • I remember that in my old computer I also had Vagrant in my home dir

So, I guess we can also say "well, fnm data is not a configuration thing at all", because it is an installation directory. So even if fnm was storing stuff in ~/.config/fnm to match some of the above, it was kinda weird to do that.

I did not mind changing the default behavior if it wasn't destructive to users that currently use fnm. People that are saavy enough to care about default directories and to avoid storing data in ~/.fnm can also configure the fnm directory using the initialization argument: fnm env --fnm-dir=$XDG_DATA_HOME/fnm

Sorry if it comes out rude or something, I clearly don't want to be rude. Just stating that this is not as clear and simple as one can think of.

I am also not sure that I would have want fnm to store data on ~/Library/Application/fnm on my Mac, but that can be configured 😉

That being said, MAYBE we can say:

  • If there is base_dir ($FNM_DIR or --fnm-dir): all good, use the provided value. (eval $("fnm env") will set up $FNM_DIR)
  • Otherwise, if there is no base_dir
    • If there is ~/.fnm, use it, and show a warning
    • Otherwise, use dirs::data_dir().join("fnm") or dirs::config_dir().join("fnm")

fnm/src/config.rs

Lines 85 to 90 in 7e9381c

pub fn base_dir_with_default(&self) -> std::path::PathBuf {
self.base_dir
.clone()
.unwrap_or_else(|| home_dir().expect("Can't get home directory").join(".fnm"))
.ensure_exists_silently()
}

@samhh
Copy link
Contributor Author

samhh commented Nov 18, 2021

Sorry for the delayed reply, this notification slipped by me.

It's reasonable to want to avoid destructive behaviour for users. It's been a while since I touched this PR, but I think what's here so far aligns with your suggestion.

What's left to implement or decide to unblock this?

@Schniz
Copy link
Owner

Schniz commented Nov 30, 2021

@samhh I think this approach is good, but let's see if we can remove the unsafe! block? Maybe by using Mutex<> and lazy_static?

@Schniz
Copy link
Owner

Schniz commented Nov 30, 2021

and I am also sorry for dragging this PR for such a long time. I'm showing bad maintainer behavior unfortunately

@samhh
Copy link
Contributor Author

samhh commented Dec 1, 2021

@Schniz No worries! I appreciate your openmindedness and time on an issue that you're not personally invested in 🙂

I've opted for an AtomicBool to try and avoid an extra dependency. Not familiar enough with Rust to say if that's a good idea, but I got the idea from here. Happy to change it to a Mutex if you'd prefer that.

@samhh samhh marked this pull request as ready for review December 1, 2021 22:23
@Schniz Schniz added the PR: New Feature A new feature was added label Dec 20, 2021
@Schniz
Copy link
Owner

Schniz commented Dec 20, 2021

okayyyy

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

Labels

PR: New Feature A new feature was added

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Install to XDG dir by default instead

4 participants