sub parse_url;
+# retrieve and parse entries from sources.list
sub parse_url {
my $src = shift;
return if $url_seen{$src};
for (split /\n+/, $doc) {
s/^\s+//; # ignore whitespace at start
next if /^#/;
- if (/^module (\S+) ([0-9.]+) (\S+)/) {
+ if (/^module (\S+) (\S+) (\S+)/) {
my($name, $ver, $url) = ($1,$2,$3);
if ($modules{$name}{$ver}) {
my $origsrc = $modules{$name}{$ver}{from};
}
}
+# hash of installed module versions from our mini-database, key (m_foobar) to version (00abacca..).
+my %mod_versions;
+
+# useless helper stub
+sub getmodversion {
+ my ($file) = @_;
+ return $mod_versions{$file};
+}
+
+# read in installed versions
+if (-e '.modulemanager')
+{
+ open SRC, '.modulemanager' or die ".modulemanager exists but i can't read it: $!";
+ while (<SRC>)
+ {
+ s/\n//;
+ (my $mod, my $ver) = split(/ /, $_);
+ $mod_versions{$mod} = $ver;
+ }
+ close SRC;
+}
+
+# read in external URL sources
open SRC, 'sources.list' or die "Could not open sources.list: $!";
while (<SRC>) {
next if /^\s*#/;
}
close SRC;
-getmodules();
+getmodules(1);
+# determine core version
`./src/version.sh` =~ /InspIRCd-([0-9.]+)/ or die "Cannot determine inspircd version";
$installed{core} = $1;
$modules{core}{$1} = {
from => 'local file',
};
+# set up core module list
for my $modname (@modlist) {
my $mod = "m_$modname";
my $modfile = "src/modules/$mod.cpp";
- my $ver = getmodversion($modfile) || '0.0';
+ my $ver = getmodversion($mod) || '0.0';
$ver =~ s/\$Rev: (.*) \$/$1/; # for storing revision in SVN
$installed{$mod} = $ver;
next if $modules{$mod}{$ver};
sub ver_cmp {
($a,$b) = @_ if @_;
+
+ # string versions first, git IDs
+ if ($a =~ /[a-z0-9]{40}/ or $b =~ /[a-z0-9]{40}/)
+ {
+ # it's a string version. compare them as such.
+ return $a ne $b;
+ }
+
+ # else it's probably a numerical type version.. i.e. 1.0
my @a = split /\./, $a;
my @b = split /\./, $b;
push @a, 0 while $#a < $#b;
return 1 unless defined $range;
if ($range =~ /(.*)-(.*)/) {
my($l,$h) = ($1,$2);
- return 0 unless ver_cmp($ver, $l) >= 0;
- return 0 unless ver_cmp($ver, $h) <= 0;
+ return 0 if $l && ver_cmp($ver, $l) < 0;
+ return 0 if $h && ver_cmp($ver, $h) > 0;
return 1;
}
return !ver_cmp($ver, $range);
my $ver = $todo{$mod};
my $info = $modules{$mod}{$ver} or die "no dependency information on $mod $ver";
for my $dep (@{$info->{depends}}) {
- $dep =~ /^(\S+)(?: ([-0-9.]+))?/ or die "Bad dependency $dep from $info->{from}";
+ $dep =~ /^(\S+)(?: (\S+))?/ or die "Bad dependency $dep from $info->{from}";
my($depmod, $depvers) = ($1,$2);
next if $todo{$depmod} && ver_in_range($todo{$depmod}, $depvers);
# need to install a dependency
}
}
for my $dep (@{$info->{conflicts}}) {
- $dep =~ /^(\S+)(?: ([-0-9.]+))?/ or die "Bad dependency $dep from $info->{from}";
+ $dep =~ /^(\S+)(?: (\S+))?/ or die "Bad dependency $dep from $info->{from}";
my($depmod, $depvers) = ($1,$2);
next unless $todo{$depmod} && ver_in_range($todo{$depmod}, $depvers);
# if there are changes this round, maybe the conflict won't come up after they are resolved.
%todo = %saved;
}
}
+} elsif ($action eq 'list') {
+ my @all = sort keys %modules;
+ for my $mod (@all) {
+ my @vers = sort { ver_cmp() } keys %{$modules{$mod}};
+ my $desc = '';
+ for my $ver (@vers) {
+ # latest defined description wins
+ $desc = $modules{$mod}{$ver}{description} || $desc;
+ }
+ next if @vers == 1 && $modules{$mod}{$vers[0]}{url} eq 'NONE';
+ my $instver = $installed{$mod} || '';
+ my $vers = join ' ', map { $_ eq $instver ? "\e[1m$_\e[m" : $_ } @vers;
+ print "$mod ($vers) - $desc\n";
+ }
} else {
- die "Unknown action $action"
+ print <<ENDUSAGE
+Use: $0 <action> <args>
+Action is one of the following
+ install install new modules
+ upgrade upgrade installed modules
+ list lists available modules
+
+For installing a package, specify its name or name=version to force the
+installation of a specific version.
+ENDUSAGE
+;exit 1;
}
resolve_deps(0);
$| = 1; # immediate print of lines without \n
+print "Processing changes for $action...\n";
for my $mod (keys %installed) {
next if $todo{$mod};
print "Uninstalling $mod $installed{$mod}\n";
unlink "src/modules/$mod.cpp";
}
+
+my $count = scalar keys %todo;
+print "Checking $count items...\n";
for my $mod (sort keys %todo) {
my $ver = $todo{$mod};
my $oldver = $installed{$mod};
} else {
print "Installing $mod $ver from $url";
}
+ $mod_versions{$mod} = $ver;
+
my $stat = getstore($url, "src/modules/$mod.cpp");
if ($stat == 200) {
print " - done\n";
print " - HTTP $stat\n";
}
}
+
+# write database of installed versions
+open SRC, '>.modulemanager' or die "can't write installed versions to .modulemanager, won't be able to track upgrades properly: $!";
+foreach my $key (keys %mod_versions)
+{
+ print SRC "$key $mod_versions{$key}\n";
+}
+close SRC;
+
+print "Finished!\n";