summaryrefslogtreecommitdiffstats
path: root/bin/depsdot
blob: 1e31fcf6d3714eac722775cf7e169a8d627ec0b5 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
#!/usr/bin/perl

use strict;
use warnings;
no indirect;
use autovivification;
use English qw(-no_match_vars);

use LWP::Simple;
use POSIX qw(strftime);

my $BASE_URL = 'http://files.proteanos.com/pub/proteanos/feeds/dev/trunk';
my @DEP_FIELDS = qw(Depends Recommends Suggests Pre-Depends);
my @IGNORE_DEPS = qw(libc.6);

my @src_pkgs;
my %bin_src_map;
my %rdeps_graph;
my %non_leaf_src_pkgs;
my %deps_graph;

sub read_list
{
	my ($list, $is_src) = @_;

	foreach my $para (split(m{\n\n}, get($list))) {
		my $package = undef;
		my $source = undef;
		my @deps;
		foreach my $line (split(m{\n}, $para)) {
			my ($name, $value) = split(m{\s*:\s*}, $line);
			if ($name eq 'Package') {
				$package = $value;
			}
			if ($name eq 'Source') {
				$source = $value;
			}
			if (grep(m{^\Q$name\E$}, @DEP_FIELDS)) {
				push(@deps, split(m{\s*,\s*}, $value));
			}
		}
		if ($is_src) {
			push(@src_pkgs, $source);
		} else {
			$bin_src_map{$package}{$source} = 1;
		}
		map({ $_ =~ s{[\s(].*$}{}; } @deps);  # Vim: )
		foreach my $dep (@deps) {
			next if grep(m{^\Q$dep\E$}, @IGNORE_DEPS);
			$rdeps_graph{$dep}{$source} = 1;
		}
	}

	return;
}

sub main
{
	my @manifest;

	@manifest = split(m{\n}, get($BASE_URL . '/Manifest'));
	foreach my $aps (@manifest) {
		read_list($BASE_URL . '/' . $aps . '/Packages',
			($aps =~ m{^src/}));
	}
	foreach my $dep_bin (keys(%rdeps_graph)) {
		foreach my $src (keys(%{$rdeps_graph{$dep_bin}})) {
			my @dep_srcs = keys(%{$bin_src_map{$dep_bin}});
			foreach my $dep_src (@dep_srcs) {
				next if $dep_src eq $src;
				$non_leaf_src_pkgs{$dep_src} = 1;
				$deps_graph{$src}{$dep_src} = scalar(@dep_srcs);
			}
		}
	}
	STDOUT->print("/*\n * ProteanOS source package dependencies\n */\n\n" .
		"strict digraph deps {\n" .
		"\toverlap = false;\n\tsplines = true;\n\tlayout = neato;\n" .
		"\tlabel = <<B>ProteanOS Source Package Dependencies as of " .
		strftime('%Y-%m-%d at %H:%M:%S %Z', localtime()) . "</B><BR/>" .
		"\n\t\tGray nodes are leaf packages (no reverse dependencies)" .
		"<BR/>\n\t\tGray edges are dependencies on multiple source " .
		"packages&nbsp;\n\t\t\tthat build binaries of the same name>;" .
		"\n\tgraph [fontname=\"FreeSans\"];\n" .
		"\tnode [fontname=\"FreeSans\"];\n" .
		"\tedge [fontname=\"FreeSans\"];\n\n\t/* Source packages */\n");
	foreach my $src (sort(@src_pkgs)) {
		my $attr = '';
		if (not defined($non_leaf_src_pkgs{$src})) {
			$attr = ' [style=filled,fillcolor="#C0C0C0"]';
		}
		STDOUT->print("\t\"" . $src . '"' . $attr . ";\n");
	}
	STDOUT->print("\n\t/* Dependencies */\n");
	foreach my $src (sort(keys(%deps_graph))) {
		foreach my $dep_src (sort(keys(%{$deps_graph{$src}}))) {
			my $attr = '';
			if ($deps_graph{$src}{$dep_src} gt 1) {
				$attr = ' [color="#808080"]';
			}
			STDOUT->print("\t\"" . $src . '" -> "' .  $dep_src .
				'"' . $attr . ";\n");
		}
	}
	STDOUT->print("}\n");

	return 0;
}

exit(main());