summaryrefslogtreecommitdiff
path: root/src/BuildOrder.pm
blob: 08362095e706544563fdaa0a4ef1da692d7ddc75 (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
package BuildOrder;
# tools for determining which order to build packages 

use strict;
use warnings;

use File::Basename "basename";
use Sort::TSort "tsort";

sub list_dependencies{
    my $file = $_;
    my @deps = ();

    open (my $fh, "<", $file) or warn "Cannot open $file";

    while (my $line = <$fh>) {
        if ($line =~ /DEPS=\((.+)\)/) {
            my @words = split(/ /, $1);
            push(@deps, @words);
        }
    }

    return @deps;
}

sub list_buildfiles{
    my @files = glob("$main::buildfiles/repo/*/*.xibuild");
    # ignore any meta packages during this stage, they can be added later
    return grep(!/\/meta\//, @files);
}

sub list_meta_pkgs{
    return map({basename($_, ".xibuild")} glob("$main::buildfiles/repo/meta/*.xibuild"));
}

sub get_packages{
    my %pkgs = ();
    
    my @files = list_buildfiles();

    foreach (@files) {
        my $pkg_file = $_;
        my $pkg_name = basename($pkg_file, ".xibuild");

        my @deps = list_dependencies($pkg_file);
        $pkgs{$pkg_name} = \@deps;
    }

    return %pkgs;
}

# Get a list of all the edges 
sub get_edges{
    my %pkgs = @_;

    my @edges = ();
    foreach (keys(%pkgs)) {
        my $pkg = $_;
        my @deps = @{$pkgs{$_}};
        foreach (@deps) {
            my $dep = $_;

            my @edge = ($pkg, $dep);
            push @edges, [ @edge ];

        }
    }
    return @edges;
}

# Determine which packages are depended on
sub get_depended_on{
    my @edges = @_;

    my %install = ();
    foreach (@edges) {
        my @edge = @{$_};
        $install{$edge[1]} = $edge[0];
    }
    
    return keys(%install);
}

sub determine_build_order{
    my ($file) = @_;
    my %pkgs = get_packages();

    my @edges = get_edges(%pkgs);

    my @install = get_depended_on(@edges);

    # use tsort to determine the build order
    my @sorted = reverse(@{tsort(\@edges)});

    my @meta = list_meta_pkgs();
    push(@sorted, @meta);

    open (my $fh, ">", $file) or die "Cannot open $file";

    foreach(@sorted) {
        my $pkg = $_;
        print($fh "$pkg");
        print($fh "+") if (grep(/^$pkg/, @install));
        print($fh "\n");
    }

    return $file;
}

1;