3 use warnings FATAL => qw(all);
11 # $installed{name} = $version
14 # $modules{$name}{$version} = {
15 # url => URL of this version (or INSECURE/DEPRECATED)
16 # depends => [ 'm_foo 1.2.0-1.3.0', ... ]
18 # from => URL of source document
27 return if $url_seen{$src};
31 die "Could not retrieve $_" unless defined $doc;
34 for (split /\n+/, $doc) {
35 s/^\s+//; # ignore whitespace at start
36 if (/^module (\S+) ([0-9.]+) (\S+)/) {
37 my($name, $ver, $url) = ($1,$2,$3);
38 if ($modules{$name}{$ver}) {
39 my $origsrc = $modules{$name}{$ver}{from};
40 warn "Overriding module $name $ver defined from $origsrc with one from $src";
48 $modules{$name}{$ver} = $mod;
49 } elsif (/^depends (.*)/) {
50 push @{$mod->{depends}}, $1;
51 } elsif (/^conflicts (.*)/) {
52 push @{$mod->{conflicts}}, $1;
53 } elsif (m#^source (http://\S+)#) {
56 print "Unknown line in $src: $_\n";
61 open SRC, 'sources.list' or die "Could not open sources.list: $!";
69 open my $verfile, 'src/version.sh' or die "Cannot determine inspircd version: $!";
70 $_ = join '', <$verfile>;
71 die "Cannot determine inspircd version" unless /InspIRCd-([0-9.]+)/;
72 $installed{core} = $1;
73 $modules{core}{$1} = {
81 for my $modname (@modlist) {
82 my $mod = "m_$modname";
83 my $modfile = "src/modules/$mod.cpp";
84 my $ver = getmodversion($modfile) || '0.0';
85 $installed{$mod} = $ver;
86 next if $modules{$mod}{$ver};
87 $modules{$mod}{$ver} = {
95 my %todo = %installed;
99 my @a = split /\./, $a;
100 my @b = split /\./, $b;
101 push @a, 0 while $#a < $#b;
102 push @b, 0 while $#b < $#a;
104 my $d = $a[$i] <=> $b[$i];
111 my($ver, $range) = @_;
112 return 1 unless defined $range;
113 if ($range =~ /(.*)-(.*)/) {
115 return 0 unless ver_cmp($ver, $l) >= 0;
116 return 0 unless ver_cmp($ver, $h) <= 0;
119 return !ver_cmp($ver, $range);
122 sub find_mod_in_range {
124 my @versions = keys %{$modules{$mod}};
125 @versions = sort { ver_cmp() } @versions;
126 for my $ver (reverse @versions) {
127 return $ver if ver_in_range($ver, $vers);
134 my $changes = 'INIT';
136 while ($changes && $tries) {
140 my @modsnow = sort keys %todo;
141 for my $mod (@modsnow) {
142 my $ver = $todo{$mod};
143 my $info = $modules{$mod}{$ver} or die "no dependency information on $mod $ver";
144 for my $dep (@{$info->{depends}}) {
145 $dep =~ /^(\S+)(?: ([-0-9.]+))?/ or die "Bad dependency $dep from $info->{from}";
146 my($depmod, $depvers) = ($1,$2);
147 next if $todo{$depmod} && ver_in_range($todo{$depmod}, $depvers);
148 # need to install a dependency
149 my $depver = find_mod_in_range($depmod, $depvers);
150 if (defined $depver) {
151 $todo{$depmod} = $depver;
152 $changes .= " $mod-$ver->$depmod-$depver";
154 $fail ||= "Could not find module $depmod $depver required by $mod $ver";
157 for my $dep (@{$info->{conflicts}}) {
158 $dep =~ /^(\S+)(?: ([-0-9.]+))?/ or die "Bad dependency $dep from $info->{from}";
159 my($depmod, $depvers) = ($1,$2);
160 next unless $todo{$depmod} && ver_in_range($todo{$depmod}, $depvers);
161 # if there are changes this round, maybe the conflict won't come up after they are resolved.
162 $fail ||= "Cannot install: module $mod ($ver) conflicts with versions $depmod version $todo{depmod}";
167 print "Infinite dependency loop:$changes\n";
176 my $action = lc shift @ARGV;
178 if ($action eq 'install') {
179 for my $mod (@ARGV) {
180 my $vers = $mod =~ s/=([-0-9.]+)// ? $1 : undef;
182 unless ($modules{$mod}) {
183 print "Cannot find module $mod\n";
186 my $ver = find_mod_in_range($mod, $vers);
188 print "Cannot find suitable version of $mod\n";
193 } elsif ($action eq 'upgrade') {
194 for my $mod (keys %installed) {
195 next unless $mod =~ /^m_/;
196 $todo{$mod} = find_mod_in_range($mod);
199 die "Unknown action $action"
204 $| = 1; # immediate print of lines without \n
206 for my $mod (keys %installed) {
208 print "Uninstalling $mod $installed{$mod}\n";
209 unlink "src/modules/$mod.cpp";
211 for my $mod (sort keys %todo) {
212 my $ver = $todo{$mod};
213 my $oldver = $installed{$mod};
214 my $url = $modules{$mod}{$ver}{url};
215 if ($url eq 'INSECURE') {
216 print "WARNING: Version $ver of $mod is insecure!\n";
218 } elsif ($url eq 'DEPRECATED') {
219 print "Note: version $ver of $mod is deprecated\n";
222 next if $oldver && $oldver eq $ver;
224 print "Upgrading $mod from $oldver to $ver using $url"
226 print "Installing $mod $ver from $url";
228 my $stat = getstore($url, "src/modules/$mod.cpp");
232 print " - HTTP $stat\n";