By default, MacPorts will deactivate,
and retain, earlier versions of any port that is upgraded with
port upgrade
. The result is that after a while some
housekeeping is required, including uninstalling outdated versions
of ports.
The list of ports which are installed, including both active and inactive versions, can be obtained with:
port installed
and the active version will be marked with "(active)". The inactive
ports (ie, those not marked with "(active)"), will include both
ports where there are other (eg, later) versions that are active,
as well as ports where all versions of the port have been made
inactive for some reason (eg, conflicting with other ports -- such
as foo
and foo-devel
ports providing
different release streams of the same software). It gives the
version number of each installed version of the port.
To get a list of the names of ports that have at least one inactive version installed use:
port echo inactive | awk '{print $1;}' | sort | uniq
(Avoid "port list inactive" or "port list actinact" or similar as that will take the names of ports given -- including repeated names due to multiple installed, but not active, versions -- and list the active version of it; which is both slow and inaccurate.)
To be able to roll back to an earlier version in the event of problems it'd be convenient to retain the last inactive version of each port, as well as the current active version. For any ports where all the versions are inactive (eg, for some other reason, such as conflicts between ports providing the same files) we'd still like to retain the last inactive version so that we can change our mind. So what we want to do is iterate through the list of ports with inactive versions, and then create commands to uninstall but the latest inactive version of that port:
INSTALLED=`port installed`
for PORT in `port echo inactive | awk '{print $1;}' | sort | uniq`; do
VERSIONS_TO_GO=`echo "${INSTALLED}" | grep " ${PORT} @" |
grep -v "active" | ghead -n-1 | awk '{print $2;}'`
if [ -n "${VERSIONS_TO_GO}" ]; then
for VERSION in ${VERSIONS_TO_GO}; do
echo port uninstall "${PORT}" "${VERSION}"
done
fi
done
which relies on the GNU "head" (part of MacPorts "coreutils" package) to pick all but the last line, and caches the output of "port installed" in a shell variable so as to avoid running the slow command repeatedly (and avoid creating temporary files). Note the spaces either size of the port name, to avoid matching partial names of ports.
The output of the above script can be redirected to a file, eg,
/tmp/togo.sh
, which can then be reviewed by comparing it
with the list of inactive ports (first command above) to make sure that
one inactive version of every port will be left. When doing so, be sure
to sort both lists again, so that they are sorted in the same manner.
Something like:
awk '{print $3, $4;}' /tmp/togo.sh | sort | tee tmp/going
port installed | grep "@" | grep -v active |
awk '{print $1, $2}' | sort | tee /tmp/inactive
diff /tmp/going /tmp/inactive | less
which should show one version of each inactive port (the last inactive one) not in the list to be removed.
When you're happy with the list of port versions to be uninstalled, you can then run through the created shell script removing those versions:
sudo sh -x /tmp/togo.sh
That will take quite a while to run (and be very disk bound) if there are lots of old versions of ports involved, which will generally make the machine slower than normally. But OTOH if there are lots of old versions of ports involved then a reasonable amount of disk space will be freed up as a result (I got back about 4 GiB of disk space). (Due to being very disk bound it is probably best to defer any other disk bound processing -- including Time Machine -- until after the port uninstallation run is complete.)
For selected ports, where you're sure that the current version is good,
you can also remove the last of the inactive port versions. Or even
uninstall all the inactive ports (sudo port uninstall
inactive
). It is possible to uninstall the previous version when
installing a new version (sudo port -u install ...
--
where the "-u" means uninstall the previous after installing the new
one).
Note that these commands don't attempt to clean up the distfiles
(eg, tarballs of downloaded software, held in
/opt/local/var/macports/distfiles
), largely because
often these can be reused in later builds and so it is worth the
disk space to avoid downloading them again. At some later point
it might be worth writing a shell script to scan the directories
there and remove all but the latest version of the tar files (using
similar techniques to the above).
The MacPorts guide to common tasks also has various other housekeeping tasks that might be required, such as pruning "leaves" (unrequested ports that nothing depends on any longer). There are various other guides around, that may have useful hints in them too.
ETA: One thing suggested in the MacPorts guide to common tasks is to check for "leaves" (packages not marked as requested, or dependencies of something that was), and consider uninstalling those. This is to deal with packages that were brought in by some other install, but are no longer required because that was removed or the dependencies have changed (ie, like "apt-get autoremove"). The basic idea is:
port echo leaves
Then review that list and look for things that you did intend to have installed and want to keep installed, and set them as requested, eg
sudo port setrequested autoconf automake gawk gpg-agent
periodically reviewing the "port echo leaves" output until it has been trimmed down to just the things that you don't actually want. Then you can consider uninstalling the ports still listed as leaves. Lather, rinse, and repeat (because when you remove some packages, others that were merely dependencies of those might now be leaves). (This will also turn up stub packages that have been replaced by other packages, but are no longer needed.)
It's probably also worth periodically reviewing whether keeping, eg, Python 2.5 or Perl 5.8 installed actually makes sense; and if not, various related ports (eg, libraries installed for multiple versions of Python or Perl) can also be removed. (I decided to remove Python 2.5 this time, just leaving Python 2.6 and Python 2.7.)