diff options
Diffstat (limited to 'scripts')
| -rw-r--r-- | scripts/.gitignore | 1 | ||||
| -rw-r--r-- | scripts/Makefile.am | 11 | ||||
| -rwxr-xr-x | scripts/makepkg-template.pl.in | 212 | ||||
| -rw-r--r-- | scripts/makepkg.sh.in | 95 | ||||
| -rw-r--r-- | scripts/po/POTFILES.in | 1 | 
5 files changed, 265 insertions, 55 deletions
| diff --git a/scripts/.gitignore b/scripts/.gitignore index 9e403bfb..26e088b9 100644 --- a/scripts/.gitignore +++ b/scripts/.gitignore @@ -1,4 +1,5 @@  makepkg +makepkg-template  pacman-db-upgrade  pacman-key  pacman-optimize diff --git a/scripts/Makefile.am b/scripts/Makefile.am index 784b1802..1f3bae24 100644 --- a/scripts/Makefile.am +++ b/scripts/Makefile.am @@ -5,6 +5,7 @@ SUBDIRS = po  bin_SCRIPTS = \  	$(OURSCRIPTS) \ +	makepkg-template \  	repo-remove \  	repo-elephant @@ -18,6 +19,7 @@ OURSCRIPTS = \  EXTRA_DIST = \  	makepkg.sh.in \ +	makepkg-template.pl.in \  	pacman-db-upgrade.sh.in \  	pacman-key.sh.in \  	pacman-optimize.sh.in \ @@ -54,6 +56,7 @@ edit = sed \  	-e 's|@PACKAGE_BUGREPORT[@]|$(PACKAGE_BUGREPORT)|g' \  	-e 's|@PACKAGE_NAME[@]|$(PACKAGE_NAME)|g' \  	-e 's|@BUILDSCRIPT[@]|$(BUILDSCRIPT)|g' \ +	-e 's|@TEMPLATE_DIR[@]|$(TEMPLATE_DIR)|g' \  	-e 's|@DEBUGSUFFIX[@]|$(DEBUGSUFFIX)|g' \  	-e "s|@INODECMD[@]|$(INODECMD)|g" \  	-e 's|@SIZECMD[@]|$(SIZECMD)|g' \ @@ -76,6 +79,14 @@ makepkg: \  	$(srcdir)/makepkg.sh.in \  	$(srcdir)/library/parseopts.sh +makepkg-template: \ +	$(srcdir)/makepkg-template.pl.in \ +	Makefile + +	$(AM_V_at)$(RM) -f makepkg-template +	$(AM_V_GEN)$(edit) $< > $@ +	$(AM_V_at)chmod +x,a-w $@ +  pacman-db-upgrade: \  	$(srcdir)/pacman-db-upgrade.sh.in \  	$(srcdir)/library/output_format.sh diff --git a/scripts/makepkg-template.pl.in b/scripts/makepkg-template.pl.in new file mode 100755 index 00000000..567514e1 --- /dev/null +++ b/scripts/makepkg-template.pl.in @@ -0,0 +1,212 @@ +#!/usr/bin/perl +#   makepkg-template - template system for makepkg +#   @configure_input@ +# +#   Copyright (c) 2013 Pacman Development Team <pacman-dev@archlinux.org> +# +#   This program is free software; you can redistribute it and/or modify +#   it under the terms of the GNU General Public License as published by +#   the Free Software Foundation; either version 2 of the License, or +#   (at your option) any later version. +# +#   This program is distributed in the hope that it will be useful, +#   but WITHOUT ANY WARRANTY; without even the implied warranty of +#   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the +#   GNU General Public License for more details. +# +#   You should have received a copy of the GNU General Public License +#   along with this program.  If not, see <http://www.gnu.org/licenses/>. +# +use warnings; +use strict; +use v5.10.1; +use Cwd qw(abs_path); +use Getopt::Long; +use Module::Load; +use Module::Load::Conditional qw(can_load); + +my %opts = ( +	input => '@BUILDSCRIPT@', +	template_dir => '@TEMPLATE_DIR@', +); + +my $template_name_charset = qr/[[:alnum:]+_.@-]/; +my $template_marker = qr/# template/; + +# runtime loading to avoid dependency on cpan since this is the only non-core module +my $loaded_gettext = can_load(modules => {'Locale::gettext' => undef}); +if ($loaded_gettext) { +	Locale::gettext::bindtextdomain("pacman-scripts", '@localedir@'); +	Locale::gettext::textdomain("pacman-scripts"); +} + +sub gettext { +	my ($string) = @_; + +	if ($loaded_gettext) { +		return Locale::gettext::gettext($string); +	} else { +		return $string; +	} +} + +sub burp { +	my ($file_name, @lines) = @_; +	open (my $fh, ">", $file_name) || die sprintf(gettext("can't create '%s': %s"), $file_name, $!); +	print $fh @lines; +	close $fh; +} + +# read a template marker line and parse values into a hash +# format is "# template (start|input); key=value; key2=value2; ..." +sub parse_template_line { +	my ($line, $filename, $linenumber) = @_; +	my %values; + +	my ($marker, @elements) = split(/;\s?/, $line); + +	($values{command}) = ($marker =~ /$template_marker (.*)/); + +	foreach my $element (@elements) { +		my ($key, $val) = ($element =~ /^([a-z0-9]+)=(.*)$/); +		unless ($key and $val) { +			die gettext("invalid key/value pair\n%s:%s: %s"), +				"$filename:$linenumber: $line"; +		} +		$values{$key} = $val; +	} + +	# end doesn't take arguments +	if ($values{command} ne "end") { +		if (!$values{name}) { +			die gettext("invalid template line: can't find template name\n"), +				"$filename:$linenumber: $line"; +		} + +		unless ($values{name} =~ /^$template_name_charset+$/) { +			die sprintf(gettext("invalid chars used in name '%s'. allowed: [:alnum:]+_.\@-\n"), $values{name}), +				"$filename:$linenumber: $line"; +		} +	} + +	return \%values; +} + +# load a template, process possibly existing markers (nested templates) +sub load_template { +	my ($values) = @_; + +	my $ret = ""; + +	my $path; +	if (!$opts{newest} and $values->{version}) { +		$path = "$opts{template_dir}/$values->{name}-$values->{version}.template"; +	} else { +		$path = "$opts{template_dir}/$values->{name}.template"; +	} + +	# resolve symlink(s) and use the real file's name for version detection +	my ($version) = (abs_path($path) =~ /-([0-9.]+)[.]template$/); + +	if (!$version) { +		die sprintf(gettext("Couldn't detect version for template '%s'"), $values->{name}); +	} + +	my $parsed = process_file($path); + +	$ret .= "# template start; name=$values->{name}; version=$version;\n"; +	$ret .= $parsed; +	$ret .= "# template end;\n"; +	return $ret; +} + +# process input file and load templates for all markers found +sub process_file { +	my ($filename) = @_; + +	my $ret = ""; +	my $nesting_level = 0; +	my $linenumber = 0; + +	open (my $fh, "<", $filename) or die sprintf(gettext("failed to open '%s': %s"), $filename, $!); +	my @lines = <$fh>; +	close $fh; + +	foreach my $line (@lines) { +		$linenumber++; + +		if ($line =~ $template_marker) { +			my $values = parse_template_line($line, $filename, $linenumber); + +			if ($values->{command} eq "start" or $values->{command} eq "input") { +				if ($nesting_level == 0) { +					$ret .= load_template($values); +				} +			} elsif ($values->{command} eq "end") { +				# nothing to do here, just for completeness +			} else { +				die sprintf(gettext("Unknown template marker '%s'\n"), $values->{command}), +					"$filename:$linenumber: $line"; +			} + +			$nesting_level++ if $values->{command} eq "start"; +			$nesting_level-- if $values->{command} eq "end"; + +			# marker lines should never be added +			next; +		} + +		# we replace code inside blocks with the template +		# so we ignore the content of the block +		next if $nesting_level > 0; + +		$ret .= $line; +	} +	return $ret; +} + +sub usage { +	my ($exitstatus) = @_; +	print  gettext("makepkg-template [options]\n"); +	print "\n"; +	print  gettext("Options:\n"); +	printf(gettext("  --input, -p <file>    Build script to read (default: %s)\n"), '@BUILDSCRIPT@'); +	print  gettext("  --output, -o <file>   file to output to (default: input file)\n"); +	print  gettext("  --newest, -n          update templates to newest version\n"); +	print  gettext("                        (default: use version specified in the template markers)\n"); +	print  gettext("  --template-dir <dir>  directory to search for templates\n"); +	printf(gettext("                        (default: %s)\n"), '@TEMPLATE_DIR@'); +	print  gettext("  --help, -h            This help message\n"); +	print  gettext("  --version             Version information\n"); +	print "\n"; +	exit($exitstatus); +} + +sub version { +	my ($exitstatus) = @_; +	printf "makepkg-template (pacman) %s\n", '@PACKAGE_VERSION@'; +	print  gettext( +		'Copyright (c) 2013 Pacman Development Team <pacman-dev@archlinux.org>.'."\n". +		'This is free software; see the source for copying conditions.'."\n". +		'There is NO WARRANTY, to the extent permitted by law.'."\n"); +	exit($exitstatus); +} + +Getopt::Long::Configure ("bundling"); +GetOptions( +	"help|h" => sub {usage(0); }, +	"version" => sub {version(0); }, +	"input|p=s" => \$opts{input}, +	"output|o=s" => \$opts{output}, +	"newest|n" => \$opts{newest}, +	"template-dir=s" => \$opts{template_dir}, +) or usage(1); + +$opts{output} = $opts{input} unless $opts{output}; + +$opts{input} = "/dev/stdin" if $opts{input} eq "-"; +$opts{output} = "/dev/stdout" if $opts{output} eq "-"; + +burp($opts{output}, process_file($opts{input})); + +# vim: set noet: diff --git a/scripts/makepkg.sh.in b/scripts/makepkg.sh.in index a8a552ff..528db14d 100644 --- a/scripts/makepkg.sh.in +++ b/scripts/makepkg.sh.in @@ -2095,6 +2095,10 @@ install_package() {  	fi  } +have_function() { +	declare -f "$1" >/dev/null +} +  check_sanity() {  	# check for no-no's in the build script  	local i @@ -2240,9 +2244,14 @@ check_sanity() {  		ret=1  	fi -	if (( ${#pkgname[@]} > 1 )); then +	if (( ${#pkgname[@]} == 1 )); then +		if have_function build && ! ( have_function package || have_function package_${pkgname}); then +			error "$(gettext "Missing %s function in %s")" "package()" "$BUILDFILE" +			ret=1 +		fi +	else  		for i in ${pkgname[@]}; do -			if ! declare -f package_${i} >/dev/null; then +			if ! have_function package_${i}; then  				error "$(gettext "Missing %s function for split package '%s'")" "package_$i()" "$i"  				ret=1  			fi @@ -2510,6 +2519,7 @@ usage() {  	printf -- "$(gettext "  --holdver        Do not update VCS sources")\n"  	printf -- "$(gettext "  --key <key>      Specify a key to use for %s signing instead of the default")\n" "gpg"  	printf -- "$(gettext "  --nocheck        Do not run the %s function in the %s")\n" "check()" "$BUILDSCRIPT" +	printf -- "$(gettext "  --noprepare      Do not run the %s function in the %s")\n" "prepare()" "$BUILDSCRIPT"  	printf -- "$(gettext "  --nosign         Do not create a signature for the package")\n"  	printf -- "$(gettext "  --pkg <list>     Only build listed packages from a split package")\n"  	printf -- "$(gettext "  --sign           Sign the resulting package with %s")\n" "gpg" @@ -2552,7 +2562,7 @@ ARGLIST=("$@")  OPT_SHORT="AcdefFghiLmop:rRsSV"  OPT_LONG=('allsource' 'asroot' 'check' 'clean' 'config:' 'force' 'geninteg'            'help' 'holdver' 'ignorearch' 'install' 'key:' 'log' 'nobuild' 'nocolor' -          'nocheck' 'nodeps' 'noextract' 'nosign' 'pkg:' 'repackage' 'rmdeps' +          'nocheck' 'nodeps' 'noextract' 'noprepare' 'nosign' 'pkg:' 'repackage' 'rmdeps'            'sign' 'skipchecksums' 'skipinteg' 'skippgpcheck' 'source' 'syncdeps'            'verifysource' 'version') @@ -2591,6 +2601,7 @@ while true; do  		-L|--log)         LOGGING=1 ;;  		-m|--nocolor)     USE_COLOR='n' ;;  		--nocheck)        RUN_CHECK='n' ;; +		--noprepare)      RUN_PREPARE='n' ;;  		--nosign)         SIGNPKG='n' ;;  		-o|--nobuild)     NOBUILD=1 ;;  		-p)               shift; BUILDFILE=$1 ;; @@ -2631,6 +2642,7 @@ trap 'trap_exit USR1 "$(gettext "An unknown error has occurred. Exiting...")"' E  [[ -n ${SRCEXT} ]] && _SRCEXT=${SRCEXT}  [[ -n ${GPGKEY} ]] && _GPGKEY=${GPGKEY}  [[ -n ${PACKAGER} ]] && _PACKAGER=${PACKAGER} +[[ -n ${CARCH} ]] && _CARCH=${CARCH}  # default config is makepkg.conf  MAKEPKG_CONF=${MAKEPKG_CONF:-$confdir/makepkg.conf} @@ -2667,12 +2679,12 @@ if [[ -t 2 && ! $USE_COLOR = "n" ]] && check_buildenv "color" "y"; then  		RED="${BOLD}$(tput setaf 1)"  		YELLOW="${BOLD}$(tput setaf 3)"  	else -		ALL_OFF="\e[1;0m" -		BOLD="\e[1;1m" -		BLUE="${BOLD}\e[1;34m" -		GREEN="${BOLD}\e[1;32m" -		RED="${BOLD}\e[1;31m" -		YELLOW="${BOLD}\e[1;33m" +		ALL_OFF="\e[0m" +		BOLD="\e[1m" +		BLUE="${BOLD}\e[34m" +		GREEN="${BOLD}\e[32m" +		RED="${BOLD}\e[31m" +		YELLOW="${BOLD}\e[33m"  	fi  fi  readonly ALL_OFF BOLD BLUE GREEN RED YELLOW @@ -2730,6 +2742,7 @@ PKGEXT=${_PKGEXT:-$PKGEXT}  SRCEXT=${_SRCEXT:-$SRCEXT}  GPGKEY=${_GPGKEY:-$GPGKEY}  PACKAGER=${_PACKAGER:-$PACKAGER} +CARCH=${_CARCH:-$CARCH}  if (( ! INFAKEROOT )); then  	if (( EUID == 0 && ! ASROOT )); then @@ -2762,17 +2775,10 @@ unset makedepends optdepends options noextract  BUILDFILE=${BUILDFILE:-$BUILDSCRIPT}  if [[ ! -f $BUILDFILE ]]; then -	if [[ -t 0 ]]; then -		error "$(gettext "%s does not exist.")" "$BUILDFILE" -		exit 1 -	else -		# PKGBUILD passed through a pipe -		BUILDFILE=/dev/stdin -		source_safe "$BUILDFILE" -	fi +	error "$(gettext "%s does not exist.")" "$BUILDFILE" +	exit 1  else -	crlftest=$(file "$BUILDFILE" | grep -F 'CRLF' || true) -	if [[ -n $crlftest ]]; then +	if [[ $(<"$BUILDFILE") = *$'\r'* ]]; then  		error "$(gettext "%s contains %s characters and cannot be sourced.")" "$BUILDFILE" "CRLF"  		exit 1  	fi @@ -2808,7 +2814,7 @@ if (( GENINTEG )); then  	exit 0 # $E_OK  fi -if declare -f pkgver >/dev/null; then +if have_function pkgver; then  	PKGVERFUNC=1  fi @@ -2823,21 +2829,24 @@ if (( ${#pkgname[@]} > 1 )); then  fi  # test for available PKGBUILD functions -if declare -f prepare >/dev/null; then -	PREPAREFUNC=1 +if have_function prepare; then +	# "Hide" prepare() function if not going to be run +	if [[ $RUN_PREPARE != "n" ]]; then +		PREPAREFUNC=1 +	fi  fi -if declare -f build >/dev/null; then +if have_function build; then  	BUILDFUNC=1  fi -if declare -f check >/dev/null; then +if have_function check; then  	# "Hide" check() function if not going to be run  	if [[ $RUN_CHECK = 'y' ]] || { ! check_buildenv "check" "n" && [[ $RUN_CHECK != "n" ]]; }; then  		CHECKFUNC=1  	fi  fi -if declare -f package >/dev/null; then +if have_function package; then  	PKGFUNC=1 -elif [[ $SPLITPKG -eq 0 ]] && declare -f package_${pkgname} >/dev/null; then +elif [[ $SPLITPKG -eq 0 ]] && have_function package_${pkgname}; then  	SPLITPKG=1  fi @@ -2875,17 +2884,7 @@ if (( INFAKEROOT )); then  	if (( ! SPLITPKG )); then  		pkgdir="$pkgdirbase/$pkgname"  		mkdir "$pkgdir" -		if (( ! PKGFUNC )); then -			if (( ! REPKG )); then -				if (( BUILDFUNC )); then -					run_build -					(( CHECKFUNC )) && run_check -				fi -			else -				warning "$(gettext "Repackaging without the use of a %s function is deprecated.")" "package()" -				plain "$(gettext "File permissions may not be preserved.")" -			fi -		else +		if (( PKGFUNC )); then  			run_package  		fi  		tidy_install @@ -2902,10 +2901,6 @@ fi  fullver=$(get_full_version)  msg "$(gettext "Making package: %s")" "$pkgbase $fullver ($(date))" -if (( !PKGFUNC && !SPLITPKG )); then -	warning "$(gettext "Using a %s without a %s function is deprecated.")" "$BUILDSCRIPT" "package()" -fi -  # if we are creating a source-only package, go no further  if (( SOURCEONLY )); then  	if [[ -f $SRCPKGDEST/${pkgbase}-${fullver}${SRCEXT} ]] \ @@ -2983,14 +2978,7 @@ cd_safe "$srcdir"  if (( NOEXTRACT && ! VERIFYSOURCE )); then  	warning "$(gettext "Using existing %s tree")" "src/" -elif (( REPKG )); then -	if (( ! PKGFUNC && ! SPLITPKG )) \ -	     && { [[ ! -d $pkgdirbase ]] || dir_is_empty "$pkgdirbase"; }; then -		error "$(gettext "The package directory is empty, there is nothing to repackage!")" -		plain "$(gettext "Aborting...")" -		exit 1 -	fi -else +elif (( !REPKG )); then  	download_sources  	check_source_integrity  	(( VERIFYSOURCE )) && exit 0 # $E_OK @@ -3004,8 +2992,8 @@ if (( NOBUILD )); then  	msg "$(gettext "Sources are ready.")"  	exit 0 #E_OK  else -	# check for existing pkg directory; don't remove if we are repackaging -	if [[ -d $pkgdirbase ]] && (( ! REPKG || PKGFUNC || SPLITPKG )); then +	# clean existing pkg directory +	if [[ -d $pkgdirbase ]]; then  		msg "$(gettext "Removing existing %s directory...")" "pkg/"  		rm -rf "$pkgdirbase"  	fi @@ -3029,9 +3017,6 @@ else  			mkdir -p "$pkgdir"  			if (( PKGFUNC )); then  				run_package -			elif (( REPKG )); then -					warning "$(gettext "Repackaging without the use of a %s function is deprecated.")" "package()" -					plain "$(gettext "File permissions may not be preserved.")"  			fi  			tidy_install  			create_package @@ -3040,7 +3025,7 @@ else  			run_split_packaging  		fi  	else -		if (( ! REPKG && ( PKGFUNC || SPLITPKG ) )); then +		if (( ! REPKG )); then  			(( BUILDFUNC )) && run_build  			(( CHECKFUNC )) && run_check  			cd_safe "$startdir" diff --git a/scripts/po/POTFILES.in b/scripts/po/POTFILES.in index 162731b9..f9e8a481 100644 --- a/scripts/po/POTFILES.in +++ b/scripts/po/POTFILES.in @@ -2,6 +2,7 @@  # scripts with gettext translations  scripts/makepkg.sh.in +scripts/makepkg-template.pl.in  scripts/pacman-db-upgrade.sh.in  scripts/pacman-key.sh.in  scripts/pacman-optimize.sh.in | 
