Add an option to `brew rm` to uninstall / remove a package, including all it's dependencies. #7465

Closed
oryband opened this Issue Sep 7, 2011 · 25 comments

Projects

None yet
@oryband
oryband commented Sep 7, 2011

I've searched over the www for a way to make Homebrew uninstall a package without leaving junk behind it, and haven't found anything useful.

Let's say I want to uninstall python package, which depends on readline package. readline is currently only used by python on my system, and not by any other package.

When I brew uninstall python I also want to uninstall readline, without having to search for the dependencies myself and check if it's okay to remove them manually. With many packages installed this process becomes cumbersome and time-consuming.

There should be an option to brew rm to do that. It shouldn't be that difficult. Just involves a clever use of brew deps & brew uses, I suppose.

@jacknagel
Contributor

To really do this properly, the metadata in the formulae isn't enough. Things that don't specify an explicit dependency on something might link against it anyway if it happens to be present already, and removing it will break things in that case.

@oryband
oryband commented Sep 7, 2011

@jacknagel: I don't understand, aren't all of a given package's dependencies listed on its formula?

What should be done seems simple in concept:

  • Check if all of the given package's dependent packages are:
    • Found in other installed packages' dependency list.
    • If not, remove them.
    • Recurse into the dependencies' packages.
@jacknagel
Contributor

In theory yes. But sometimes packages that aren't dependencies get picked up by other packages configure scripts, even if they are not required. And removing them will break things.

@oryband
oryband commented Sep 7, 2011

@jacknagel: Well, I guess that's the formula's responsibility to state its dependencies correctly, right?

If these unstated packages are picked up by the configure scripts, what happens when they're absent when these scripts run? Do the formula break?

@jacknagel
Contributor

No. What I'm saying is they are not "dependencies" in the sense that they are not required, and the formulae will build fine in their absence. But if they are present, they might get picked up anyway.

@oryband
oryband commented Sep 7, 2011

@jacknagel: I understand now, thanks.

I guess in these case, these unstated packages shouldn't be uninstalled, since they were installed prior to installing the given package.

@jacknagel
Contributor

A better (safer) way to do this would be to run otool on everything in bin and lib in each keg, and ensure that we aren't removing anything that something is currently linked against.

@oryband
oryband commented Sep 7, 2011

Well, at least we agree this option is necessary and helpful. :)

@jacknagel
Contributor

Another example of the need to do this the safe way is if someone has run brew link FORMULA on a keg-only library and forgotten to unlink it. Then a package that normally builds fine against the system library could pick up the keg-only library, and simply checking its list of stated dependencies wouldn't be enough.

Not that we have to protect against everyone's silly mistakes. But there are a lot of corner cases.

@jacknagel
Contributor

One thing I forgot to mention--you might be interested in brew leaves, which will show formulae that are installed but are not dependencies of any other installed formulae. (It's a contributed external command, which is why it is not documented in the man page[1]).

Well, at least we agree this option is necessary and helpful.

The more I think about it, the less I agree. In addition to the issues I mentioned before, there is this: how do you distinguish between "orphaned" formulae (those that were installed as dependencies of something else, but that something else has been removed) and formulae that have been installed explicitly? These are not always mutually exclusive.

To illustrate, say I brew install sqlite and then brew install python, or perhaps just brew install python but later begin using sqlite for something independent of python. How do we determine if we should remove sqlite?

I don't think we can get any more clever than just looking at the output of brew leaves every once in a while and removing formulae we don't want. Anything more would require storing a bunch of metadata.

[1] That reminds me that we should make an external commands man page.

@mxcl
Member
mxcl commented Sep 7, 2011

Jack is right, but we should be aware of this stuff and deal with it as it happens. It is not a reason to not implement this feature. However I can't be arsed. As you said "It shouldn't be that hard" so hopefully someone is motivated.

@oryband
oryband commented Sep 7, 2011

Created issue #7475 for creating an external commands man page.

This (7465) issue is for creating a command for removing a package along its dependencies, if they're going to become orphaned after the given package's removal.

@jacknagel
Contributor

In the interim, one could probably do this:

$ brew rm FORMULA
$ brew rm $(join <(brew leaves) <(brew deps FORMULA))

to uninstall all deps of FORMULA that have been orphaned.

@teoljungberg
Contributor

Not sure if I'm bringing up an old, and dead, discussion, but...this would be pretty neat and handy.
To not be able to do:

$ brew rm $(join <(brew leaves) <(brew deps FORMULA))

or

$ brew rm $(brew deps FORMULA) FORMULA

would be very appriciative.
This could be done by adding a --with-deps flag to uninstall/rm/remove that mayby aliases one of the mentioned above commands

@mxcl
Member
mxcl commented Mar 19, 2012

Patch welcome. Maybe one day I'll get around to it. But one day has become three years already.

@adamv
Contributor
adamv commented Apr 6, 2012

This can be added now as an external command; call it brew rmdeps or brew rmtree. That way we can audition the functionality without adding it directly to Homebrew-core.

@adamv
Contributor
adamv commented Jun 11, 2012

Closing, but will consider an external command that does this.

@adamv adamv closed this Jun 11, 2012
@mecampbellsoup

Did this command ever get created?

@MikeMcQuaid
Member

No.

@joshlewis

It'd be useful.

@aristidesfl
Contributor

Very useful, like Arch's pacman -Rs

-s, --recursive

Remove each target specified including all of their dependencies, provided that (A) they are not required by other packages; and (B) they were not explicitly installed by the user. This operation is recursive and analogous to a backwards --sync operation, and helps keep a clean system without orphans. If you want to omit condition (B), pass this option twice.

@MikeMcQuaid
Member

If someone implements it we'll review a PR. Being increasingly specific about what it should do is less productive than actually trying to implement it 😄

@beeftornado

For everyone who comes here looking for an implementation of rmtree. There is nothing special about it, it is still subject to all the caveats mentioned in this thread, so use at your own risk.

https://gist.github.com/beeftornado/1efe85f0239d9adf6a0c

@beeftornado

Been tapped...

$ brew tap beeftornado/rmtree && brew install brew-rmtree

https://github.com/beeftornado/homebrew-rmtree

@nickmccurdy

@beeftornado I just tried out your script, and it seems to be working pretty well so far! I agree that it would be useful to have something like this in brew. We could always warn the user about some of the edge cases mentioned previously (maybe we could force a confirmation the first time the command is used or something like that?).

@xu-cheng xu-cheng locked and limited conversation to collaborators Feb 16, 2016
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.