#!/usr/bin/env perl # # pkg-repgen: generates a binary repository for pkg-get # # requires prt-get # # html index generation code adapted from Jukka Heino's portspage # # usage: pkg-repgen [..] # use warnings; use strict; use Getopt::Long; use Digest::file qw(digest_file_hex); our $prtget = "/usr/bin/prt-get"; our $prtdir; our $title = "CRUX Packages"; our $header; our $footer; GetOptions("prtdir=s"=>\$prtdir, "title=s"=>\$title, "header=s"=>\$header, "footer=s"=>\$footer); # Use compression-mode defined in pkgmk-conf our $compress = "gz"; open CONFIG, "/etc/pkgmk.conf" or die "Could not open /etc/pkgmk.conf"; while () { $compress = $1 if m/^PKGMK_COMPRESSION_MODE=(.*)(\#|$)/; } close CONFIG; $compress =~ s/["' ]//g; $prtget .= " --no-std-config --config-set=\"prtdir $prtdir\"" if ($prtdir); my @dirlist = glob("*#*.pkg.tar.$compress"); my @packages; if ($#ARGV >= 0) { # single packages foreach my $pkgname (@ARGV) { my @hits = sort grep { /^$pkgname\#/ } @dirlist; push(@packages,$hits[-1]) if (@hits); } } else { @packages = @dirlist; } # Populate hashes using a single run of prt-get our %path; our %depends; our %descrip; our %flags; my @validkeys = @dirlist; map { s/\#.*// } @validkeys; my %printme = map { $_ => 1 } @validkeys; open (my $ppf, "$prtget printf '%n^%p^%e^%d^%E:%O:%R\n' |"); while (<$ppf>) { chomp; my ($name,$repo,$deps,$desc,$prepostread) = split /\^/; next if (! $printme{$name}); $path{$name} = $repo . "/" . $name; $depends{$name} = $deps; $desc =~ s/\:/ /g; $descrip{$name} = $desc; $flags{$name} = $prepostread; } close ($ppf); # Needed for alternating colors in the html index my %parity = ( 0 => "even", 1 => "odd" ); # Generate the metadata files ($#ARGV >= 0) ? pkg_single() : pkg_dir(); # Generate README and PKGINST pkgreadscripts(); ######################## individual packages ######################## sub pkg_single { my ($pname, $dbO, $oname, $pdeps, $desc, $du, $md5, $ppr); my $count = 0; my ($pver, $url, $date); # needed for the html index foreach my $db ("PKGREPO", "PKGDEPS", "index.html") { my $firstrun = 0; my $dbNew; my $status = "+ Generating "; if ($db eq "PKGREPO") { $status .= "repository\n"; } elsif ($db eq "PKGDEPS") { $status .= "dependencies\n"; } else { $status .= "html index\n"; } print $status; open (my $dbOld, "$db") or $firstrun=1; if ( ($firstrun == 1) and ($db eq "index.html") ) { printheader(); rename($db, "$db.new"); open ($dbNew, ">>$db.new"); } else { open ($dbNew, ">$db.new"); } PACKAGE: foreach my $p (sort @packages) { $count++ if ($db eq "index.html"); $pname = $p; $pver = $p; $pname =~ s/#.*//; $pver =~ s/.*#(.*)\.pkg\.tar\.*/$1/; if ($db eq "PKGREPO") { $du = (-s $p); $md5 = digest_file_hex($p,"MD5"); $desc = (! $descrip{$pname}) ? "N.A." : $descrip{$pname}; $ppr = (! $flags{$pname}) ? "no:no:no" : $flags{$pname}; printf $dbNew "%-s:%-s:%-s:%-s:%-s\n", $p, $du, $md5, $desc, $ppr if ($firstrun == 1); } elsif ($db eq "PKGDEPS") { $pdeps = (! $depends{$pname}) ? "" : $depends{$pname}; printf $dbNew "%-30s:%s\n", $pname, $pdeps if ($firstrun == 1); } else { $date = isotime( (stat($p))[9], 1); $url = $p; $url =~ s/\#/\%23/; htmlrow($dbNew,$parity{($count % 2)},$pname,$url,$pver, $descrip{$pname},$date) if ($firstrun == 1); } next PACKAGE if ($firstrun == 1); while ($dbO = <$dbOld>) { chomp($dbO); if (($db eq "index.html") and ($dbO !~ m/^) ) { if ($db eq "index.html") { $count++; $dbO =~ s/class="(even|odd)"/class="$parity{($count % 2)}"/; } print $dbNew $dbO; } close($dbNew); ($firstrun == 1) or close($dbOld); rename("$db.new", "$db"); printfooter($count) if (($firstrun == 1) and ($db eq "index.html")); } } ######################## full repository ######################## sub pkg_dir { print "+ Generating dependencies\n"; open (my $iD, ">PKGDEPS"); print "+ Generating repository\n"; open (my $iR, ">PKGREPO"); printheader(); my $count = 0; open (my $ih, '>>index.html'); foreach my $p (@packages) { chomp($p); my $date = isotime( (stat($p))[9], 1); $count++; my ($name, $version, $url) = ($p, $p, $p); $name =~ s/\#.*//; $version =~ s/^.*\#//; $version =~ s/\.pkg\.tar\.[gbx]z*//; $url =~ s/\#/\%23/; if (($depends{$name}) and ($depends{$name} ne "")) { printf $iD "%-30s : %-s\n", $name, $depends{$name}; } my $du = (-s $p); my $md5 = digest_file_hex($p,"MD5"); if (! $descrip{$name}) {$descrip{$name} = "N.A.";} if (! $flags{$name}) { $flags{$name} = "no:no:no"; } printf $iR "%-s:%-s:%-s:%-s:%-s\n", $p,$du,$md5,$descrip{$name},$flags{$name}; htmlrow($ih,$parity{($count % 2)},$name,$url, $version,$descrip{$name},$date); } close($ih); printfooter($count); close($iR); close($iD); } # consolidate all the README and install scripts for the available packages sub pkgreadscripts { print "+ Generating README\n"; open (my $fR, '>PKGREAD'); print $fR "# README files for repository. Do NOT remove this line.\n"; print "+ Generating scripts\n"; open (my $fS, '>PKGINST'); print $fS '#!/usr/bin/env bash # # PKGINST: pre- and post-install scripts for CRUX packages # run_script() { case "$1" in '; foreach my $name (sort @dirlist) { $name =~ s/\#.*//; if (-f "$path{$name}/README"){ print $fR "##### PKGREADME: $name\n"; open(my $readme, "$path{$name}/README"); while (<$readme>){ print $fR $_; } close($readme); } foreach my $when ("pre", "post") { if (-f "$path{$name}/${when}-install"){ print $fS " $name.$when)\n"; open(my $rs, "$path{$name}/${when}-install"); while (<$rs>){ chomp; print $fS " $_\n" unless (m/^\#(!.*sh|\s*EOF|\s*End)/); } close($rs); print $fS " ;;\n"; } } } print $fS " esac\n}\n\n"; print $fS '[ "$1" ] && [[ "$2" == @(pre|post) ]] && run_script "$1.$2"'; print $fS "\n"; close $fS; close $fR; } ######################## html index subs ######################## sub printheader { open (my $ih, '>index.html'); print $ih < EOH print $ih " $title\n"; print $ih < body { font-family: Verdana, sans-serif; font-size: 85%; padding: 2em; } a { color: #67550d; } table { border: solid #e5dccf 1px; font-size: 85%; } td { padding: 6px; } tr.header { background-color: #e5dccf; } tr.odd { background-color: #f7f3ed; } tr.even { background-color: #fcf9f8; } EOH print $ih "

$title

\n"; if ($header) { open(FILE, $header) or die "Couldn't open header file"; while () { print $ih " " . $_; } close(FILE); } print $ih " \n"; print $ih " "; print $ih ""; print $ih "\n"; close($ih); } sub htmlrow { my ($ih, $odd, $name, $url, $version, $desc, $date) = @_; print $ih ""; print $ih ""; print $ih "\n"; } sub printfooter { my $count = $_[0]; open (my $ih, '>>index.html'); print $ih "
PortVersionDescriptionLast modified
$name$version$desc$date
\n"; print $ih "

$count packages

\n"; if ($footer) { open(FILE, $footer) or die "Couldn't open footer file"; while () { print $ih " " . $_; } close(FILE); } print $ih "

Generated by pkg-repgen on " . isotime() . ".

\n"; print $ih < EOH close($ih); } sub isotime { my $time = (shift or time); my $accuracy = (shift or 2); my @t = gmtime ($time); my $year = $t[5] + 1900; my $month = sprintf("%02d", $t[4] + 1); my $day = sprintf("%02d", $t[3]); return "$year-$month-$day" if ($accuracy == 1); return "$year-$month-$day " . sprintf("%02d:%02d:%02d UTC", $t[2], $t[1], $t[0]); }