Shell script to uninstall ports with dependents
April 30, 2009
Before we begin, I seem to be getting a lot of people visiting this post when searching for “uninstall macports”. Read 2.5 Uninstall from the MacPorts Guide you want to uninstall MacPorts itself.
EDIT: steve k wrote in and opened my eyes to:
sudo port uninstall --follow-dependents portname
So use that instead, and read on only if you like bash.
(I have another script that does the inverse—traverses up the dependency chain removing ‘leaf’ nodes—that is, ports with no further dependencies. Maybe I’ll make a new post on that one—after making sure it’s also not already available as some hidden option. :p )
If you use MacPorts, then at some point you’ve probably tried to uninstall a port that had other ports as dependents. (If you’re a developer on OS X and you don’t use MacPorts, then you probably should.)
Even when using a friendly GUI like, say, Porticus, you’re prevented from uninstalling a port with dependents. Of course, you can force uninstall a port but MacPorts themselves warn us that doing so might cause problems later on (when rebuilding the dependents).
So, I used to manually traverse down the dependency tree and uninstall the leaf nodes (ports with no dependents) one by one until I could uninstall the ‘root’ port that I wanted to uninstall in the first place.
If you like doing that, then by all means keep doing so.
If, like me, you’re tired of having to do it by hand, then here’s a short shell script I wrote that can do all that for you.
Note that the script will fail if you have more than one installed version of any port. MacPorts itself will helpfully tell you which ports in the dependency tree have multiple versions installed. Maybe one of these days I’ll get motivated and challenged enough to update this script to handle (and uninstall) multiple versions properly.
I initially thought of writing this in Ruby, but since I used MacPorts to install Ruby itself I realized I very well couldn’t use the same script to uninstall anything up the Ruby dependency chain. Fortunately, I found that simple shell scripting (plus common tools like awk) was more than adequate for the task.
With that out of the way, here’s my deport.sh script:
function deport {
port="$1"
if port dependents "$port"|grep "depends on $port"; then
# depth-first traversal of dependents
port dependents "$port"|awk ‘/depends on/ {print $1}’|while read dependent; do
deport "$dependent"
done
fi
# make sure no more dependents
if port dependents "$port"|grep "$port has no dependents\!"; then
echo "port uninstall $port"
port uninstall "$port"
fi
}
if [ -z "$1" ]; then
echo "Usage:"
echo " deport.sh <portname>"
else
deport "$1"
fi
If you find this useful, then you’re welcome! If it doesn’t work for you, please drop me a line.
g
June 27, 2009 at 11:38 pm
Does your script yield different results than the built-in command:
sudo port uninstall –follow-dependents your-port-name
Thanks
July 15, 2009 at 3:05 pm
You’re right! I never knew about that option until you mentioned it.
Well, this basically makes my script useful only for academic purposes, doesn’t it? :p
September 3, 2009 at 10:22 pm
The uninstall flag should actually be –follow-dependents
September 3, 2009 at 10:24 pm
Apparently two dashes are being converted to a long dash character in the comment text
September 4, 2009 at 7:39 am
Thanks. I noticed I also had to use a <span>…<span> trick to have two dashes show up properly in the post.