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 | ||||
-rw-r--r-- | scripts/repo-add.sh.in | 12 |
6 files changed, 277 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 02f5a02d..2a391575 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 diff --git a/scripts/repo-add.sh.in b/scripts/repo-add.sh.in index 4470dd0a..a9a4499b 100644 --- a/scripts/repo-add.sh.in +++ b/scripts/repo-add.sh.in @@ -31,6 +31,7 @@ declare -r confdir='@sysconfdir@' QUIET=0 DELTA=0 ONLYADDNEW=0 +RMEXISTING=0 WITHFILES=0 SIGN=0 VERIFY=0 @@ -58,6 +59,7 @@ Multiple packages to add can be specified on the command line.\n")" printf -- "$(gettext "Options:\n")" printf -- "$(gettext " -d, --delta generate and add delta for package update\n")" printf -- "$(gettext " -n, --new only add packages that are not already in the database\n")" + printf -- "$(gettext " -R, --remove remove package file from disk when updating database entry\n")" printf -- "$(gettext " -f, --files update database's file list\n")" elif [[ $cmd == "repo-remove" ]] ; then printf -- "$(gettext "Usage: repo-remove [options] <path-to-db> <packagename|delta> ...\n")" @@ -304,6 +306,15 @@ db_write_entry() { local oldfilename=$(grep -A1 FILENAME "$pkgentry/desc" | tail -n1) local oldfile="$(dirname "$1")/$oldfilename" fi + elif (( RMEXISTING )); then + # only remove existing package if we're not doing deltas + pkgentry=$(find_pkgentry "$pkgname") + if [[ -n $pkgentry ]]; then + local oldfilename="$(sed -n '/^%FILENAME%$/ {n;p;q;}' "$pkgentry/desc")" + local oldfile="$(dirname "$1")/$oldfilename" + msg2 "$(gettext "Removing existing package '%s'")" "$oldfilename" + rm -f ${oldfile} ${oldfile}.sig + fi fi fi @@ -611,6 +622,7 @@ while (( $# )); do -q|--quiet) QUIET=1;; -d|--delta) DELTA=1;; -n|--new) ONLYADDNEW=1;; + -R|--remove) RMEXISTING=1;; -f|--files) WITHFILES=1;; --nocolor) USE_COLOR='n';; -s|--sign) |