Recursive dependencies, recursive uninstall, variants

Ryan Schmidt ryandesign at macports.org
Fri Apr 25 22:15:17 PDT 2008


On Apr 25, 2008, at 12:59 PM, Shreevatsa R wrote:

> Hi MacPorts developers,
>
> I was planning to write some non-trivial code before posting to this
> list, but I thought I would first check if I was doing anything
> stupid.
>
> I found that the "port deps" command only lists the explicit
> dependencies of a port, and not everything that the port actually
> depends on ("recursive dependencies"). This meant that often
> installing something trivial looking would start pulling in something
> enormous that I didn't want to install, and I would have to kill it,
> or wait hours. Contrast this to something like Debian's apt (used by
> Fink too), which when you try to install something, gives a message
> like:
>      # apt-get install nautilus
>      Reading Package Lists... Done
>      Building Dependency Tree... Done
>      The following extra packages will be installed:
>        bonobo libmedusa0 libnautilus0
>      The following NEW packages will be installed:
>        bonobo libmedusa0 libnautilus0 nautilus
>      0 packages upgraded, 4 newly installed, 0 to remove and 1  not  
> upgraded.
>      Need to get 8329kB of archives. After unpacking 17.2MB will be  
> used.
>      Do you want to continue? [Y/n]
>
> So deciding that at least knowing all dependencies of a port
> beforehand would help, I tried writing a command for recursive
> dependencies. The proc action_deps does a lot of stuff, and it's not
> easy getting just the list of dependencies with no extra output, so I
> wrote my own "bare" proc that does the actual dependencies, etc., and
> rdeps that recursively calls it:
>
> proc add_to_set {set_var item} {
>     upvar $set_var var
>     if {[lsearch -exact $var $item] == -1}  { lappend var $item }
> }
>
> proc actdeps {portname depstype} {
>     array unset portinfo
>     array set portinfo [lindex [mportsearch $portname no exact] 1]
>
>     #set deps [map {x {lindex [split $x :] end}} $portinfo($depstype)]
>     set deps []
>     if {[info exists portinfo($depstype)]} {
>         foreach i $portinfo($depstype) {
>             lappend deps [lindex [split $i :] end]
>         }
>     }
>     return $deps
> }
>
> proc rdeps {portname {depth 0}} {
>     global shownports
>     if [info exists shownports] {    } else { set shownports [] }
>     add_to_set shownports $portname
>
>     set depstypes {depends_build depends_lib depends_run}
>     set depstypes_descr {"build" "library" "runtime"}
>
>     foreach depstype $depstypes depsdecr $depstypes_descr {
>         foreach port [actdeps $portname $depstype] {
>             if {[lsearch $shownports $port] == -1} {
>                 puts "[string repeat \t $depth]$port"
>                 rdeps $port [expr {$depth + 1}]
>             }
>         }
>     }
> }
>
> proc action_rdeps {action portlist opts} {
>     foreachport $portlist {
>         rdeps $portname
>     }
> }
>
> And "rdeps       action_rdeps" in action_array. Yeah, it uses a global
> variable to avoid printing the same ports again, but it works:
>
> ~$ port rdeps subversion
> expat
> neon
>         gettext
>                 libiconv
>                         gperf
>                 ncurses
>                         ncursesw
>         openssl
>                 zlib
> apr
> apr-util
>         db44
>         sqlite3
>                 gawk
>                 gmake
>                 readline
>
> This is not great code, but it does what I want. (It is also the only
> Tcl I have ever written, so please tell me what I'm doing stupidly.)
> I was planning to do the same for variants (because I install
> something and later discover I should have installed one of its
> dependencies with a different variant), and for uninstall (because it
> is a real pain to uninstall ports).
> More specifically, I was planning to
> (1) make a general (simple) function for getting a specific port's
> "tree of dependencies" (and/or tree of dependents) and then something
> to act on it. Uninstall would then be trivial.
> (2) Also, putting something to return the list of dependencies of a
> port in the MacPorts API itself.
> (3) Also, looking at action_deps, it seems to share a lot in common
> with other functions (searching for ports, etc.), so that part can be
> cleaned up...
>
> Comments?

Being able to get a recursive list of dependencies would certainly be  
useful. I wrote a PHP web page [1] to display a graph of this  
information, because I also wanted to see it. Would be handy to have  
the main logic in the port command. Should make it faster.


[1] http://www.ryandesign.com/tmp/portviz.tar.bz2


More information about the macports-dev mailing list