X-Git-Url: https://git.netwichtig.de/gitweb/?a=blobdiff_plain;f=modulemanager;h=0e978977abdc098d17f1b202c8af2e31ff450dba;hb=6e6846b68a28d858275702e6662e79328e62c60e;hp=2f3d0a505a7ce71941119fef271050c949f1c2db;hpb=3e72c8cb7eb2daf7419d00a9ff50eda3cbb40db3;p=user%2Fhenk%2Fcode%2Finspircd.git diff --git a/modulemanager b/modulemanager index 2f3d0a505..0e978977a 100755 --- a/modulemanager +++ b/modulemanager @@ -12,16 +12,19 @@ my %installed; my %modules; # $modules{$name}{$version} = { -# url => URL of this version (or INSECURE/DEPRECATED) +# url => URL of this version # depends => [ 'm_foo 1.2.0-1.3.0', ... ] # conflicts => [ ] # from => URL of source document +# mask => Reason for not installing (INSECURE/DEPRECATED) +# description => some string # } my %url_seen; sub parse_url; +# retrieve and parse entries from sources.list sub parse_url { my $src = shift; return if $url_seen{$src}; @@ -34,7 +37,7 @@ sub parse_url { 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}; @@ -51,6 +54,10 @@ sub parse_url { push @{$mod->{depends}}, $1; } elsif (/^conflicts (.*)/) { push @{$mod->{conflicts}}, $1; + } elsif (/^description (.*)/) { + $mod->{description} = $1; + } elsif (/^mask (.*)/) { + $mod->{mask} = $1; } elsif (m#^source (http://\S+)#) { parse_url $1; } else { @@ -59,6 +66,29 @@ sub parse_url { } } +# 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 () + { + 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 () { next if /^\s*#/; @@ -66,11 +96,10 @@ while () { } close SRC; -getmodules(); +getmodules(1); -open my $verfile, 'src/version.sh' or die "Cannot determine inspircd version: $!"; -$_ = join '', <$verfile>; -die "Cannot determine inspircd version" unless /InspIRCd-([0-9.]+)/; +# determine core version +`./src/version.sh` =~ /InspIRCd-([0-9.]+)/ or die "Cannot determine inspircd version"; $installed{core} = $1; $modules{core}{$1} = { url => 'NONE', @@ -78,12 +107,13 @@ $modules{core}{$1} = { conflicts => [], from => 'local file', }; -close $verfile; +# 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}; $modules{$mod}{$ver} = { @@ -98,6 +128,15 @@ my %todo = %installed; 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; @@ -114,24 +153,26 @@ sub ver_in_range { 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); } sub find_mod_in_range { - my($mod,$vers) = @_; + my($mod, $vers, $force) = @_; my @versions = keys %{$modules{$mod}}; - @versions = sort { ver_cmp() } @versions; - for my $ver (reverse @versions) { + @versions = sort { -ver_cmp() } @versions; + for my $ver (@versions) { + next if $modules{$mod}{$ver}{mask} && !$force; return $ver if ver_in_range($ver, $vers); } return undef; } sub resolve_deps { + my($trial) = @_; my $tries = 100; my $changes = 'INIT'; my $fail = undef; @@ -144,7 +185,7 @@ sub resolve_deps { 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 @@ -153,18 +194,21 @@ sub resolve_deps { $todo{$depmod} = $depver; $changes .= " $mod-$ver->$depmod-$depver"; } else { - $fail ||= "Could not find module $depmod $depver required by $mod $ver"; + $fail ||= "Could not find module $depmod $depvers required by $mod $ver"; } } 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. - $fail ||= "Cannot install: module $mod ($ver) conflicts with versions $depmod version $todo{depmod}"; + $fail ||= "Cannot install: module $mod ($ver) conflicts with $depmod version $todo{$depmod}"; } } } + if ($trial) { + return !($changes || $fail); + } if ($changes) { print "Infinite dependency loop:$changes\n"; exit 1; @@ -185,7 +229,7 @@ if ($action eq 'install') { print "Cannot find module $mod\n"; exit 1; } - my $ver = find_mod_in_range($mod, $vers); + my $ver = find_mod_in_range($mod, $vers, $vers ? 1 : 0); unless ($ver) { print "Cannot find suitable version of $mod\n"; exit 1; @@ -193,40 +237,71 @@ if ($action eq 'install') { $todo{$mod} = $ver; } } elsif ($action eq 'upgrade') { - for my $mod (keys %installed) { + my @installed = sort keys %installed; + for my $mod (@installed) { next unless $mod =~ /^m_/; + my %saved = %todo; $todo{$mod} = find_mod_in_range($mod); + if (!resolve_deps(1)) { + %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 < +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(); +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}; - my $url = $modules{$mod}{$ver}{url}; - if ($url eq 'INSECURE') { - print "WARNING: Version $ver of $mod is insecure!\n"; - next; - } elsif ($url eq 'DEPRECATED') { - print "Note: version $ver of $mod is deprecated\n"; - next; + if ($modules{$mod}{$ver}{mask}) { + print "Module $mod $ver is masked: $modules{$mod}{$ver}{mask}\n"; } next if $oldver && $oldver eq $ver; + my $url = $modules{$mod}{$ver}{url}; if ($oldver) { print "Upgrading $mod from $oldver to $ver using $url" } 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"; @@ -234,3 +309,13 @@ for my $mod (sort keys %todo) { 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";