aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile2
-rwxr-xr-xsbofixinfo209
2 files changed, 210 insertions, 1 deletions
diff --git a/Makefile b/Makefile
index 9f43d27..515394a 100644
--- a/Makefile
+++ b/Makefile
@@ -14,7 +14,7 @@ MAN1DIR=$(MANDIR)/man1
DOCDIR=$(PREFIX)/doc/$(PROJ)-$(VERSION)
DOCS=README QUICKSTART TODO pre-commit-sbolint
-SCRIPTS=sbopkglint sbolint
+SCRIPTS=sbopkglint sbolint sbofixinfo
all:
@echo "Use 'make install PREFIX=<path>' to install $(PROJ)."
diff --git a/sbofixinfo b/sbofixinfo
new file mode 100755
index 0000000..2515989
--- /dev/null
+++ b/sbofixinfo
@@ -0,0 +1,209 @@
+#!/usr/bin/perl -w
+
+# reorder the keys in a SBo .info file.
+# assumes the file is otherwise valid.
+# companion piece to sbolint.
+
+$VERSION="0.1";
+
+# generate man page with:
+# pod2man --stderr -r0.1 -s1 -c"SBo Maintainer Tools" sbofixinfo > sbofixinfo.1
+
+=pod
+
+=head1 NAME
+
+sbofixinfo - fix common errors in a SlackBuilds.org .info file
+
+=head1 SYNOPSIS
+
+sbofixinfo [-b] infofile [infofile ...]
+
+=head1 DESCRIPTION
+
+B<sbofixinfo> attempts to fix the following errors in SBo .info files:
+
+=over 4
+
+=item -
+
+Out-of-order keys will be reordered to match order in the template.
+
+=item -
+
+Extraneous keys will be removed.
+
+=item -
+
+Blank lines will be removed.
+
+=item -
+
+Extra whitespace will be removed. This doesn't include indentation for
+the 2nd and further lines of a multi-line value.
+
+=item -
+
+Missing \ (backslash) continuation characters will be added.
+
+=item -
+
+Missing " (double-quote) characters around key values will be added.
+
+=item -
+
+Values quoted with single-quotes will be quoted with double-quotes.
+
+=item -
+
+Multi-valued keys (e.g. DOWNLOAD with two URLs) will be split up into
+multiple lines, if they're not already. Any missing line-continuation
+backslashes will be added.
+
+=back
+
+B<sbofixinfo> doesn't attempt to detect any other errors or dubious
+constructs. Use B<sbolint> before and after running B<sbofixinfo> for
+comprehensive checking.
+
+The file is modified 'in-place', in the same way as the B<-i> option
+to B<sed>(1).
+
+=head1 OPTIONS
+
+B<-b> causes B<sbofixinfo> to keep a backup of the original file with the
+extension I<.bak> appended to the filename. If the backup file already
+exists, it will be silently overwritten. After the new file is generated,
+B<diff>(1) (with its B<-u> option) is run on the backup and modified
+files, and the backup is deleted if the new file is identical. The diff
+output also goes to stdout, so the user can see what changes were made.
+
+=head1 EXIT STATUS
+
+Will be 0 for success. If any errors reading or writing any of the .info
+files occur, the exit status will be the error count.
+
+=head1 BUGS
+
+Misspelled key names (e.g. MD5USM or DOWNLAOD) will have their values
+discarded. Not a true bug (it's by design), but it violates the principle
+of least surprise a bit.
+
+B<sbofixinfo> can't automatically fix every issue B<sbolint> reports.
+In particular, missing or extra values (for valid keys) can't
+automatically be fixed. This isn't really a bug, as B<sbofixinfo>
+can't know what to do in these situations. In other words, B<sbofixinfo>
+operates only at the syntactic level, and knows nothing of semantics.
+
+=head1 AUTHOR
+
+B. Watson (yalhcru at slackware.uk, or Urchlay on Libera IRC)
+
+=head1 SEE ALSO
+
+B<sbolint>(1), B<sbopkglint>(1)
+
+=cut
+
+($SELF = $0) =~ s,.*/,,;
+
+@keyorder = qw/
+PRGNAM VERSION HOMEPAGE DOWNLOAD MD5SUM DOWNLOAD_x86_64 MD5SUM_x86_64 REQUIRES MAINTAINER EMAIL
+/;
+
+die "$SELF v$VERSION\nUsage: $SELF [--help] [-b] infofile <infofile ...>\n" unless @ARGV;
+
+if($ARGV[0] eq '--help') {
+ no warnings;
+ require FindBin;
+ system("perldoc $FindBin::RealScript");
+ exit 0;
+}
+
+if($ARGV[0] eq '-b') {
+ $backup = 1;
+ shift;
+}
+
+$errcnt = 0;
+fix_info($_) for @ARGV;
+exit $errcnt;
+
+sub fix_info {
+ my $file = shift;
+ open my $fh, "<$file" or do {
+ warn "$SELF: can't read $file: $!\n";
+ $errcnt++;
+ return;
+ };
+
+ my $key = 'INVALID_STUFF';
+ my %info;
+
+ # read through the whole file, extracting the values of all the
+ # keys, stash them in a hashtable. Multi-valued keys will be stored
+ # with carriage returns as a delimiter (they're otherwise not allowed).
+ # Quotes, backslashes, etc aren't stored (only the actual values).
+ while(<$fh>) {
+ chomp;
+ s/\r//g; # no DOS line endings
+ next if /^\s*$/; # ignore blank lines entirely
+
+ s/(?:^\s+|\s+$)//g; # remove leading/trailing spaces
+ s/^(\w+)\s+=\s+/$1=/; # remove spaces around =
+
+ if(/^(\w+)=(.*)$/) {
+ $key = $1;
+ $val = $2;
+ $val =~ s,(?:^['"]|['"]$),,g; # remove quotes around value
+ $val =~ s,[\s\\]*$,,; # remove any line-continuation backslash
+
+ # multiple valued keys all on the same line get split up into
+ # multi-line values. This only applies to download and md5sum
+ # URLs (which can't contain spaces anyway).
+ if($key =~ /^(?:DOWNLOAD|MD5SUM)/) {
+ $val =~ s/\s+/\r/g;
+ }
+
+ $info{$key} = $val;
+ } else {
+ s,[\s\\\"]*$,,;
+ $info{$key} .= "\r$_";
+ }
+ }
+ close $fh;
+
+ system("mv $file $file.bak") if $backup;
+
+ open $fh, ">$file" or do {
+ warn "$SELF: can't write $file: $!\n";
+ $errcnt++;
+ return;
+ };
+
+ # Reconstitute info file from the values, with correct indentation and
+ # quoting, backslashes, etc.
+ for $key (@keyorder) {
+ $info{$key} ||= ""; # avoid unitialized value on missing key
+ my @values = split /\r/, $info{$key};
+ if(@values == 0) {
+ print $fh "$key=\"\"\n";
+ } elsif(@values == 1) {
+ print $fh "$key=\"$values[0]\"\n";
+ } else {
+ my $indent = " " x (length($key) + 2);
+ my $first = shift @values;
+ my $last = pop @values;
+ print $fh "$key=\"$first \\\n";
+ print $fh "$indent$_ \\\n" for @values;
+ print $fh "$indent$last\"\n";
+ }
+ }
+
+ if($backup) {
+ my $result = system("diff $file.bak $file");
+ if($result == 0) {
+ system("rm $file.bak");
+ }
+ }
+}