diff options
-rwxr-xr-x | update_sbtext.pl | 215 |
1 files changed, 215 insertions, 0 deletions
diff --git a/update_sbtext.pl b/update_sbtext.pl new file mode 100755 index 0000000..952d0c3 --- /dev/null +++ b/update_sbtext.pl @@ -0,0 +1,215 @@ +#!/usr/bin/perl -w + +##### +# update_sbtext.pl +##### + +##### +# Written by B. Watson (urchlay@slackware.uk) on 20240806. If you +# modify this file, please include the date, a description of the +# changes, and your name, below. +##### + +##### +# Revision history: +# 20240806, initial version, B. Watson. +##### + +##### +# Description: + +# Replacement for update_sbtext.sh. Does the same job but runs a good +# bit faster. + +# Differences between update_sbtext.sh and update_sbtext.pl: + +# 1. update_sbtext.pl is written in Perl (yeah, call me Captain Obvious). + +# 2. update_sbtext.pl is approximaly 60 times as fast. With ~9400 builds +# in the repo, the shell version ran in 15 minutes, and this one +# runs in 15 *seconds*. + +# 3. The output isn't *quite* identical to the .sh version: I made +# the short description more consistent (always one space after +# the colon; remove the duplicate package names caused by a bug in +# the old script that manifested whenever the package name has a + +# in it). + +# 4. This script writes to SLACKBUILDS.TXT.new, and doesn't disturb +# the existing SLACKBUILDS.TXT or SLACKBUILDS.TXT.gz until it's +# done (then it overwrites the old files in one swell foop, so no +# users ever see partial results). + +# 5. If there are symlinks in the repo, they will show up in the +# SLACKBUILD FILE LIST for the build they belong to. With the shell +# version, they are ignored. This actually only affects one build +# (desktop/mint-y-icons), and it's not clear to me that symlinks +# should be allowed in the git repo anyway. + +# I know most of my fellow SBo admins aren't real big on Perl, so I +# commented the hell out of this. If it still doesn't make sense, find +# me on IRC or by email and I'll try to make it make sense. +##### + +##### +# These 2 variables are configurable settings, if you can think of a +# reason to change them. +##### +$slackbuilds_top_dir = "/slackbuilds/www/slackbuilds"; +$output = "SLACKBUILDS.TXT"; + +##### +# Use only modules that ship with Slackware's perl package here! +use File::Find; +##### + +#### +# Rest of the file is hopefully bug-free code (hey, I can hope, right?) +#### + +# File::Find "wanted" predicate. When find() calls this, it sets +# $_ to the filename (the basename only) and $File::Find::dir +# to the directory (relative to find()'s 2nd argument). See +# "perldoc File::Find" if you need more information. +sub found_file { + # don't process directories at all. + return if -d $_; + + # $dot is always "." + # $cat is the category (audio, development, etc). + # $prgnam is (guess what?) the build name. + # @path is the rest. for e.g. slack-desc, it'll be just the name. + # if there's a subdirectory, it'll be dir/filename. + my ($dot, $cat, $prgnam, @path) = split /\//, $File::Find::dir; + + # if there aren't at least 2 dir components, ignore. + return unless defined $cat; + return unless defined $prgnam; + + # %files hash key. + $dir = "$dot/$cat/$prgnam"; + + # %files values are array references, holding the subdirs under the + # SlackBuild dir, if any, and the basename. + push @{$files{$dir}}, join("/", @path, $_); + + return unless /(.*)\.info$/; + + # if we found an .info file, add it to the list. + push @infos, "$dir/$_"; +} + +# Join together lines in .info files that are split by +# backslashes. This is actually more forgiving of spacing errors +# than it needs to be (better not to be so picky). +sub fix_backslashes { + for($_[0]) { + s, + \s* # optional spaces + \\ # required: single backslash + \s* # optional spaces + \n # required: newline + \s* # optional spaces + , ,gx; # all the above gets replaced with a single space. + return $_; + } +} + +# Read an entire file, join any lines back together if they're split +# with a backslash, return entire file contents as a scalar. +sub slurp_file { + my $file = shift; + + local $/ = undef; + open my $fh, '<', $file || die $!; + my $content = <$fh>; + close $fh; + + return fix_backslashes($content); +} + +# Return just the value from the .info file contents, given the key. +# Assumes the content's already had fix_backslashes() called on it. +sub get_info_value { + my $file = shift; # only needed for error message + my $info = shift; + my $key = shift; + + $$info =~ m,^$key="(.*?)",m or die "no match for $key in $file\n"; + return $1; +} + +# get the first non-comment line of the slack-desc in $dir, remove +# the 'buildname: ' prefix, return the rest. +sub get_short_desc { + my $buildname = quotemeta shift; + my $dir = shift; + my $file = $dir . "/slack-desc"; + + open my $fh, '<', $file || die "$file: $!\n"; + my $line; + while(<$fh>) { + chomp; + last if /^$buildname: /; + } + close $fh; + + die "$file: can't figure out short description\n" unless defined $_; + + s,^\S+:\s*,,; + return $_; +} + +# parse_info() actually prints the 'entry' in SLACKBUILDS.TXT for a +# given info file. Argument must be the path to the file, like +# ./category/progname/progname.info +sub parse_info { + my $file = shift; + my $loc; + my $name; + + ($loc, $name) = ($file =~ m,(^.*)/([^/]+)\.info$,); + + print "SLACKBUILD NAME: $name\n"; + print "SLACKBUILD LOCATION: $loc\n"; + print "SLACKBUILD FILES: " . join(" ", sort @{$files{$loc}}) . "\n"; + + my $content = slurp_file($file); + + for (qw/VERSION DOWNLOAD DOWNLOAD_x86_64 MD5SUM MD5SUM_x86_64 REQUIRES/) { + print "SLACKBUILD $_: " . get_info_value($file, \$content, $_) . "\n"; + } + + # N.B. update_sbtext.sh always puts 2 spaces after the : here, unless + # the script name has a + in it (e.g. wmweather+, atari++), in which + # case it puts one space, and duplicates the package name. I consider + # this a bug in the original script; here, there's always one space + # and no dup package names. + print "SLACKBUILD SHORT DESCRIPTION: " . get_short_desc($name, $loc); + + print "\n\n"; +} + +# main() +$subdir = shift || die "Usage: $0 <version>\n"; + +chdir $slackbuilds_top_dir . "/" . $subdir || die $!; + +open $outfh, '>', "$output.new" || die $!; +*STDOUT = $outfh; + +# slight difference: .sh version printed this string to stdout, not +# stderr. I don't think anyone cares. +warn "$0: Updating SLACKBUILDS.TXT...\n"; + +# builds the %files and @infos tables. +find(\&found_file, '.'); + +# generate the entries, in sorted order. +parse_info($_) for sort @infos; + +close $outfh; + +# don't overwrite SLACKBUILDS.TXT (and .TXT.gz) until the end. +rename "$output.new", $output; +system("gzip -9c $output > $output.gz"); |