From 71b21caafd97dcf5ca40c6f05dbcb64d868e145b Mon Sep 17 00:00:00 2001 From: Pekka Helenius Date: Sun, 15 Aug 2021 03:01:38 +0300 Subject: [PATCH] Add pacman/makepkg modifications --- pacman/usr/local/bin/makepkg | 1971 ++++++++++++++++++++++++ pacman/usr/local/bin/pacman | 7 + pacman/usr/local/bin/pacmankeycheck.sh | 64 + pacman/usr/share/makepkg/source.sh | 113 ++ pacman/usr/share/makepkg/source/git.sh | 138 ++ 5 files changed, 2293 insertions(+) create mode 100755 pacman/usr/local/bin/makepkg create mode 100755 pacman/usr/local/bin/pacman create mode 100644 pacman/usr/local/bin/pacmankeycheck.sh create mode 100755 pacman/usr/share/makepkg/source.sh create mode 100755 pacman/usr/share/makepkg/source/git.sh diff --git a/pacman/usr/local/bin/makepkg b/pacman/usr/local/bin/makepkg new file mode 100755 index 0000000..5afde97 --- /dev/null +++ b/pacman/usr/local/bin/makepkg @@ -0,0 +1,1971 @@ +#!/usr/bin/bash +# +# makepkg - make packages compatible for use with pacman +# Generated from makepkg.sh.in; do not edit by hand. +# +# Copyright (c) 2021 by Pekka Helenius +# Copyright (c) 2006-2018 Pacman Development Team +# Copyright (c) 2002-2006 by Judd Vinet +# Copyright (c) 2005 by Aurelien Foret +# Copyright (c) 2006 by Miklos Vajna +# Copyright (c) 2005 by Christian Hamar +# Copyright (c) 2006 by Alex Smith +# Copyright (c) 2006 by Andras Voroskoi +# +# 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 . +# + +# makepkg uses quite a few external programs during its execution. You +# need to have at least the following installed for makepkg to function: +# awk, bsdtar (libarchive), bzip2, coreutils, fakeroot, file, find (findutils), +# gettext, gpg, grep, gzip, sed, tput (ncurses), xz + +# gettext initialization +export TEXTDOMAIN='pacman-scripts' +export TEXTDOMAINDIR='/usr/share/locale' + +# file -i does not work on Mac OSX unless legacy mode is set +export COMMAND_MODE='legacy' +# Ensure CDPATH doesn't screw with our cd calls +unset CDPATH +# Ensure GREP_OPTIONS doesn't screw with our grep calls +unset GREP_OPTIONS + +declare -r makepkg_version='5.1.3' +declare -r confdir='/etc' +declare -r BUILDSCRIPT='PKGBUILD' +declare -r startdir="$(pwd -P)" + +LIBRARY=${LIBRARY:-'/usr/share/makepkg'} + +build_options=('ccache' 'distcc' 'buildflags' 'makeflags') +splitpkg_overrides=('pkgdesc' 'arch' 'url' 'license' 'groups' 'depends' + 'optdepends' 'provides' 'conflicts' 'replaces' 'backup' + 'options' 'install' 'changelog') +readonly -a build_options splitpkg_overrides + +known_hash_algos=('md5' 'sha1' 'sha224' 'sha256' 'sha384' 'sha512' 'whirlpool') + +# Options +ASDEPS=0 +BUILDFUNC=0 +CHECKFUNC=0 +CLEANBUILD=0 +CLEANUP=0 +RMBUILDDEPS=0 +DEP_BIN=0 +FORCE=0 +GENINTEG=0 +HOLDVER=0 +IGNOREARCH=0 +INFAKEROOT=0 +INSTALL=0 +LOGGING=0 +NEEDED=0 +NOARCHIVE=0 +NOBUILD=0 +NODEPS=0 +NOEXTRACT=0 +PKGFUNC=0 +PKGVERFUNC=0 +PREPAREFUNC=0 +REPKG=0 +REPRODUCIBLE=0 +RMDEPS=0 +SKIPCHECKSUMS=0 +SKIPPGPCHECK=0 +SIGNPKG='' +SPLITPKG=0 +SOURCEONLY=0 +UPDPKGSUMS=0 +VERIFYSOURCE=0 + +if [[ -n $SOURCE_DATE_EPOCH ]]; then + REPRODUCIBLE=1 +else + SOURCE_DATE_EPOCH=$(date +%s) +fi +export SOURCE_DATE_EPOCH + +PACMAN_OPTS=() + +shopt -s extglob + +### SUBROUTINES ### + +# Import libmakepkg +for lib in "$LIBRARY"/*.sh; do + source "$lib" +done + +## +# Special exit call for traps, Don't print any error messages when inside, +# the fakeroot call, the error message will be printed by the main call. +## +trap_exit() { + local signal=$1; shift + + if (( ! INFAKEROOT )); then + echo + error "$@" + fi + [[ -n $srclinks ]] && rm -rf "$srclinks" + + # unset the trap for this signal, and then call the default handler + trap -- "$signal" + kill "-$signal" "$$" +} + + +## +# Clean up function. Called automatically when the script exits. +## +clean_up() { + local EXIT_CODE=$? + + if (( INFAKEROOT )); then + # Don't clean up when leaving fakeroot, we're not done yet. + return 0 + fi + + if (( (EXIT_CODE == E_OK || EXIT_CODE == E_INSTALL_FAILED) && CLEANUP )); then + local pkg file + + # If it's a clean exit and -c/--clean has been passed... + msg "$(gettext "Cleaning up...")" + rm -rf "$pkgdirbase" "$srcdir" + if [[ -n $pkgbase ]]; then + local fullver=$(get_full_version) + # Can't do this unless the BUILDSCRIPT has been sourced. + if (( PKGVERFUNC )); then + rm -f "${pkgbase}-${fullver}-${CARCH}-pkgver.log"* + fi + if (( PREPAREFUNC )); then + rm -f "${pkgbase}-${fullver}-${CARCH}-prepare.log"* + fi + if (( BUILDFUNC )); then + rm -f "${pkgbase}-${fullver}-${CARCH}-build.log"* + fi + if (( CHECKFUNC )); then + rm -f "${pkgbase}-${fullver}-${CARCH}-check.log"* + fi + if (( PKGFUNC )); then + rm -f "${pkgbase}-${fullver}-${CARCH}-package.log"* + elif (( SPLITPKG )); then + for pkg in ${pkgname[@]}; do + rm -f "${pkgbase}-${fullver}-${CARCH}-package_${pkg}.log"* + done + fi + + # clean up dangling symlinks to packages + for pkg in ${pkgname[@]}; do + for file in ${pkg}-*-*-*{${PKGEXT},${SRCEXT}}; do + if [[ -h $file && ! -e $file ]]; then + rm -f "$file" + fi + done + done + fi + fi + + remove_deps +} + +enter_fakeroot() { + msg "$(gettext "Entering %s environment...")" "fakeroot" + fakeroot -- $0 -F "${ARGLIST[@]}" || exit $? +} + +# Automatically update pkgver variable if a pkgver() function is provided +# Re-sources the PKGBUILD afterwards to allow for other variables that use $pkgver +update_pkgver() { + newpkgver=$(run_function_safe pkgver) + if ! check_pkgver "$newpkgver"; then + error "$(gettext "pkgver() generated an invalid version: %s")" "$newpkgver" + exit $E_PKGBUILD_ERROR + fi + + if [[ -n $newpkgver && $newpkgver != "$pkgver" ]]; then + if [[ -f $BUILDFILE && -w $BUILDFILE ]]; then + if ! /usr/bin/sed --follow-symlinks -i "s:^pkgver=[^ ]*:pkgver=$newpkgver:" "$BUILDFILE"; then + error "$(gettext "Failed to update %s from %s to %s")" \ + "pkgver" "$pkgver" "$newpkgver" + exit $E_PKGBUILD_ERROR + fi + /usr/bin/sed --follow-symlinks -i "s:^pkgrel=[^ ]*:pkgrel=1:" "$BUILDFILE" + source_safe "$BUILDFILE" + local fullver=$(get_full_version) + msg "$(gettext "Updated version: %s")" "$pkgbase $fullver" + else + warning "$(gettext "%s is not writeable -- pkgver will not be updated")" \ + "$BUILDFILE" + fi + fi +} + +# Print 'source not found' error message and exit makepkg +missing_source_file() { + error "$(gettext "Unable to find source file %s.")" "$(get_filename "$1")" + plain "$(gettext "Aborting...")" + exit $E_MISSING_FILE +} + +run_pacman() { + local cmd + if [[ $1 != -@(T|Q)*([[:alpha:]]) ]]; then + cmd=("$PACMAN_PATH" "${PACMAN_OPTS[@]}" "$@") + else + cmd=("$PACMAN_PATH" "$@") + fi + if [[ $1 != -@(T|Q)*([[:alpha:]]) ]]; then + if [[ $PACMAN == "pacman" ]]; then + if type -p sudo >/dev/null; then + cmd=(sudo "${cmd[@]}") + else + cmd=(su root -c "$(printf '%q ' "${cmd[@]}")") + fi + fi + fi + "${cmd[@]}" +} + +check_deps() { + (( $# > 0 )) || return 0 + + local ret=0 + local pmout + pmout=$(run_pacman -T "$@") + ret=$? + + if (( ret == 127 )); then #unresolved deps + printf "%s\n" "$pmout" + elif (( ret )); then + error "$(gettext "'%s' returned a fatal error (%i): %s")" "$PACMAN" "$ret" "$pmout" + return "$ret" + fi +} + +handle_deps() { + local R_DEPS_SATISFIED=0 + local R_DEPS_MISSING=1 + + (( $# == 0 )) && return $R_DEPS_SATISFIED + + deplist=("$@") + + if (( ! DEP_BIN )); then + return $R_DEPS_MISSING + fi + + if (( DEP_BIN )); then + # install missing deps from binary packages (using pacman -S) + msg "$(gettext "Installing missing dependencies...")" + + if ! run_pacman -S "${PACMAN_OPTS[@]}" "${deplist[@]}"; then + error "$(gettext "'%s' failed to install missing dependencies.")" "$PACMAN" + for d in "${deplist[@]}"; do + if run_pacman -Qq "${d}" >/dev/null 2>&1; then + msg "$(gettext "Removing obsolete dependency %s...")" "${d}" + run_pacman -Rs --noconfirm "${d}" + fi + done + exit $E_INSTALL_DEPS_FAILED + fi + fi + + # we might need the new system environment + # save our shell options and turn off extglob + local shellopts=$(shopt -p extglob) + shopt -u extglob + source /etc/profile &>/dev/null + eval "$shellopts" + + # umask might have been changed in /etc/profile + # ensure that sane default is set again + umask 0022 + + return $R_DEPS_SATISFIED +} + +function info_missingdeps() { + local response + + depsall=$(printf '%s ' ${deplist[@]}) + msg "$(gettext "Missing ${DEPS_TYPE} dependencies:")" + msg2 "$depsall" + printf "\n" + + case ${DEPS_TYPE} in + "buildtime") buildtime_depsall=${depsall} ;; + "runtime") runtime_depsall=${depsall} ;; + esac + +} + +function enforce_missingdeps() { + local R_DEPS_ENFORCED=0 + local R_DEPS_MISSING=1 + + msg "$(gettext "Enforce compilation without missing dependencies? [Y/n]")" + read depsresponse + + if [[ $(echo $depsresponse) =~ ^([yY][eE][sS]|[yY])$ ]]; then + NODEPS=1 + return $R_DEPS_ENFORCED + else + return $R_DEPS_MISSING + fi + +} + +function ask_missingdeps() { + local R_DEPS_SATISFIED=0 + local R_DEPS_MISSING=1 + + local list=(${1}) + local PACMAN_OPTS=('--noconfirm' '--asdeps') + + if [[ -z $depsresponse ]]; then + msg "$(gettext "Do you want to install missing dependencies? [Y/n]")" + read depsresponse + fi + + if [[ $(echo $depsresponse) =~ ^([yY][eE][sS]|[yY])$ ]]; then + DEP_BIN=1 + handle_deps ${list[@]} + else + enforce_missingdeps + fi + + if [[ $? -ne 0 ]]; then + msg "$(gettext "Missing dependencies:")" + info_missingdeps + msg "$(gettext "These packages couldn't be provided by $PACMAN")" + return $R_DEPS_MISSING + else + msg "$(gettext "Dependencies installed.")" + return $R_DEPS_SATISFIED + fi + +} + +resolve_deps() { + local R_DEPS_SATISFIED=0 + local R_DEPS_MISSING=1 + local PACMAN_OPTS=('--asdeps') + + DEPS_TYPE=${1} + shift + + # deplist cannot be declared like this: local deplist=$(foo) + # Otherwise, the return value will depend on the assignment. + local deplist + deplist=($(check_deps "$@")) || exit $E_INSTALL_DEPS_FAILED + [[ -z $deplist ]] && return $R_DEPS_SATISFIED + + if handle_deps "${deplist[@]}"; then + # check deps again to make sure they were resolved + deplist=$(check_deps "$@") || exit $E_INSTALL_DEPS_FAILED + [[ -z $deplist ]] && return $R_DEPS_SATISFIED + fi + + info_missingdeps +} + +remove_deps() { + (( ! RMDEPS )) && return 0 + + # check for packages removed during dependency install (e.g. due to conflicts) + # removing all installed packages is risky in this case + if [[ -n $(grep -xvFf <(printf '%s\n' "${current_pkglist[@]}") \ + <(printf '%s\n' "${original_pkglist[@]}")) ]]; then + warning "$(gettext "Failed to remove installed dependencies.")" + return $E_REMOVE_DEPS_FAILED + fi + + local deplist + deplist=($(grep -xvFf <(printf "%s\n" "${original_pkglist[@]}") \ + <(printf "%s\n" "${current_pkglist[@]}"))) + if [[ -z $deplist ]]; then + return 0 + fi + + msg "Removing installed dependencies..." + # exit cleanly on failure to remove deps as package has been built successfully + if ! run_pacman -Rn ${deplist[@]}; then + warning "$(gettext "Failed to remove installed dependencies.")" + return $E_REMOVE_DEPS_FAILED + fi +} + +error_function() { + if [[ -p $logpipe ]]; then + rm "$logpipe" + fi + # first exit all subshells, then print the error + if (( ! BASH_SUBSHELL )); then + error "$(gettext "A failure occurred in %s().")" "$1" + plain "$(gettext "Aborting...")" + fi + exit $E_USER_FUNCTION_FAILED +} + +source_safe() { + shopt -u extglob + if ! source "$@"; then + error "$(gettext "Failed to source %s")" "$1" + exit $E_MISSING_FILE + fi + shopt -s extglob +} + +merge_arch_attrs() { + local attr supported_attrs=( + provides conflicts depends replaces optdepends + makedepends checkdepends) + + for attr in "${supported_attrs[@]}"; do + eval "$attr+=(\"\${${attr}_$CARCH[@]}\")" + done + + # ensure that calling this function is idempotent. + unset -v "${supported_attrs[@]/%/_$CARCH}" +} + +source_buildfile() { + source_safe "$@" +} + +prepare_buildenv() { + # clear user-specified buildflags if requested + if check_option "buildflags" "n"; then + unset CPPFLAGS CFLAGS CXXFLAGS LDFLAGS + fi + + if check_option "debug" "y"; then + DEBUG_CFLAGS+=" -fdebug-prefix-map=$srcdir=${DBGSRCDIR:-/usr/src/debug}" + DEBUG_CXXFLAGS+=" -fdebug-prefix-map=$srcdir=${DBGSRCDIR:-/usr/src/debug}" + CFLAGS+=" $DEBUG_CFLAGS" + CXXFLAGS+=" $DEBUG_CXXFLAGS" + fi + + # clear user-specified makeflags if requested + if check_option "makeflags" "n"; then + unset MAKEFLAGS + fi + + # ensure all necessary build variables are exported + export CPPFLAGS CFLAGS CXXFLAGS LDFLAGS MAKEFLAGS CHOST + + local ccache=0 + + # use ccache if it is requested (check buildenv and PKGBUILD opts) + if check_buildoption "ccache" "y" && [[ -d /usr/lib/ccache/bin ]]; then + export PATH="/usr/lib/ccache/bin:$PATH" + ccache=1 + fi + + # use distcc if it is requested (check buildenv and PKGBUILD opts) + if check_buildoption "distcc" "y"; then + if (( ccache )); then + export CCACHE_PREFIX="${CCACHE_PREFIX:+$CCACHE_PREFIX }distcc" + export CCACHE_BASEDIR="$srcdir" + elif [[ -d /usr/lib/distcc/bin ]]; then + export PATH="/usr/lib/distcc/bin:$PATH" + fi + export DISTCC_HOSTS + fi +} + +run_function_safe() { + local restoretrap restoreset restoreshopt + + # we don't set any special shopts of our own, but we don't want the user to + # muck with our environment. + restoreshopt=$(shopt -p) + + restoreset=$(shopt -o -p) + shopt -o -s errexit errtrace + + restoretrap=$(trap -p ERR) + trap "error_function '$1'" ERR + + run_function "$1" + + trap - ERR + eval "$restoretrap" + eval "$restoreset" + eval "$restoreshopt" +} + +run_function() { + if [[ -z $1 ]]; then + return 1 + fi + local pkgfunc="$1" + + msg "$(gettext "Starting %s()...")" "$pkgfunc" + cd_safe "$srcdir" + + # save our shell options so pkgfunc() can't override what we need + local shellopts=$(shopt -p) + + local ret=0 + if (( LOGGING )); then + local fullver=$(get_full_version) + local BUILDLOG="$LOGDEST/${pkgbase}-${fullver}-${CARCH}-$pkgfunc.log" + if [[ -f $BUILDLOG ]]; then + local i=1 + while true; do + if [[ -f $BUILDLOG.$i ]]; then + i=$(($i +1)) + else + break + fi + done + mv "$BUILDLOG" "$BUILDLOG.$i" + fi + + # ensure overridden package variables survive tee with split packages + logpipe=$(mktemp -u "$LOGDEST/logpipe.XXXXXXXX") + mkfifo "$logpipe" + tee "$BUILDLOG" < "$logpipe" & + local teepid=$! + + $pkgfunc &>"$logpipe" + + wait $teepid + rm "$logpipe" + else + "$pkgfunc" + fi + # reset our shell options + eval "$shellopts" +} + +run_prepare() { + run_function_safe "prepare" +} + +run_build() { + run_function_safe "build" +} + +run_check() { + run_function_safe "check" +} + +run_package() { + local pkgfunc + if [[ -z $1 ]]; then + pkgfunc="package" + else + pkgfunc="package_$1" + fi + + run_function_safe "$pkgfunc" +} + +find_libdepends() { + local d sodepends; + + sodepends=0; + for d in "${depends[@]}"; do + if [[ $d = *.so ]]; then + sodepends=1; + break; + fi + done + + if (( sodepends == 0 )); then + (( ${#depends[@]} )) && printf '%s\n' "${depends[@]}" + return 0 + fi + + local libdeps filename soarch sofile soname soversion; + declare -A libdeps; + + while read -r filename; do + # get architecture of the file; if soarch is empty it's not an ELF binary + soarch=$(LC_ALL=C readelf -h "$filename" 2>/dev/null | sed -n 's/.*Class.*ELF\(32\|64\)/\1/p') + [[ -n "$soarch" ]] || continue + + # process all libraries needed by the binary + for sofile in $(LC_ALL=C readelf -d "$filename" 2>/dev/null | sed -nr 's/.*Shared library: \[(.*)\].*/\1/p') + do + # extract the library name: libfoo.so + soname="${sofile%.so?(+(.+([0-9])))}".so + # extract the major version: 1 + soversion="${sofile##*\.so\.}" + + if [[ ${libdeps[$soname]} ]]; then + if [[ ${libdeps[$soname]} != *${soversion}-${soarch}* ]]; then + libdeps[$soname]+=" ${soversion}-${soarch}" + fi + else + libdeps[$soname]="${soversion}-${soarch}" + fi + done + done < <(find "$pkgdir" -type f -perm -u+x) + + local libdepends v + for d in "${depends[@]}"; do + case "$d" in + *.so) + if [[ ${libdeps[$d]} ]]; then + for v in ${libdeps[$d]}; do + libdepends+=("$d=$v") + done + else + warning "$(gettext "Library listed in %s is not required by any files: %s")" "'depends'" "$d" + libdepends+=("$d") + fi + ;; + *) + libdepends+=("$d") + ;; + esac + done + + (( ${#libdepends[@]} )) && printf '%s\n' "${libdepends[@]}" +} + + +find_libprovides() { + local p libprovides missing + for p in "${provides[@]}"; do + missing=0 + case "$p" in + *.so) + mapfile -t filename < <(find "$pkgdir" -type f -name $p\*) + if [[ $filename ]]; then + # packages may provide multiple versions of the same library + for fn in "${filename[@]}"; do + # check if we really have a shared object + if LC_ALL=C readelf -h "$fn" 2>/dev/null | grep -q '.*Type:.*DYN (Shared object file).*'; then + # get the string binaries link to (e.g. libfoo.so.1.2 -> libfoo.so.1) + local sofile=$(LC_ALL=C readelf -d "$fn" 2>/dev/null | sed -n 's/.*Library soname: \[\(.*\)\].*/\1/p') + if [[ -z "$sofile" ]]; then + warning "$(gettext "Library listed in %s is not versioned: %s")" "'provides'" "$p" + libprovides+=("$p") + continue + fi + + # get the library architecture (32 or 64 bit) + local soarch=$(LC_ALL=C readelf -h "$fn" | sed -n 's/.*Class.*ELF\(32\|64\)/\1/p') + + # extract the library major version + local soversion="${sofile##*\.so\.}" + + libprovides+=("${p}=${soversion}-${soarch}") + else + warning "$(gettext "Library listed in %s is not a shared object: %s")" "'provides'" "$p" + libprovides+=("$p") + fi + done + else + libprovides+=("$p") + missing=1 + fi + ;; + *) + libprovides+=("$p") + ;; + esac + + if (( missing )); then + warning "$(gettext "Cannot find library listed in %s: %s")" "'provides'" "$p" + fi + done + + (( ${#libprovides[@]} )) && printf '%s\n' "${libprovides[@]}" +} + +write_kv_pair() { + local key="$1" + shift + + for val in "$@"; do + if [[ $val = *$'\n'* ]]; then + error "$(gettext "Invalid value for %s: %s")" "$key" "$val" + exit $E_PKGBUILD_ERROR + fi + printf "%s = %s\n" "$key" "$val" + done +} + +write_pkginfo() { + local size="$(/usr/bin/du -sk --apparent-size)" + size="$(( ${size%%[^0-9]*} * 1024 ))" + + merge_arch_attrs + + msg2 "$(gettext "Generating %s file...")" ".PKGINFO" + printf "# Generated by makepkg %s\n" "$makepkg_version" + printf "# using %s\n" "$(fakeroot -v)" + + write_kv_pair "pkgname" "$pkgname" + write_kv_pair "pkgbase" "$pkgbase" + + local fullver=$(get_full_version) + write_kv_pair "pkgver" "$fullver" + + # TODO: all fields should have this treatment + local spd="${pkgdesc//+([[:space:]])/ }" + spd=("${spd[@]#[[:space:]]}") + spd=("${spd[@]%[[:space:]]}") + + write_kv_pair "pkgdesc" "$spd" + write_kv_pair "url" "$url" + write_kv_pair "builddate" "$SOURCE_DATE_EPOCH" + write_kv_pair "packager" "$PACKAGER" + write_kv_pair "size" "$size" + write_kv_pair "arch" "$pkgarch" + + mapfile -t provides < <(find_libprovides) + mapfile -t depends < <(find_libdepends) + + write_kv_pair "license" "${license[@]}" + write_kv_pair "replaces" "${replaces[@]}" + write_kv_pair "group" "${groups[@]}" + write_kv_pair "conflict" "${conflicts[@]}" + write_kv_pair "provides" "${provides[@]}" + write_kv_pair "backup" "${backup[@]}" + write_kv_pair "depend" "${depends[@]}" + write_kv_pair "optdepend" "${optdepends[@]//+([[:space:]])/ }" + write_kv_pair "makedepend" "${makedepends[@]}" + write_kv_pair "checkdepend" "${checkdepends[@]}" +} + +write_buildinfo() { + msg2 "$(gettext "Generating %s file...")" ".BUILDINFO" + + write_kv_pair "format" "1" + + write_kv_pair "pkgname" "$pkgname" + write_kv_pair "pkgbase" "$pkgbase" + + local fullver=$(get_full_version) + write_kv_pair "pkgver" "$fullver" + + write_kv_pair "pkgarch" "$pkgarch" + + local sum="$(sha256sum "${BUILDFILE}")" + sum=${sum%% *} + write_kv_pair "pkgbuild_sha256sum" $sum + + write_kv_pair "packager" "${PACKAGER}" + write_kv_pair "builddate" "${SOURCE_DATE_EPOCH}" + write_kv_pair "builddir" "${BUILDDIR}" + write_kv_pair "buildenv" "${BUILDENV[@]}" + write_kv_pair "options" "${OPTIONS[@]}" + + local pkginfos_parsed=($(LC_ALL=C run_pacman -Qi | awk -F': ' '\ + /^Name .*/ {printf "%s", $2} \ + /^Version .*/ {printf "-%s", $2} \ + /^Architecture .*/ {print "-"$2} \ + ')) + + write_kv_pair "installed" "${pkginfos_parsed[@]}" +} + +#write_kv_pair() { +# local key="$1" +# shift +# +# for val in "$@"; do +# if [[ $val = *$'\n'* ]]; then +# error "$(gettext "Invalid value for %s: %s")" "$key" "$val" +# exit $E_PKGBUILD_ERROR +# fi +# done +# printf "%s = %s\n" "$key" "$@" +#} +# +#write_pkginfo() { +# local size="$(/usr/bin/du -sk --apparent-size)" +# size="$(( ${size%%[^0-9]*} * 1024 ))" +# +# merge_arch_attrs +# +# msg2 "$(gettext "Generating %s file...")" ".PKGINFO" +# printf "# Generated by makepkg %s\n" "$makepkg_version" +# printf "# using %s\n" "$(fakeroot -v)" +# +# write_kv_pair "pkgname" "$pkgname" +# write_kv_pair "pkgbase" "$pkgbase" +# +# local fullver=$(get_full_version) +# write_kv_pair "pkgver" "$fullver" +# +# # TODO: all fields should have this treatment +# local spd="${pkgdesc//+([[:space:]])/ }" +# spd=("${spd[@]#[[:space:]]}") +# spd=("${spd[@]%[[:space:]]}") +# +# write_kv_pair "pkgdesc" "$spd" +# write_kv_pair "url" "$url" +# write_kv_pair "builddate" "$SOURCE_DATE_EPOCH" +# write_kv_pair "packager" "$PACKAGER" +# write_kv_pair "size" "$size" +# write_kv_pair "arch" "$pkgarch" +# +# mapfile -t provides < <(find_libprovides) +# mapfile -t depends < <(find_libdepends) +# +# write_kv_pair "license" "${license[@]}" +# write_kv_pair "replaces" "${replaces[@]}" +# write_kv_pair "group" "${groups[@]}" +# write_kv_pair "conflict" "${conflicts[@]}" +# write_kv_pair "provides" "${provides[@]}" +# write_kv_pair "backup" "${backup[@]}" +# write_kv_pair "depend" "${depends[@]}" +# write_kv_pair "optdepend" "${optdepends[@]//+([[:space:]])/ }" +# write_kv_pair "makedepend" "${makedepends[@]}" +# write_kv_pair "checkdepend" "${checkdepends[@]}" +#} +# +#write_buildinfo() { +# msg2 "$(gettext "Generating %s file...")" ".BUILDINFO" +# +# write_kv_pair "format" "1" +# +# write_kv_pair "pkgname" "$pkgname" +# write_kv_pair "pkgbase" "$pkgbase" +# +# local fullver=$(get_full_version) +# write_kv_pair "pkgver" "$fullver" +# +# write_kv_pair "pkgarch" "$pkgarch" +# +# local sum="$(sha256sum "${BUILDFILE}")" +# sum=${sum%% *} +# write_kv_pair "pkgbuild_sha256sum" $sum +# +# write_kv_pair "packager" "${PACKAGER}" +# write_kv_pair "builddate" "${SOURCE_DATE_EPOCH}" +# write_kv_pair "builddir" "${BUILDDIR}" +# write_kv_pair "buildenv" "${BUILDENV[@]}" +# write_kv_pair "options" "${OPTIONS[@]}" +# +# # Additional build time environment information +# write_kv_pair "CPPFLAGS" "${CPPFLAGS}" +# write_kv_pair "CFLAGS" "${CFLAGS}" +# write_kv_pair "CXXFLAGS" "${CXXFLAGS}" +# write_kv_pair "LDFLAGS" "${LDFLAGS}" +# write_kv_pair "MAKEFLAGS" "${MAKEFLAGS}" +# write_kv_pair "DEBUG_CFLAGS" "${DEBUG_CFLAGS}" +# write_kv_pair "DEBUG_CXXFLAGS" "${DEBUG_CXXFLAGS}" +# write_kv_pair "STRIP_BINARIES" "${STRIP_BINARIES}" +# write_kv_pair "STRIP_SHARED" "${STRIP_SHARED}" +# write_kv_pair "STRIP_STATIC" "${STRIP_STATIC}" +# +# local pkginfos_parsed=($(LC_ALL=C run_pacman -Qi | awk -F': ' '\ +# /^Name .*/ {printf "%s", $2} \ +# /^Version .*/ {printf "-%s", $2} \ +# /^Architecture .*/ {print "-"$2} \ +# ')) +# +# write_kv_pair "installed" "${pkginfos_parsed[@]}" +#} + +# build a sorted NUL-separated list of the full contents of the current +# directory suitable for passing to `bsdtar --files-from` +# database files are placed at the beginning of the package regardless of +# sorting +list_package_files() { + (find . -path './.*' \! -name '.'; find . \! -path './.*' \! -name '.' | LC_ALL=C sort) | + sed -e 's|^\./||' | tr '\n' '\0' +} + +create_package() { + (( NOARCHIVE )) && return 0 + + if [[ ! -d $pkgdir ]]; then + error "$(gettext "Missing %s directory.")" "\$pkgdir/" + plain "$(gettext "Aborting...")" + exit $E_MISSING_PKGDIR + fi + + cd_safe "$pkgdir" + msg "$(gettext "Creating package \"%s\"...")" "$pkgname" + + pkgarch=$(get_pkg_arch) + write_pkginfo > .PKGINFO + write_buildinfo > .BUILDINFO + + # check for changelog/install files + for i in 'changelog/.CHANGELOG' 'install/.INSTALL'; do + IFS='/' read -r orig dest < <(printf '%s\n' "$i") + + if [[ -n ${!orig} ]]; then + msg2 "$(gettext "Adding %s file...")" "$orig" + if ! cp "$startdir/${!orig}" "$dest"; then + error "$(gettext "Failed to add %s file to package.")" "$orig" + exit $E_MISSING_FILE + fi + chmod 644 "$dest" + fi + done + + # tar it up + local fullver=$(get_full_version) + local pkg_file="$PKGDEST/${pkgname}-${fullver}-${pkgarch}${PKGEXT}" + local ret=0 + + [[ -f $pkg_file ]] && rm -f "$pkg_file" + [[ -f $pkg_file.sig ]] && rm -f "$pkg_file.sig" + + # ensure all elements of the package have the same mtime + find . -exec touch -h -d @$SOURCE_DATE_EPOCH {} + + + msg2 "$(gettext "Generating .MTREE file...")" + list_package_files | LANG=C bsdtar -cnf - --format=mtree \ + --options='!all,use-set,type,uid,gid,mode,time,size,md5,sha256,link' \ + --null --files-from - --exclude .MTREE | gzip -c -f -n > .MTREE + touch -d @$SOURCE_DATE_EPOCH .MTREE + + msg2 "$(gettext "Compressing package...")" + # TODO: Maybe this can be set globally for robustness + shopt -s -o pipefail + list_package_files | LANG=C bsdtar -cnf - --null --files-from - | + compress_as "$PKGEXT" > "${pkg_file}" || ret=$? + + shopt -u -o pipefail + + if (( ret )); then + error "$(gettext "Failed to create package file.")" + exit $E_PACKAGE_FAILED + fi +} + +create_debug_package() { + # check if a debug package was requested + if ! check_option "debug" "y" || ! check_option "strip" "y"; then + return 0 + fi + + pkgdir="$pkgdirbase/$pkgbase-debug" + + # check if we have any debug symbols to package + if dir_is_empty "$pkgdir/usr/lib/debug"; then + return 0 + fi + + unset groups depends optdepends provides conflicts replaces backup install changelog + + local pkg + for pkg in ${pkgname[@]}; do + if [[ $pkg != $pkgbase ]]; then + provides+=("$pkg-debug") + fi + done + + pkgdesc="Detached debugging symbols for $pkgname" + pkgname=$pkgbase-debug + + create_package +} + +create_srcpackage() { + local ret=0 + msg "$(gettext "Creating source package...")" + local srclinks="$(mktemp -d "$startdir"/srclinks.XXXXXXXXX)" + mkdir "${srclinks}"/${pkgbase} + + msg2 "$(gettext "Adding %s...")" "$BUILDSCRIPT" + ln -s "${BUILDFILE}" "${srclinks}/${pkgbase}/${BUILDSCRIPT}" + + msg2 "$(gettext "Generating %s file...")" .SRCINFO + write_srcinfo > "$srclinks/$pkgbase"/.SRCINFO + + local file all_sources + + get_all_sources 'all_sources' + for file in "${all_sources[@]}"; do + if [[ "$file" = "$(get_filename "$file")" ]] || (( SOURCEONLY == 2 )); then + local absfile + absfile=$(get_filepath "$file") || missing_source_file "$file" + msg2 "$(gettext "Adding %s...")" "${absfile##*/}" + ln -s "$absfile" "$srclinks/$pkgbase" + fi + done + + local i + for i in 'changelog' 'install'; do + local file files + + [[ ${!i} ]] && files+=("${!i}") + for name in "${pkgname[@]}"; do + if extract_function_variable "package_$name" "$i" 0 file; then + files+=("$file") + fi + done + + for file in "${files[@]}"; do + if [[ $file && ! -f "${srclinks}/${pkgbase}/$file" ]]; then + msg2 "$(gettext "Adding %s file (%s)...")" "$i" "${file}" + ln -s "${startdir}/$file" "${srclinks}/${pkgbase}/" + fi + done + done + + local fullver=$(get_full_version) + local pkg_file="$SRCPKGDEST/${pkgbase}-${fullver}${SRCEXT}" + + # tar it up + msg2 "$(gettext "Compressing source package...")" + cd_safe "${srclinks}" + + # TODO: Maybe this can be set globally for robustness + shopt -s -o pipefail + LANG=C bsdtar -cLf - ${pkgbase} | compress_as "$SRCEXT" > "${pkg_file}" || ret=$? + + shopt -u -o pipefail + + if (( ret )); then + error "$(gettext "Failed to create source package file.")" + exit $E_PACKAGE_FAILED + fi + + cd_safe "${startdir}" + rm -rf "${srclinks}" +} + +install_package() { + (( ! INSTALL )) && return 0 + + if (( ! SPLITPKG )); then + msg "$(gettext "Installing package %s with %s...")" "$pkgname" "$PACMAN -U" + else + msg "$(gettext "Installing %s package group with %s...")" "$pkgbase" "$PACMAN -U" + fi + + local fullver pkgarch pkg pkglist + (( ASDEPS )) && pkglist+=('--asdeps') + (( NEEDED )) && pkglist+=('--needed') + + for pkg in ${pkgname[@]}; do + fullver=$(get_full_version) + pkgarch=$(get_pkg_arch $pkg) + pkglist+=("$PKGDEST/${pkg}-${fullver}-${pkgarch}${PKGEXT}") + + if [[ -f "$PKGDEST/${pkg}-debug-${fullver}-${pkgarch}${PKGEXT}" ]]; then + pkglist+=("$PKGDEST/${pkg}-debug-${fullver}-${pkgarch}${PKGEXT}") + fi + done + + if ! run_pacman -U "${pkglist[@]}"; then + warning "$(gettext "Failed to install built package(s).")" + return $E_INSTALL_FAILED + fi +} + +get_vcsclient() { + local proto=${1%%+*} + + local i + for i in "${VCSCLIENTS[@]}"; do + local handler="${i%%::*}" + if [[ $proto = "$handler" ]]; then + local client="${i##*::}" + break + fi + done + + # if we didn't find an client, return an error + if [[ -z $client ]]; then + error "$(gettext "Unknown download protocol: %s")" "$proto" + plain "$(gettext "Aborting...")" + exit $E_CONFIG_ERROR + fi + + printf "%s\n" "$client" +} + +check_vcs_software() { + local netfile all_sources all_deps deps ret=0 + + if (( SOURCEONLY == 1 )); then + # we will not download VCS sources + return $ret + fi + + if [[ -z $PACMAN_PATH ]]; then + warning "$(gettext "Cannot find the %s binary needed to check VCS source requirements.")" "$PACMAN" + return $ret + fi + + # we currently only use global depends/makedepends arrays for --syncdeps + for attr in depends makedepends; do + get_pkgbuild_attribute "$pkg" "$attr" 1 'deps' + all_deps+=("${deps[@]}") + + get_pkgbuild_attribute "$pkg" "${attr}_$CARCH" 1 'deps' + all_deps+=("${deps[@]}") + done + + get_all_sources_for_arch 'all_sources' + for netfile in ${all_sources[@]}; do + local proto=$(get_protocol "$netfile") + + case $proto in + bzr*|git*|hg*|svn*) + if ! type -p ${proto%%+*} > /dev/null; then + local client + client=$(get_vcsclient "$proto") || exit $? + # ensure specified program is installed + local uninstalled + uninstalled=$(check_deps "$client") || exit $E_INSTALL_DEPS_FAILED + # if not installed, check presence in depends or makedepends + if [[ -n "$uninstalled" ]] && (( ! NODEPS || ( VERIFYSOURCE && !DEP_BIN ) )); then + if ! in_array "$client" ${all_deps[@]}; then + error "$(gettext "Cannot find the %s package needed to handle %s sources.")" \ + "$client" "${proto%%+*}" + ret=1 + fi + fi + fi + ;; + *) + # non VCS source + ;; + esac + done + + return $ret +} + +check_software() { + # check for needed software + local ret=0 + + # check for PACMAN if we need it + if (( ! NODEPS || DEP_BIN || RMDEPS || INSTALL )); then + if [[ -z $PACMAN_PATH ]]; then + error "$(gettext "Cannot find the %s binary required for dependency operations.")" "$PACMAN" + ret=1 + fi + fi + + # check for sudo if we will need it during makepkg execution + if (( DEP_BIN || RMDEPS || INSTALL )); then + if ! type -p sudo >/dev/null; then + warning "$(gettext "Cannot find the %s binary. Will use %s to acquire root privileges.")" "sudo" "su" + fi + fi + + # fakeroot - correct package file permissions + if check_buildenv "fakeroot" "y" && (( EUID > 0 )); then + if ! type -p fakeroot >/dev/null; then + error "$(gettext "Cannot find the %s binary.")" "fakeroot" + ret=1 + fi + fi + + # gpg - package signing + if [[ $SIGNPKG == 'y' ]] || { [[ -z $SIGNPKG ]] && check_buildenv "sign" "y"; }; then + if ! type -p gpg >/dev/null; then + error "$(gettext "Cannot find the %s binary required for signing packages.")" "gpg" + ret=1 + fi + fi + + # gpg - source verification + if (( ! SKIPPGPCHECK )) && source_has_signatures; then + if ! type -p gpg >/dev/null; then + error "$(gettext "Cannot find the %s binary required for verifying source files.")" "gpg" + ret=1 + fi + fi + + # checksum operations + if (( GENINTEG || ! SKIPCHECKSUMS )); then + local integlist + IFS=$'\n' read -rd '' -a integlist < <(get_integlist) + + local integ + for integ in "${integlist[@]}"; do + if ! type -p "${integ}sum" >/dev/null; then + error "$(gettext "Cannot find the %s binary required for source file checksums operations.")" "${integ}sum" + ret=1 + fi + done + fi + + # distcc - compilation with distcc + if check_buildoption "distcc" "y"; then + if ! type -p distcc >/dev/null; then + error "$(gettext "Cannot find the %s binary required for distributed compilation.")" "distcc" + ret=1 + fi + fi + + # ccache - compilation with ccache + if check_buildoption "ccache" "y"; then + if ! type -p ccache >/dev/null; then + error "$(gettext "Cannot find the %s binary required for compiler cache usage.")" "ccache" + ret=1 + fi + fi + + # strip - strip symbols from binaries/libraries + if check_option "strip" "y"; then + if ! type -p strip >/dev/null; then + error "$(gettext "Cannot find the %s binary required for object file stripping.")" "strip" + ret=1 + fi + fi + + # gzip - compressig man and info pages + if check_option "zipman" "y"; then + if ! type -p gzip >/dev/null; then + error "$(gettext "Cannot find the %s binary required for compressing man and info pages.")" "gzip" + ret=1 + fi + fi + + # tools to download vcs sources + if ! check_vcs_software; then + ret=1 + fi + + return $ret +} + +check_build_status() { + if (( ! SPLITPKG )); then + fullver=$(get_full_version) + pkgarch=$(get_pkg_arch) + if [[ -f $PKGDEST/${pkgname}-${fullver}-${pkgarch}${PKGEXT} ]] \ + && ! (( FORCE || SOURCEONLY || NOBUILD || NOARCHIVE)); then + if (( INSTALL )); then + warning "$(gettext "A package has already been built, installing existing package...")" + install_package + exit $? + else + error "$(gettext "A package has already been built. (use %s to overwrite)")" "-f" + exit $E_ALREADY_BUILT + fi + fi + else + allpkgbuilt=1 + somepkgbuilt=0 + for pkg in ${pkgname[@]}; do + fullver=$(get_full_version) + pkgarch=$(get_pkg_arch $pkg) + if [[ -f $PKGDEST/${pkg}-${fullver}-${pkgarch}${PKGEXT} ]]; then + somepkgbuilt=1 + else + allpkgbuilt=0 + fi + done + if ! (( FORCE || SOURCEONLY || NOBUILD || NOARCHIVE)); then + if (( allpkgbuilt )); then + if (( INSTALL )); then + warning "$(gettext "The package group has already been built, installing existing packages...")" + install_package + exit $? + else + error "$(gettext "The package group has already been built. (use %s to overwrite)")" "-f" + exit $E_ALREADY_BUILT + fi + fi + if (( somepkgbuilt && ! PKGVERFUNC )); then + error "$(gettext "Part of the package group has already been built. (use %s to overwrite)")" "-f" + exit $E_ALREADY_BUILT + fi + fi + unset allpkgbuilt somepkgbuilt + fi +} + +backup_package_variables() { + local var + for var in ${splitpkg_overrides[@]}; do + local indirect="${var}_backup" + eval "${indirect}=(\"\${$var[@]}\")" + done +} + +restore_package_variables() { + local var + for var in ${splitpkg_overrides[@]}; do + local indirect="${var}_backup" + if [[ -n ${!indirect} ]]; then + eval "${var}=(\"\${$indirect[@]}\")" + else + unset ${var} + fi + done +} + +run_split_packaging() { + local pkgname_backup=("${pkgname[@]}") + for pkgname in ${pkgname_backup[@]}; do + pkgdir="$pkgdirbase/$pkgname" + mkdir "$pkgdir" + backup_package_variables + run_package $pkgname + tidy_install + lint_package || exit $E_PACKAGE_FAILED + create_package + restore_package_variables + done + pkgname=("${pkgname_backup[@]}") + create_debug_package +} + +function get_repository_files() { + + if [[ -n ${REPOPACKAGE} ]]; then + + getsource $REPOPACKAGE $BUILDSCRIPT + + if [[ $? -ne 0 ]]; then + error "$(gettext "Couldn't get source files for $REPOPACKAGE")" + exit 1 + fi + + else + error "$(gettext "Package name not given.")" + exit 1 + fi + exit $E_OK +} + +usage() { + printf "makepkg (pacman) %s\n" "$makepkg_version" + echo + printf -- "$(gettext "Make packages compatible for use with pacman")\n" + echo + printf -- "$(gettext "Usage: %s [options]")\n" "$0" + echo + printf -- "$(gettext "Options:")\n" + printf -- "$(gettext " -A, --ignorearch Ignore incomplete %s field in %s")\n" "arch" "$BUILDSCRIPT" + printf -- "$(gettext " -c, --clean Clean up work files after build")\n" + printf -- "$(gettext " -C, --cleanbuild Remove %s dir before building the package")\n" "\$srcdir/" + printf -- "$(gettext " -d, --nodeps Skip all dependency checks")\n" + printf -- "$(gettext " -D, --rmbuilddeps Remove installed build time dependencies after a successful build")\n" + printf -- "$(gettext " -e, --noextract Do not extract source files (use existing %s dir)")\n" "\$srcdir/" + printf -- "$(gettext " -f, --force Overwrite existing package")\n" + printf -- "$(gettext " -g, --geninteg Generate integrity checks for source files")\n" + printf -- "$(gettext " -h, --help Show this help message and exit")\n" + printf -- "$(gettext " -i, --install Install package after successful build")\n" + printf -- "$(gettext " -L, --log Log package build process")\n" + printf -- "$(gettext " -m, --nocolor Disable colorized output messages")\n" + printf -- "$(gettext " -o, --nobuild Download and extract files only")\n" + printf -- "$(gettext " -p Use an alternate build script (instead of '%s')")\n" "$BUILDSCRIPT" + printf -- "$(gettext " -r, --rmdeps Remove installed dependencies after a successful build")\n" + printf -- "$(gettext " -R, --repackage Repackage contents of the package without rebuilding")\n" + printf -- "$(gettext " -s, --syncdeps Install missing dependencies with %s")\n" "${PACMAN}" + printf -- "$(gettext " -S, --source Generate a source-only tarball without downloaded sources")\n" + printf -- "$(gettext " -U, --updpkgsums Update integrity check sums for source files with updpkgsums")\n" + printf -- "$(gettext " -V, --version Show version information and exit")\n" + printf -- "$(gettext " --addgroup Add package to a user-defined pacman group")\n" + printf -- "$(gettext " --allsource Generate a source-only tarball including downloaded sources")\n" + printf -- "$(gettext " --check Run the %s function in the %s")\n" "check()" "$BUILDSCRIPT" + printf -- "$(gettext " --config Use an alternate config file (instead of '%s')")\n" "$confdir/makepkg.conf" + printf -- "$(gettext " --getsource Get source files from Arch Linux repositories")\n" + printf -- "$(gettext " --holdver Do not update VCS sources")\n" + printf -- "$(gettext " --key Specify a key to use for %s signing instead of the default")\n" "gpg" + printf -- "$(gettext " --noarchive Do not create package archive")\n" + 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 " --packagelist Only list package filepaths that would be produced")\n" + printf -- "$(gettext " --printsrcinfo Print the generated SRCINFO and exit")\n" + printf -- "$(gettext " --sign Sign the resulting package with %s")\n" "gpg" + printf -- "$(gettext " --nochecksums Do not verify checksums of the source files")\n" + printf -- "$(gettext " --nointeg Do not perform any verification checks on source files")\n" + printf -- "$(gettext " --nocertcheck Do not verify source files with PGP signatures")\n" + printf -- "$(gettext " --verifysource Download source files (if needed) and perform integrity checks")\n" + echo + printf -- "$(gettext "These options can be passed to %s:")\n" "${PACMAN}" + echo + printf -- "$(gettext " --asdeps Install packages as non-explicitly installed")\n" + printf -- "$(gettext " --needed Do not reinstall the targets that are already up to date")\n" + printf -- "$(gettext " --noconfirm Do not ask for confirmation when resolving dependencies")\n" + printf -- "$(gettext " --noprogressbar Do not show a progress bar when downloading files")\n" + echo + printf -- "$(gettext "If %s is not specified, %s will look for '%s'")\n" "-p" "makepkg" "$BUILDSCRIPT" + echo +} + +version() { + printf "makepkg (pacman) %s\n" "$makepkg_version" + printf -- "$(gettext "\ +Copyright (c) 2019 Pekka Helenius .\n\ +Copyright (c) 2006-2018 Pacman Development Team .\n\ +Copyright (C) 2002-2006 Judd Vinet .\n\n\ +This is free software; see the source for copying conditions.\n\ +There is NO WARRANTY, to the extent permitted by law.\n")" +} + +# PROGRAM START + +# ensure we have a sane umask set +umask 0022 + +# determine whether we have gettext; make it a no-op if we do not +if ! type -p gettext >/dev/null; then + gettext() { + printf "%s\n" "$@" + } +fi + +ARGLIST=("$@") + +# Parse Command Line Options. +OPT_SHORT="AcCdDefFghiLmop:rRsSUV" +OPT_LONG=('allsource' 'addgroup:' 'check' 'clean' 'cleanbuild' 'rmbuilddeps' 'config:' 'force' 'geninteg' + 'help' 'holdver' 'ignorearch' 'install' 'key:' 'log' 'noarchive' 'nobuild' + 'nocolor' 'nocheck' 'nodeps' 'noextract' 'noprepare' 'nosign' 'packagelist' + 'printsrcinfo' 'repackage' 'rmdeps' 'sign' 'nochecksums' 'nointeg' + 'nocertcheck' 'source' 'syncdeps' 'updpkgsums' 'verifysource' 'version' 'getsource:') + +# Pacman Options +OPT_LONG+=('asdeps' 'noconfirm' 'needed' 'noprogressbar') + +if ! parseopts "$OPT_SHORT" "${OPT_LONG[@]}" -- "$@"; then + exit $E_INVALID_OPTION; +fi +set -- "${OPTRET[@]}" +unset OPT_SHORT OPT_LONG OPTRET + +while true; do + case "$1" in + # Pacman Options + --asdeps) ASDEPS=1 ;; + --needed) NEEDED=1 ;; + --noconfirm) PACMAN_OPTS+=("--noconfirm") ;; + --noprogressbar) PACMAN_OPTS+=("--noprogressbar") ;; + + # Makepkg Options + --addgroup) shift; ADDGROUP=$1 ;; + --allsource) SOURCEONLY=2 ;; + -A|--ignorearch) IGNOREARCH=1 ;; + -c|--clean) CLEANUP=1 ;; + -C|--cleanbuild) CLEANBUILD=1 ;; + --check) RUN_CHECK='y' ;; + --config) shift; MAKEPKG_CONF=$1 ;; + -d|--nodeps) NODEPS=1 ;; + -D|--rmbuilddeps) RMBUILDDEPS=1 ;; + -e|--noextract) NOEXTRACT=1 ;; + -f|--force) FORCE=1 ;; + -F) INFAKEROOT=1 ;; + # generating integrity checks does not depend on architecture + -g|--geninteg) GENINTEG=1 IGNOREARCH=1 ;; + --getsource) shift; REPOPACKAGE=$1 ;; + --holdver) HOLDVER=1 ;; + -i|--install) INSTALL=1 ;; + --key) shift; GPGKEY=$1 ;; + -L|--log) LOGGING=1 ;; + -m|--nocolor) USE_COLOR='n'; PACMAN_OPTS+=("--color" "never") ;; + --noarchive) NOARCHIVE=1 ;; + --nocheck) RUN_CHECK='n' ;; + --noprepare) RUN_PREPARE='n' ;; + --nosign) SIGNPKG='n' ;; + -o|--nobuild) NOBUILD=1; NODEPS=1; SKIPPGPCHECK=1; SKIPPGPCHECK=1; SKIPCHECKSUMS=1 ;; + -p) shift; BUILDFILE=$1 ;; + --packagelist) PACKAGELIST=1 IGNOREARCH=1 ;; + --printsrcinfo) PRINTSRCINFO=1 IGNOREARCH=1 ;; + -r|--rmdeps) RMDEPS=1 ;; + -R|--repackage) REPKG=1 ;; + --sign) SIGNPKG='y' ;; + --nochecksums) SKIPCHECKSUMS=1 ;; + --nointeg) SKIPCHECKSUMS=1; SKIPPGPCHECK=1 ;; + --nocertcheck) SKIPPGPCHECK=1 ;; + -s|--syncdeps) DEP_BIN=1 ;; + -S|--source) SOURCEONLY=1 ;; + -U|--updpkgsums) UPDPKGSUMS=1; ;; + --verifysource) VERIFYSOURCE=1 ;; + + -h|--help) usage; exit $E_OK ;; + -V|--version) version; exit $E_OK ;; + + --) shift; break ;; + esac + shift +done + +# attempt to consume any extra argv as environment variables. this supports +# overriding (e.g. CC=clang) as well as overriding (e.g. CFLAGS+=' -g'). +extra_environment=() +while [[ $1 ]]; do + if [[ $1 = [_[:alpha:]]*([[:alnum:]_])?(+)=* ]]; then + extra_environment+=("$1") + fi + shift +done + +# TODO improve left-over dependency handling here +# setup signal traps +trap 'clean_up' 0 +for signal in TERM HUP QUIT; do + trap "trap_exit $signal \"$(gettext "%s signal caught. Exiting...")\" \"$signal\"" "$signal" +done +trap 'trap_exit INT "$(gettext "Aborted by user! Exiting...")"' INT +trap 'trap_exit USR1 "$(gettext "An unknown error has occurred. Exiting...")"' ERR + +# preserve environment variables to override makepkg.conf +restore_envvars=$(declare -p PKGDEST SRCDEST SRCPKGDEST LOGDEST BUILDDIR PKGEXT SRCEXT GPGKEY PACKAGER CARCH 2>/dev/null || true) + +# default config is makepkg.conf +MAKEPKG_CONF=${MAKEPKG_CONF:-$confdir/makepkg.conf} + +# Source the config file; fail if it is not found +if [[ -r $MAKEPKG_CONF ]]; then + source_safe "$MAKEPKG_CONF" +else + error "$(gettext "%s not found.")" "$MAKEPKG_CONF" + plain "$(gettext "Aborting...")" + exit $E_CONFIG_ERROR +fi + +# Source user-specific makepkg.conf overrides, but only if no override config +# file was specified +XDG_PACMAN_DIR="${XDG_CONFIG_HOME:-$HOME/.config}/pacman" +if [[ "$MAKEPKG_CONF" = "$confdir/makepkg.conf" ]]; then + if [[ -r "$XDG_PACMAN_DIR/makepkg.conf" ]]; then + source_safe "$XDG_PACMAN_DIR/makepkg.conf" + elif [[ -r "$HOME/.makepkg.conf" ]]; then + source_safe "$HOME/.makepkg.conf" + fi +fi + +eval "$restore_envvars" + +# override settings from extra variables on commandline, if any +if (( ${#extra_environment[*]} )); then + export "${extra_environment[@]}" +fi + +# canonicalize paths and provide defaults if anything is still undefined +for var in PKGDEST SRCDEST SRCPKGDEST LOGDEST BUILDDIR; do + printf -v "$var" "$(canonicalize_path "${!var:-$startdir}")" +done +unset var +PACKAGER=${PACKAGER:-"Unknown Packager"} + +# set pacman command if not already defined +PACMAN_HELPER="pacaur" +PACMAN=${PACMAN:-${PACMAN_HELPER}} +# save full path to command as PATH may change when sourcing /etc/profile +PACMAN_PATH=$(type -P $PACMAN) + +# check if messages are to be printed using color +if [[ -t 2 && $USE_COLOR != "n" ]] && check_buildenv "color" "y"; then + colorize +else + unset ALL_OFF BOLD BLUE GREEN RED YELLOW +fi + + +# check makepkg.conf for some basic requirements +lint_config || exit $E_CONFIG_ERROR + + +# check that all settings directories are user-writable +if ! ensure_writable_dir "BUILDDIR" "$BUILDDIR"; then + plain "$(gettext "Aborting...")" + exit $E_FS_PERMISSIONS +fi + +if (( ! (NOBUILD || GENINTEG) )) && ! ensure_writable_dir "PKGDEST" "$PKGDEST"; then + plain "$(gettext "Aborting...")" + exit $E_FS_PERMISSIONS +fi + +if ! ensure_writable_dir "SRCDEST" "$SRCDEST" ; then + plain "$(gettext "Aborting...")" + exit $E_FS_PERMISSIONS +fi + +if (( SOURCEONLY )); then + if ! ensure_writable_dir "SRCPKGDEST" "$SRCPKGDEST"; then + plain "$(gettext "Aborting...")" + exit $E_FS_PERMISSIONS + fi + + # If we're only making a source tarball, then we need to ignore architecture- + # dependent behavior. + IGNOREARCH=1 +fi + +if (( LOGGING )) && ! ensure_writable_dir "LOGDEST" "$LOGDEST"; then + plain "$(gettext "Aborting...")" + exit $E_FS_PERMISSIONS +fi + +if (( ! INFAKEROOT )); then + if (( EUID == 0 )); then + error "$(gettext "Running %s as root is not allowed as it can cause permanent,\n\ +catastrophic damage to your system.")" "makepkg" + exit $E_ROOT + fi +else + if [[ -z $FAKEROOTKEY ]]; then + error "$(gettext "Do not use the %s option. This option is only for internal use by %s.")" "'-F'" "makepkg" + exit $E_INVALID_OPTION + fi +fi + +unset pkgname pkgbase pkgver pkgrel epoch pkgdesc url license groups provides +unset md5sums replaces depends conflicts backup source install changelog build +unset sha{1,224,256,384,512}sums makedepends optdepends options noextract validpgpkeys +unset "${!makedepends_@}" "${!depends_@}" "${!source_@}" "${!checkdepends_@}" +unset "${!optdepends_@}" "${!conflicts_@}" "${!provides_@}" "${!replaces_@}" +unset "${!md5sums_@}" "${!sha1sums_@}" "${!sha224sums_@}" "${!sha256sums_@}" +unset "${!sha384sums_@}" "${!sha512sums_@}" + +[[ -n ${REPOPACKAGE} ]] && get_repository_files + +BUILDFILE=${BUILDFILE:-$BUILDSCRIPT} +if [[ ! -f $BUILDFILE ]]; then + error "$(gettext "%s does not exist.")" "$BUILDFILE" + exit $E_USER_FUNCTION_FAILED + +else + if [[ $(<"$BUILDFILE") = *$'\r'* ]]; then + error "$(gettext "%s contains %s characters and cannot be sourced.")" "$BUILDFILE" "CRLF" + exit $E_PKGBUILD_ERROR + fi + + if [[ ! $BUILDFILE -ef $PWD/${BUILDFILE##*/} ]]; then + error "$(gettext "%s must be in the current working directory.")" "$BUILDFILE" + exit $E_PKGBUILD_ERROR + fi + + if [[ ${BUILDFILE:0:1} != "/" ]]; then + BUILDFILE="$startdir/$BUILDFILE" + fi + source_buildfile "$BUILDFILE" +fi + +if [[ -v ADDGROUP ]]; then + groups=(${groups[@]//$ADDGROUP}) + groups+=($ADDGROUP) + sed -i "s/^groups=.*//" "$BUILDFILE" + + printf 'groups=(' >> "$BUILDFILE" + printf " '%s' " "${groups[@]}" >> "$BUILDFILE" + printf ")" >> "$BUILDFILE" + msg "$(gettext "Package added into group %s in %s")" "'$ADDGROUP'" "$BUILDSCRIPT" +fi + +pkgbase=${pkgbase:-${pkgname[0]}} + +# check the PKGBUILD for some basic requirements +lint_pkgbuild || exit $E_PKGBUILD_ERROR + +if (( !SOURCEONLY && !PRINTSRCINFO )); then + merge_arch_attrs +fi + +basever=$(get_full_version) + +if [[ $BUILDDIR -ef "$startdir" ]]; then + srcdir="$BUILDDIR/src" + pkgdirbase="$BUILDDIR/pkg" +else + srcdir="$BUILDDIR/$pkgbase/src" + pkgdirbase="$BUILDDIR/$pkgbase/pkg" + +fi + +# set pkgdir to something "sensible" for (not recommended) use during build() +pkgdir="$pkgdirbase/$pkgbase" + +# TODO fix incorrect duplicate functionality +if (( GENINTEG )); then + mkdir -p "$srcdir" + chmod a-s "$srcdir" + cd_safe "$srcdir" + download_sources novcs allarch + generate_checksums + msg "$(gettext "Update your $BUILDSCRIPT")" + exit $E_OK +fi + +if have_function pkgver; then + PKGVERFUNC=1 +fi + +# check we have the software required to process the PKGBUILD +check_software || exit $E_MISSING_MAKEPKG_DEPS + +if (( ${#pkgname[@]} > 1 )); then + SPLITPKG=1 +fi + +# test for available PKGBUILD functions +if have_function prepare; then + # "Hide" prepare() function if not going to be run + if [[ $RUN_PREPARE != "n" ]]; then + PREPAREFUNC=1 + fi +fi +if have_function build; then + BUILDFUNC=1 +fi +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 have_function package; then + PKGFUNC=1 +elif [[ $SPLITPKG -eq 0 ]] && have_function package_${pkgname}; then + SPLITPKG=1 +fi + +# check if gpg signature is to be created and if signing key is valid +if { [[ -z $SIGNPKG ]] && check_buildenv "sign" "y"; } || [[ $SIGNPKG == 'y' ]]; then + SIGNPKG='y' + if ! gpg --list-key ${GPGKEY} &>/dev/null; then + if [[ ! -z $GPGKEY ]]; then + error "$(gettext "The key %s does not exist in your keyring.")" "${GPGKEY}" + else + error "$(gettext "There is no key in your keyring.")" + fi + exit $E_PRETTY_BAD_PRIVACY + fi +fi + +if (( PACKAGELIST )); then + print_all_package_names + exit $E_OK +fi + +if (( PRINTSRCINFO )); then + write_srcinfo_content + exit $E_OK +fi + +if (( ! PKGVERFUNC )); then + check_build_status +fi + +# Run the bare minimum in fakeroot +if (( INFAKEROOT )); then + if (( SOURCEONLY )); then + create_srcpackage + msg "$(gettext "Leaving %s environment.")" "fakeroot" + exit $E_OK + fi + + prepare_buildenv + + chmod 755 "$pkgdirbase" + if (( ! SPLITPKG )); then + pkgdir="$pkgdirbase/$pkgname" + mkdir "$pkgdir" + if (( PKGFUNC )); then + run_package + fi + tidy_install + lint_package || exit $E_PACKAGE_FAILED + create_package + create_debug_package + else + run_split_packaging + fi + + msg "$(gettext "Leaving %s environment.")" "fakeroot" + exit $E_OK +fi + +msg "$(gettext "Making package: %s")" "$pkgbase $basever ($(date +%c))" + +# if we are creating a source-only package, go no further +if (( SOURCEONLY )); then + if [[ -f $SRCPKGDEST/${pkgbase}-${basever}${SRCEXT} ]] \ + && (( ! FORCE )); then + error "$(gettext "A source package has already been built. (use %s to overwrite)")" "-f" + exit $E_ALREADY_BUILT + fi + + # Get back to our src directory so we can begin with sources. + mkdir -p "$srcdir" + chmod a-s "$srcdir" + cd_safe "$srcdir" + if (( SOURCEONLY == 2 )); then + download_sources allarch + elif ( (( ! SKIPCHECKSUMS )) || \ + ( (( ! SKIPPGPCHECK )) && source_has_signatures ) ); then + download_sources allarch novcs + fi + check_source_integrity all + cd_safe "$startdir" + + enter_fakeroot + + if [[ $SIGNPKG = 'y' ]]; then + msg "$(gettext "Signing package...")" + create_signature "$SRCPKGDEST/${pkgbase}-${fullver}${SRCEXT}" + fi + + msg "$(gettext "Source package created: %s")" "$pkgbase ($(date +%c))" + exit $E_OK +fi + +# get back to our src directory so we can begin with sources +mkdir -p "$srcdir" +chmod a-s "$srcdir" +cd_safe "$srcdir" + +if (( !REPKG )); then + if (( NOEXTRACT && ! VERIFYSOURCE )); then + warning "$(gettext "Using existing %s tree")" "\$srcdir/" + else + + download_sources + + if (( UPDPKGSUMS )); then + if type -p updpkgsums >/dev/null; then + updpkgsums "${startdir}/${BUILDSCRIPT}" + exit + else + error "$(gettext "Missing updpkgsums executable. Couldn't update checksums.")" + exit 1 + fi + fi + + check_source_integrity all + (( VERIFYSOURCE )) && exit $E_OK + + if (( CLEANBUILD )); then + msg "$(gettext "Removing existing %s directory...")" "\$srcdir/" + rm -rf "$srcdir"/* + fi + + extract_sources + if (( PREPAREFUNC )); then + run_prepare + fi + if (( REPRODUCIBLE )); then + # We have activated reproducible builds, so unify source times before + # building + find "$srcdir" -exec touch -h -d @$SOURCE_DATE_EPOCH {} + + fi + fi + + if (( PKGVERFUNC )); then + update_pkgver + basever=$(get_full_version) + check_build_status + fi +fi + +if (( NODEPS || ( VERIFYSOURCE && !DEP_BIN ) )); then + if (( NODEPS )); then + warning "$(gettext "Skipping dependency checks.")" + fi +else + if (( RMDEPS && ! INSTALL )); then + original_pkglist=($(run_pacman -Qq)) # required by remove_dep + fi + deperr=0 + + msg "$(gettext "Checking runtime dependencies...")" + resolve_deps runtime "${depends[@]}" || deperr=1 + + if (( RMDEPS && INSTALL )); then + original_pkglist=($(run_pacman -Qq)) # required by remove_dep + fi + + msg "$(gettext "Checking buildtime dependencies...")" + if (( CHECKFUNC )); then + resolve_deps buildtime "${makedepends[@]}" "${checkdepends[@]}" || deperr=1 + else + resolve_deps buildtime "${makedepends[@]}" || deperr=1 + fi + + [[ -n $runtime_depsall ]] && ask_missingdeps $runtime_depsall + [[ -n $buildtime_depsall ]] && ask_missingdeps $buildtime_depsall + + if (( RMDEPS )); then + current_pkglist=($(run_pacman -Qq)) # required by remove_deps + fi + + if (( deperr )); then + error "$(gettext "Could not resolve all dependencies.")" + exit $E_INSTALL_DEPS_FAILED + fi +fi + +if (( NOBUILD )); then + msg "$(gettext "Sources are ready.")" + exit $E_OK +else + # clean existing pkg directory + if [[ -d $pkgdirbase ]]; then + msg "$(gettext "Removing existing %s directory...")" "\$pkgdir/" + rm -rf "$pkgdirbase" + fi + mkdir -p "$pkgdirbase" + chmod a-srw "$pkgdirbase" + cd_safe "$startdir" + + prepare_buildenv + + if (( ! REPKG )); then + (( BUILDFUNC )) && run_build + (( CHECKFUNC )) && run_check + cd_safe "$startdir" + fi + + enter_fakeroot + + create_package_signatures +fi + + +if [[ ${runtime_depsall} ]]; then + msg "$(gettext "Runtime dependencies installed in prior to compilation:")" + msg2 "$runtime_depsall" +fi + +if [[ ${buildtime_depsall} ]]; then + msg "$(gettext "Buildtime dependencies installed in prior to compilation:")" + msg2 "$buildtime_depsall" + + if [[ $RMDEPS == 0 ]];then + if [[ $RMBUILDDEPS == 0 ]]; then + msg "$(gettext "Do you want to remove the buildtime dependencies? [Y/n]")" + read response + else + response=y + fi + + if [[ $(echo $response) =~ ^([yY][eE][sS]|[yY])$ ]]; then + msg "$(gettext "Removing installed buildtime dependencies...")" + echo "${buildtime_depsall}" + run_pacman -Rs ${buildtime_depsall} + fi + fi + +fi + +# if inhibiting archive creation, go no further +if (( NOARCHIVE )); then + msg "$(gettext "Package directory is ready.")" + exit $E_OK +fi + +msg "$(gettext "Finished making: %s")" "$pkgbase $basever ($(date +%c))" + +install_package && exit $E_OK || exit $E_INSTALL_FAILED diff --git a/pacman/usr/local/bin/pacman b/pacman/usr/local/bin/pacman new file mode 100755 index 0000000..359bd28 --- /dev/null +++ b/pacman/usr/local/bin/pacman @@ -0,0 +1,7 @@ +#!/bin/env bash + +source /usr/local/bin/pacmankeycheck.sh + +keyringcheck + +/usr/bin/pacman ${@:1} diff --git a/pacman/usr/local/bin/pacmankeycheck.sh b/pacman/usr/local/bin/pacmankeycheck.sh new file mode 100644 index 0000000..24b7da5 --- /dev/null +++ b/pacman/usr/local/bin/pacmankeycheck.sh @@ -0,0 +1,64 @@ +#!/bin/env bash +# +# pacmankeycheck - Check age of Pacman PGP/GPG public key ring files and update if wanted +# +# Copyright (C) 2021 Pekka Helenius +# +# 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 . + +LIBRARY=${LIBRARY:-'/usr/share/makepkg'} + +source "$LIBRARY/util/message.sh" +source "$LIBRARY/util/pkgbuild.sh" + +colorize + +function keyringcheck() { + keyfilepath="/etc/pacman.d/gnupg" + + keyfiles=( + 'pubring.gpg' + # 'secring.gpg' + 'trustdb.gpg' + ) + + # Deadline in days + deadline=30 + + expiredkeys=0 + deadlineseconds=$(($deadline * 24 * 60 * 60)) + + for i in ${keyfiles[@]}; do + + file="${keyfilepath}/${i}" + age=$(( $(date "+%s") - $(stat -c %Z "${file}") )) + lastupdated=$(date --date=@$(stat -c %Z "${file}")) + + if [[ $age -gt $deadlineseconds ]]; then + expiredkeys=1 + warning "$(gettext "Pacman PGP/GPG public key ring file %s is over %s days old. Last updated: %s")" "${i}" "${deadline}" "${lastupdated}" + fi + + done + + if [[ $expiredkeys -eq 1 ]]; then + msg "$(gettext "Outdated pacman public key ring files may cause issues on package installations.")" + msg "$(gettext "Do you wish to update the pacman key ring files before proceeding with the pacman command? [Y/n]")" + read response + + if [[ $(echo $response) =~ ^([yY][eE][sS]|[yY])$ ]]; then + su root -c 'pacman-key --populate archlinux; pacman-key --refresh' + fi + fi +} diff --git a/pacman/usr/share/makepkg/source.sh b/pacman/usr/share/makepkg/source.sh new file mode 100755 index 0000000..05c31c9 --- /dev/null +++ b/pacman/usr/share/makepkg/source.sh @@ -0,0 +1,113 @@ +#!/usr/bin/bash +# +# source.sh - functions for downloading and extracting sources +# +# Copyright (c) 2015-2018 Pacman Development Team +# +# 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 . +# + +[[ -n "$LIBMAKEPKG_SOURCE_SH" ]] && return +LIBMAKEPKG_SOURCE_SH=1 + +LIBRARY=${LIBRARY:-'/usr/share/makepkg'} + +source "$LIBRARY/util/message.sh" +source "$LIBRARY/util/pkgbuild.sh" +source "$LIBRARY/util/source.sh" + + +for lib in "$LIBRARY/source/"*.sh; do + source "$lib" +done + + +download_sources() { + local netfile all_sources + local get_source_fn=get_all_sources_for_arch get_vcs=1 + + msg "$(gettext "Retrieving sources...")" + + while true; do + case $1 in + allarch) + get_source_fn=get_all_sources + ;; + novcs) + get_vcs=0 + ;; + *) + break + ;; + esac + shift + done + + "$get_source_fn" 'all_sources' + for netfile in "${all_sources[@]}"; do + pushd "$SRCDEST" &>/dev/null + + local proto=$(get_protocol "$netfile") + case "$proto" in + local) + download_local "$netfile" + ;; + bzr*) + (( get_vcs )) && download_bzr "$netfile" + ;; + git*) + (( get_vcs )) && download_git "$netfile" "--depth" "1" + ;; + hg*) + (( get_vcs )) && download_hg "$netfile" + ;; + svn*) + (( get_vcs )) && download_svn "$netfile" + ;; + *) + download_file "$netfile" + ;; + esac + + popd &>/dev/null + done +} + +extract_sources() { + msg "$(gettext "Extracting sources...")" + local netfile all_sources + + get_all_sources_for_arch 'all_sources' + for netfile in "${all_sources[@]}"; do + local file=$(get_filename "$netfile") + local proto=$(get_protocol "$netfile") + case "$proto" in + bzr*) + extract_bzr "$netfile" + ;; + git*) + extract_git "$netfile" + ;; + hg*) + extract_hg "$netfile" + ;; + svn*) + extract_svn "$netfile" + ;; + *) + extract_file "$file" + ;; + esac + done +} diff --git a/pacman/usr/share/makepkg/source/git.sh b/pacman/usr/share/makepkg/source/git.sh new file mode 100755 index 0000000..70f8c87 --- /dev/null +++ b/pacman/usr/share/makepkg/source/git.sh @@ -0,0 +1,138 @@ +#!/usr/bin/bash +# +# git.sh - function for handling the download and "extraction" of Git sources +# +# Copyright (c) 2015-2018 Pacman Development Team +# +# 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 . +# + +[[ -n "$LIBMAKEPKG_SOURCE_GIT_SH" ]] && return +LIBMAKEPKG_SOURCE_GIT_SH=1 + + +LIBRARY=${LIBRARY:-'/usr/share/makepkg'} + +source "$LIBRARY/util/message.sh" +source "$LIBRARY/util/pkgbuild.sh" + + +download_git() { + local netfile=$1 + + local options=${@:2} + + local dir=$(get_filepath "$netfile") + [[ -z "$dir" ]] && dir="$SRCDEST/$(get_filename "$netfile")" + + local repo=$(get_filename "$netfile") + + local url=$(get_url "$netfile") + url=${url#git+} + url=${url%%#*} + url=${url%%\?*} + + if [[ ! -d "$dir" ]] || dir_is_empty "$dir" ; then + if [[ ${options[@]} ]]; then + msg2 "$(gettext "Cloning %s %s repo (params: %s)...")" "${repo}" "git" "${options[*]}" + else + msg2 "$(gettext "Cloning %s %s repo...")" "${repo}" "git" + fi + if ! git clone ${options[*]} --mirror "$url" "$dir"; then + error "$(gettext "Failure while downloading %s %s repo")" "${repo}" "git" + plain "$(gettext "Aborting...")" + exit 1 + fi + elif (( ! HOLDVER )); then + cd_safe "$dir" + # Make sure we are fetching the right repo + if [[ "$url" != "$(git config --get remote.origin.url)" ]] ; then + error "$(gettext "%s is not a clone of %s")" "$dir" "$url" + plain "$(gettext "Aborting...")" + exit 1 + fi + msg2 "$(gettext "Updating %s %s repo...")" "${repo}" "git" + if ! git fetch --all -p; then + # only warn on failure to allow offline builds + warning "$(gettext "Failure while updating %s %s repo")" "${repo}" "git" + fi + fi +} + +extract_git() { + local netfile=$1 tagname + + local fragment=$(get_uri_fragment "$netfile") + local repo=$(get_filename "$netfile") + + local dir=$(get_filepath "$netfile") + [[ -z "$dir" ]] && dir="$SRCDEST/$(get_filename "$netfile")" + + msg2 "$(gettext "Creating working copy of %s %s repo...")" "${repo}" "git" + pushd "$srcdir" &>/dev/null + + local updating=0 + if [[ -d "${dir##*/}" ]]; then + updating=1 + cd_safe "${dir##*/}" + if ! git fetch; then + error "$(gettext "Failure while updating working copy of %s %s repo")" "${repo}" "git" + plain "$(gettext "Aborting...")" + exit 1 + fi + cd_safe "$srcdir" + echo "${dir##*/}" + elif ! git clone "$dir" "${dir##*/}"; then + error "$(gettext "Failure while creating working copy of %s %s repo")" "${repo}" "git" + plain "$(gettext "Aborting...")" + exit 1 + fi + + cd_safe "${dir##*/}" + + local ref=origin/HEAD + if [[ -n $fragment ]]; then + case ${fragment%%=*} in + commit|tag) + ref=${fragment##*=} + ;; + branch) + ref=origin/${fragment##*=} + ;; + *) + error "$(gettext "Unrecognized reference: %s")" "${fragment}" + plain "$(gettext "Aborting...")" + exit 1 + esac + fi + + if [[ ${fragment%%=*} = tag ]]; then + tagname="$(git tag -l --format='%(tag)' "$ref")" + if [[ -n $tagname && $tagname != $ref ]]; then + error "$(gettext "Failure while checking out version %s, the git tag has been forged")" "$ref" + plain "$(gettext "Aborting...")" + exit 1 + fi + fi + + if [[ $ref != "origin/HEAD" ]] || (( updating )) ; then + if ! git checkout --force --no-track -B makepkg $ref; then + error "$(gettext "Failure while creating working copy of %s %s repo")" "${repo}" "git" + plain "$(gettext "Aborting...")" + exit 1 + fi + fi + + popd &>/dev/null +}