diff options
| -rw-r--r-- | Makefile | 2 | ||||
| -rwxr-xr-x | sbofixinfo | 209 | 
2 files changed, 210 insertions, 1 deletions
| @@ -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"); +		} +	} +} | 
