cleanup command
RafalSkolasinski opened this issue · 15 comments
Is your feature request related to a problem? Please describe.
There does not seem to be way to install all old version of packages.
Describe the solution you'd like
A command like asdf uninstall --not-global
that would remove all version of packages not specifiied in global .tool-versions
.
There does not seem to be way to install all old version of packages.
Did you mean to say "uninstall all old versions"?
A command like
asdf uninstall --not-global
that would remove all version of packages not specifiied in global.tool-versions
.
This can be done by loop over the lines in .tool-versions
and looking for tool versions returned by asdf list $tool
that aren't present on the line in .tool-versions
.
#!/usr/bin/env bash
# Loop over each line of the .tool-versions file
while read -r line; do
IFS=' ' read -r -a tool_and_versions <<< "$line"
# Split out the tool name and versions
tool_name="${tool_and_versions[0]}"
global_versions=("${tool_and_versions[@]:1}")
# Loop over each version of the tool name
for version in $(asdf list $tool_name); do
# When version not in `global_versions` array from .tool-versions file
if [[ ! " ${global_versions[@]} " =~ " ${version} " ]]; then
# Remove the version here if you want
echo "$tool_name version $version not found in .tool-versions"
fi
done
done < ~/.tool-versions
I get this is not a trivial piece of code for our users, but adding a command to do something this specific is not something I want to do right now. We've had many requests over the last couple years for specialized features like this.
Did you mean to say "uninstall all old versions"?
Yup.
but adding a command to do something this specific is not something I want to do right now.
As it goes against design decision or lack of time? If latter would you be willing to accept a PR maybe?
As it goes against design decision or lack of time? If latter would you be willing to accept a PR maybe?
One of the design goals is for asdf to have as simple an API as possible. We've rejected a lot of commands for one off features that will only be used for a subset of our users. In this specific case, its not clear to me that this is something that will be widely needed. I've never needed this feature and I don't expect I ever will. I don't want to remove tool versions unless I am certain nothing on my computer needs them.
Another aspect of the API design is making it easy to do the correct or canonical things and making it difficult to do things that aren't recommended.
I'm going to leave this issue open so anyone interested in a feature like this can comment and share opinions/ideas. I don't see this as a beneficial feature for asdf core.
Thanks for explaining your reasoning, it makes sense.
I will add the script you shared somewhere in my PATH and make use if it whenever I need to do a cleanup :)
Thanks!
I had noted a similar feature to myself just a few days ago. My idea was not a pruning command, but to track in some file the time each <tool> <version>
pair was used so that an asdf list <tool>
could print this information and people could action that information themselves.
What if you just want to keep your version up to date in the shell? I just always want the latest version of go, but asdf install golang latest
won't clean up any old versions.
I had noted a similar feature to myself just a few days ago. My idea was not a pruning command, but to track in some file the time each
<tool> <version>
pair was used so that anasdf list <tool>
could print this information and people could action that information themselves.
The problem with that is we have to take into account shell versions if we wanted that information to be accurate, and it's not possible to get all shell versions in all running processes without resorting to hacky and slow methods (e.g. looking at the environment for every running process, and even them we won't necessarily have permission on the OS to do that).
So we have a couple options here:
- Build something with the caveat shell versions are ignored and will lead to info that is incorrect
- Not support this
- Resort to some hacky methods to try to get the best info about shell versions possible
I personally would rather see us not support this. I don't think I have ever uninstalled a tool other than for debugging purposes and after 3 years on this machine I have about 10GB of version data:
du -h -d 1 .asdf/installs/
3.8G .asdf/installs//nodejs
2.0G .asdf/installs//python
21M .asdf/installs//clojure
252M .asdf/installs//elixir
1.9M .asdf/installs//rebar
1.8G .asdf/installs//erlang
0B .asdf/installs//java
4.7M .asdf/installs//yarn
6.3M .asdf/installs//lua
1.7G .asdf/installs//postgres
64M .asdf/installs//kafka
229M .asdf/installs//elasticsearch
606M .asdf/installs//ruby
10G .asdf/installs/
Almost 4GB of which is nodejs (node_modules again maybe?).
See, I would greatly like a command like this. Mostly because I only ever care about latest versions of my tools, and don't like clutter. I even wish there was a --all
on the install
command, so I can just symlink my .tool-versions
file, and have asdf install all the plugins, install all the versions in the file, and then set them to global.
I use asdf to keep consistent versions of my tools between computers. I regularly run the following commands:
asdf plugin update --all
asdf list | xargs -I $ asdf install $ latest
asdf list | xargs -I $ asdf global $ latest
Problem is, there is no cleanup script so after a while, i have a bunch of unneeded versions that I have to manually remove.
Having something like asdf cleanup
which can potentially take a parameter of how many to keep, if you don't just want one. that and --all
param on the install
, global
and plugin add
commands would be real helpful.
while i understand the concern about how hard it can be to support this i do think that having a pruning option (whatever the name of it) is a must have.
Just migrated (quite by accident) my asdf binary versions from my intel mac to my new silicon mac. Having a way to prune (just keep last versions defined in global config file) could help to limit the size of it and the number of versions that you have to check for running in roseta mode
Stratus3D said:
I don't want to remove tool versions unless I am certain nothing on my computer needs them.
And I think this is the key issue here.
So, one way to get closer here is to collect some metadata, like last-used timestamp and some history of arguments (maybe via opt-in because there might be sensitive data), so that you can at least investigate a bit when and how tools are used.
This should be quite easy to implement since all calls to installed tools are going through shims anyway, no?
I don't think anyone is advocating making this happen automatically or anything, just a option for those that would find a use for it. I work with tools and programming languages that are better if you are always on the latest version. Hell, golang doesn't officially support anything other than the latest 2 versions. Dart has a similar mindset, and many others.
I can understand the issue for say Python, or Ruby where version can matter, but I would hazard to say it's important to stay updated on those too.
Regardless it can even be a flag on asdf remove. Do asdf uninstall --purge --i-am-really-sure
or something if you want to discourage it. You can even ask for a confirmation after entering the command.
The issue is I need to frequently do this to keep my asdf installs in check. I run the script that was posted earlier. But it gets annoying having to manage my own scripts around another script that executes scripts. I don't see why such a command can't exist as part of asdf, since 50% of the work is already done. I'll even open the PR for all of these if I knew they wouldn't be rejected.
No one is asking you to run these commands for your workflow, but for some it's useful for theirs.
See, I would greatly like a command like this. Mostly because I only ever care about latest versions of my tools, and don't like clutter. I even wish there was a
--all
on theinstall
command, so I can just symlink my.tool-versions
file, and have asdf install all the plugins, install all the versions in the file, and then set them to global.I use asdf to keep consistent versions of my tools between computers. I regularly run the following commands:
asdf plugin update --all asdf list | xargs -I $ asdf install $ latest asdf list | xargs -I $ asdf global $ latestProblem is, there is no cleanup script so after a while, i have a bunch of unneeded versions that I have to manually remove.
Having something like
asdf cleanup
which can potentially take a parameter of how many to keep, if you don't just want one. that and--all
param on theinstall
,global
andplugin add
commands would be real helpful.
To add on top of this if you always run on latest (which is set last in the lists) you can also run
for plugin in $(asdf plugin-list); do asdf list $plugin | head -n -1 | xargs -I $ asdf uninstall $plugin $; done
if you switch back and forward on non latest and only want to retain the set one
for plugin in $(asdf plugin-list); do asdf uninstall $plugin $(asdf list $plugin | grep -v "$(asdf current $plugin | awk '{print $2}')"); done
edited a better one comm -13 does not work in all use cases.
See, I would greatly like a command like this. Mostly because I only ever care about latest versions of my tools, and don't like clutter. I even wish there was a
--all
on theinstall
command, so I can just symlink my.tool-versions
file, and have asdf install all the plugins, install all the versions in the file, and then set them to global.I use asdf to keep consistent versions of my tools between computers. I regularly run the following commands:
asdf plugin update --all asdf list | xargs -I $ asdf install $ latest asdf list | xargs -I $ asdf global $ latestProblem is, there is no cleanup script so after a while, i have a bunch of unneeded versions that I have to manually remove.
Having something like
asdf cleanup
which can potentially take a parameter of how many to keep, if you don't just want one. that and--all
param on theinstall
,global
andplugin add
commands would be real helpful.To add on top of this if you always run on latest (which is set last in the lists) you can also run
for plugin in $(asdf plugin-list); do asdf list $plugin | head -n -1 | xargs -I $ asdf uninstall $plugin $; doneif you switch back and forward on non latest and only want to retain the set one
for plugin in $(asdf plugin-list); do asdf uninstall $plugin $(asdf list $plugin | grep -v "$(asdf current $plugin | awk '{print $2}')"); doneedited a better one comm -13 does not work in all use cases.
Those are super helpful.
But I have given up on asdf. I switched to Nix and Home Manager for the tools use case. Now everything works as I want it, it's clean and easier to manage. And I have profiles for work and home with different tools, yet everything is modular and in-sync.
I hope asdf improves for others though.
Here's my 2 cents since I have some experience with this in mise. mise has a mise prune
command that makes use of an internal directory that stores symlinks to every config file (.tool-version) it has seen and deletes things that don't match what is in any of them. This feature has been there for probably a year now and while I don't have numbers, I've had users mention to me that they use this often.
This has the drawback that versions configured via env vars won't be considered. I think that's functionality that isn't often used though, and when it is, I think users don't remember what was installed anyways and it's often ephemeral stuff—so probably makes sense to delete anyways. Since adding this nobody has ever mentioned anything about env vars causing any problems for them—but that said the docs are also pretty clear about this limitation.
I don't think users like it because they're worried about disk usage. I think it's just that they like keeping things tidy and having things like asdf list
output only relevant things. I don't think this is a majority of users but it's significant enough that I wouldn't consider this a "one-off" thing for a handful of users either.
All that said, I think it's fair to say that asdf goes for being "precise" in general where in mise I make assumptions all over the place about what I think the user probably wants to do. So even though it seems to work well in mise it might not fit the culture of asdf to have a feature like this that only works for even a large subset of users.