#!/usr/bin/perl -w

#
# ==Authors==
#   Lukas Ocilka <locilka@suse.cz>
#
# ==About==
#   Script generates all logic dependencies between YaST modules.
#   It uses another script from devtools 'check_deps'.
#   This script needs to be called in the root of YaST SVN because
#   directories are used for generating RPM names.
#
#   Script generates input file for 'dot' program (/usr/bin/dot, graphviz.rpm)
#
# ==Usage==
#   cd /...../source/; # copy of YaST trunk or any branch
#   /usr/share/YaST2/data/devtools/bin/gen_logic_deps [rpm_root [show_base]] > dot-in.txt
#   dot -Tpng -oGraph.png dot-in.txt
#   display Graph.png
#
# ==Examples==
#   * /usr/share/YaST2/data/devtools/bin/gen_logic_deps > dot-in.txt
#     - uses "/" as a default --root for RPM queries
#     - doesn't include yast2.rpm
#
#   * /usr/share/YaST2/data/devtools/bin/gen_logic_deps / yes > dot-in.txt
#     - uses "/" as a default --root for RPM queries
#     - includes yast2.rpm in the output
#
# ==Output==
#   digraph "YaST RPM dependencies" {
#       [...]
#       "yast2-repair (0)" -> "yast2 (81)" [ color="black" ]
#       "yast2-repair (0)" -> "yast2-bootloader (9)" [ color="black" ]
#       "yast2-repair (0)" -> "yast2-storage (13)" [ color="black" ]
#       [...]
#   }
#
#   And what does it mean :)?
#       * 'yast2-repair' requires 'yast2'
#       * 'yast2-repair' requires 'yast2-bootloader'
#       * 'yast2-repair' requires 'yast2-storage'
#       * 'yast2' is required by 81 YaST RPMs
#       * 'yast2-bootloader' is requierd by 9 YaST RPMs
#       * 'yast2-storage' is requierd by 13 YaST RPMs
#       * 'yast2-repair' is not required by any YaST RPM
#

# change this for debugging purpose, scripts exists after checking 'n' directories
my $max_dirs_at_once = 9999;

my $wd = `pwd`;
chop $wd;
warn "Working dir: '".$wd."'\n";

# RPM-root, first commandline parameter or "/"
my $root = $ARGV[0] || "/";

# Show yast2.rpm-related deps, second commandline parameter, default false
# anything == true
$show_base = 0;
if (defined $ARGV[1]) {
    $show_base = 1;
}

warn "Root: ".$root."\n";

$reqrpms = {};

my $rpms_of_files = {};

# how many times is a package required
my $all_RPM_req = {};

sub CheckDir ($) {
    my $dir = shift;

    my $RPM_deps = {};

    my $lines_s = `cd $wd/$dir; /usr/share/YaST2/data/devtools/bin/check_deps . . '$root'`;

    # try to imagine the RPM name
    if ($dir =~ /autoinstallation/) {
	$dir = "autoyast2-installation";
    } elsif ($dir =~ /autoyast2/) {
	$dir = "autoyast2";
    } elsif ($dir eq "yast2") {
	$dir = "yast2";
    } else {
	$dir = 'yast2-'.$dir;
    }

    warn "\tIdentified as: ".$dir."\n";

    my @lines = split (/\n/, $lines_s);
    foreach my $line (@lines) {
	next if ($line !~ /^([^ \t]+)[ \t]+File: (.*)$/);

	my $yast_rpm = $1;
	my $yast_module = $2;

	### do not report dependency on yast2.rpm
	### if not explicitely requested
	next if ($show_base == 0 && $yast_rpm eq 'yast2');
	### do not report itself
	next if ($yast_rpm eq $dir);

	push @{$reqrpms->{$yast_rpm}}, $dir;

	$RPM_deps->{$yast_rpm} = 1;
    }

    foreach my $key (keys (%{$RPM_deps})) {
	warn "\t* RPM ".$dir." requires ".$key."\n";
	if (! defined $all_RPM_req->{$key}) {
	    $all_RPM_req->{$key} = 0;
	}
	++$all_RPM_req->{$key};
    }
}

opendir (DIR, $wd) || do {
    warn "Cannot open directory ".$wd.": ".$!;
    exit 2;
};

foreach my $dir (readdir (DIR)) {
    # not a directory
    next if (! -d $dir);
    next if ($dir =~ /^\./);
    # blacklist
    next if ($dir =~ /^(qt|gtk|cim|xml|core|ncurses|pkg-bindings|liby2util|perl-bindings|packagemanager-test|devtools|ruby-bindings|y2pmsh)$/);
    next if ($max_dirs_at_once <= 0);
    --$max_dirs_at_once;

    warn "Checking dir: '".$dir."'\n";
    CheckDir ($dir);
}

closedir (DIR);

warn " \n";
warn " \n";

my $print_it_arrows = {};
my $print_key = "";

sub HowManyTimesRequired ($) {
    my $rpm = shift || "";

    if (! defined $all_RPM_req->{$rpm}) {
	return 0;
    } else {
	return $all_RPM_req->{$rpm};
    }
}

foreach my $key (sort ({@{$reqrpms->{$b}} <=> @{$reqrpms->{$a}}} keys %{$reqrpms})) {
    foreach my $module (sort {$a cmp $b} (@{$reqrpms->{$key}})) {
	$print_it_arrows->{"\t\"".$module." (".HowManyTimesRequired($module).")\" -> \"".$key." (".HowManyTimesRequired($key).")\" [ color=\"black\" ]\n"} = 1;
    }
}

print "digraph \"YaST RPM dependencies\" {\n\n";

foreach my $key (sort {$a cmp $b} (keys %{$print_it_arrows})) {
    print $key;
}

print "\n}\n";

exit 0;