Date: Tue, 24 Apr 2001 07:16:25 -0700 (PDT) From: Jeff Kletsky <Jeff+freebsd@wagsky.com> To: freebsd-stable@freebsd.org Subject: Re: pkg/port dependency tool (enclosed) Message-ID: <Pine.BSF.4.21.0104240708590.5506-100000@wildside.wagsky.com> In-Reply-To: <15076.20167.337195.349137@guru.mired.org>
next in thread | previous in thread | raw e-mail | index | archive | help
Thanks to some good pointers, I have an *alpha* of the text-output version of the tool available. I need to integrate with the code already in pkg_version and resolve how to detect and include the dependencies introduced by the USE_* variables. I'll probably be quiet for a while, the "easy" part is done -- now to make it a robust tool... Jeff #!/usr/bin/perl -w # $Header: /usr/local/cvsroot/pkg_graph/graph_depends.pl,v 1.4 2001/04/24 14:08:28 jeff Exp $ # # Tool to read from /var/db/pkg to find all pkg/port dependencies # create a graph and solve for process to rebuild ports in "proper # order" # # Examples of use: # # pkg_version -L = | cut -f 1 -d " " | graph_depends.pl # # graph_depends.pl -a # # Status: ALPHA development # Author: Jeff Kletsky mailto:jeff+freebsd@wagsky.com # # TODO: # # * use '/usr/sbin/pkg_version'; to access the ports index, tie nodes # to their cannonical names, and ouput code to rebuild ports # # * deal with the USE_BZIP2 variables that Kevin Way has pointed out # # * Include dependencies of ports about to be built # # * Discriminate between existing dependencies and future ones # - How are "orphaned" ports to be handled?? # # * Consider solving the problem where the changes are driven by # wishing to rebuild a target, all its predecessors, and all their # successors (e.g., " I need a clean version of gnome") # # # Thanks to: # # * Mike Meyer for mumbling the words "transitive closure of the # dependency matrix" and getting this rolling in the right direction # # * Garance Drosihn for providing me to Kevin Way's comments on the # USE_ variable issue # use strict; use POSIX qw(EXIT_FAILURE EXIT_SUCCESS); use FileHandle; require Graph; # (not yet in the ports tree) my $usage = qq( Usage: $0 [-a] Reads a list of packages/ports to be updated from STDIN and prints a suggested order for updating those packages/ports based on the dependencies seen in the installed list of packages/ports in /var/db/pkg -a Ignores STDIN and looks at all registered packages/ports ); my $doall = 0; if ( $#ARGV > 0 ) { die $usage; } if ( $#ARGV == 0 ) { $doall = ( shift @ARGV eq "-a" ); die $usage unless $doall; } my $pkg_db_dir = '/var/db/pkg'; $pkg_db_dir =~ s/\/$//; # prevent "trailing-slash" issue my $required_by_filename = '+REQUIRED_BY'; # # Open the directory that contains pkg/port information # opendir (VARDBPKG, $pkg_db_dir) or die "Unable to open $pkg_db_dir: $!"; # # Get the subdirectories, and iterate through them # my @installed_pkgs = readdir VARDBPKG; die "No files read in $pkg_db_dir\n" unless $#installed_pkgs > 1; # # Read the list of files from STDIN # my $target; my %targets; if ( !$doall ) { while ( $target = <> ) { chomp $target; $targets{$target} = 'true'; } } else { foreach $target (@installed_pkgs) { $targets{$target} = 'true'; } } my $pkg; my $rqd; my $required_by_fqn; my $required_by_fh; my $pkg_node; my $rqd_node; my $graph = new Graph; $graph->directed('true'); PKG: foreach $pkg (sort @installed_pkgs) { next PKG if $pkg =~ m/^\./; $graph->add_vertex($pkg); # # See if there is a +REQUIRED_BY file, open it, and process lines # $required_by_fqn = "${pkg_db_dir}/${pkg}/${required_by_filename}"; next PKG unless -e $required_by_fqn; $required_by_fh = new FileHandle "< $required_by_fqn"; die "Unable to open $required_by_fqn: $!" unless defined $required_by_fh; while ($rqd = <$required_by_fh>) { chomp $rqd; $graph->add_edge($pkg,$rqd); } } # PKG # # Now that we have the full graph, check for loops # Loops should "never" occur or certain ports would be un-buildable # It *is* vaguely possible that the dependencies change and create a loop # after one of the components in the loop were already built. # Since this is a remote possibility, just die... # die "Graph loops back on itself, unable to resolve" if ( $graph->self_loop_vertices ); if (! $doall ) { # # If not looking at all pkgs/ports, trim the tree # my $tcgraph = $graph->TransitiveClosure_Floyd_Warshall; # # Mark and sweep # # # Note that the output of pkg_version is "unqualified" # create a new list that identifies all old and new targets # my %tgt_pkgs; my $tgtmatch; foreach $pkg ($graph->vertices) { $graph->delete_attribute('candidate', $pkg); foreach $target (keys %targets) { $tgtmatch = "^" . quotemeta($target); $tgt_pkgs{$pkg} = 'true' if $pkg =~/$tgtmatch/; } } foreach $target (keys %tgt_pkgs) { # print "setting $target\n"; $graph->set_attribute('candidate', $target, 'true') ; foreach $pkg ($graph->vertices) { $graph->set_attribute('candidate', $pkg, 'true') # && print "setting $pkg as dependent on $target\n" if $tcgraph->has_edge($target, $pkg); } } foreach $pkg ($graph->vertices) { $graph->delete_vertex($pkg) unless $graph->get_attribute('candidate', $pkg); } } # # Start dumping out the order of processing # my $level = 0; my @pkgs; while ( $graph->vertices ) { print "\n\nLevel ${level}:\n"; print "========\n"; @pkgs = ($graph->isolated_vertices, $graph->source_vertices); print join("\n", sort(@pkgs)); $graph->delete_vertices(@pkgs); die "No packages found which can be built at this level, unable to resolve" unless @pkgs; $level++; } print "\n\nDone\n"; exit EXIT_SUCCESS; To Unsubscribe: send mail to majordomo@FreeBSD.org with "unsubscribe freebsd-stable" in the body of the message
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?Pine.BSF.4.21.0104240708590.5506-100000>