summaryrefslogtreecommitdiff
path: root/src/librefetch/librefetch
diff options
context:
space:
mode:
Diffstat (limited to 'src/librefetch/librefetch')
-rwxr-xr-xsrc/librefetch/librefetch400
1 files changed, 400 insertions, 0 deletions
diff --git a/src/librefetch/librefetch b/src/librefetch/librefetch
new file mode 100755
index 0000000..2b8af61
--- /dev/null
+++ b/src/librefetch/librefetch
@@ -0,0 +1,400 @@
+#!/usr/bin/env bash
+# librefetch
+#
+# Copyright (C) 2013-2016 Luke Shumaker <lukeshu@sbcglobal.net>
+#
+# For just the create_signature() function:
+# Copyright (C) 2006-2013 Pacman Development Team <pacman-dev@archlinux.org>
+# Copyright (C) 2002-2006 Judd Vinet <jvinet@zeroflux.org>
+# Copyright (C) 2005 Aurelien Foret <orelien@chez.com>
+# Copyright (C) 2006 Miklos Vajna <vmiklos@frugalware.org>
+# Copyright (C) 2005 Christian Hamar <krics@linuxforum.hu>
+# Copyright (C) 2006 Alex Smith <alex@alex-smith.me.uk>
+# Copyright (C) 2006 Andras Voroskoi <voroskoi@frugalware.org>
+#
+# License: GNU GPLv3+
+#
+# This file is part of LibreFetch.
+#
+# LibreFetch 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 3 of the License, or
+# (at your option) any later version.
+#
+# LibreFetch 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 LibreFetch. If not, see <http://www.gnu.org/licenses/>.
+
+# create_signature() is taken from pacman:makepkg, which is GPLv2+,
+# so we take the '+' to combine it with our GPLv3+.
+
+. "$(librelib conf)"
+. "$(librelib messages)"
+setup_traps
+
+tmpfiles=()
+tmpdirs=()
+trap 'rm -f -- "${tmpfiles[@]}"; rm -rf -- "${tmpdirs[@]}"' EXIT
+
+cmd=${0##*/}
+usage() {
+ print "Usage: %s [OPTIONS] SOURCE_URL [OUTPUT_FILE]" "$cmd"
+ print "Usage: %s -[g|S|M|h]" "$cmd"
+ print "Downloads or creates a liberated source tarball."
+ echo
+ prose "The default mode is to create OUTPUT_FILE, first by trying
+ download mode, then create mode."
+ echo
+ prose "If OUTPUT_FILE isn't specified, it defaults to the non-directory
+ part of SOURCE_URL, in the current directory."
+ echo
+ prose "Unless '-C' is specified, if SOURCE_URL does not begin with a
+ configured mirror, create mode is inhibited."
+ echo
+ prose "In download mode, it simply tries to download SOURCE_URL. At the
+ beginning of a URL, 'libre://' expands to the first configured
+ mirror."
+ echo
+ prose "In create mode, it either looks at a build script and uses that
+ to create the source tarball, or it uses GPG to create a
+ signature (if OUTPUT_FILE ends with \`.sig\` or \`.sig.part\`).
+ If it is using GPG to create a signature, but the file that it is
+ trying to sign doesn't exist yet, it recurses on itself to first
+ create that file. SOURCE_URL is ignored, except that it is used
+ to set the default value of OUTPUT_FILE, and that it may be used
+ when recursing."
+ echo
+ prose "The default build script is 'PKGBUILD', or 'SRCBUILD' if it
+ exists."
+ echo
+ prose "Other options, if they are valid \`makepkg\` options, are passed
+ straight to makepkg."
+ echo
+ print "Example usage:"
+ print ' $ %s https://repo.parabola.nu/other/mypackage/mypackage-1.0.tar.gz' "$cmd"
+ echo
+ print "Options:"
+ flag 'Settings:' \
+ "-C" "Force create mode (don't download)" \
+ "-D" "Force download mode (don't create)" \
+ "-p <$(_ FILE)>" "Use an alternate build script (instead of
+ 'PKGBUILD'). If an SRCBUILD exists in the same
+ directory, it is used instead" \
+ 'Alternate modes:' \
+ "-g, --geninteg" "Generate integrity checks for source files" \
+ "-S, --srcbuild" "Print the effective build script (SRCBUILD)" \
+ "-M, --makepkg" "Generate and print the location of the
+ effective makepkg script" \
+ "-h, --help" "Show this message"
+}
+
+main() {
+ BUILDFILE="$(realpath -Lm PKGBUILD)"
+ makepkg_opts=()
+ extra_opts=()
+ mode=download-create
+ if ! parse_options "$@"; then
+ usage >&2
+ exit 1
+ fi
+
+ doit
+}
+
+doit() {
+ # Mode: help ###########################################################
+
+ if [[ $mode =~ help ]]; then
+ usage
+ exit 0
+ fi
+
+ ########################################################################
+
+ makepkg="$(modified_makepkg)"
+
+ # Mode: makepkg ########################################################
+
+ if [[ $mode =~ makepkg ]]; then
+ printf '%s\n' "$makepkg"
+ exit 0
+ else
+ tmpdirs+=("${makepkg%/*}")
+ fi
+
+ ########################################################################
+
+ local BUILDFILEDIR="${BUILDFILE%/*}"
+ if [[ -f "${BUILDFILEDIR}/SRCBUILD" ]]; then
+ BUILDFILE="${BUILDFILEDIR}/SRCBUILD"
+ fi
+ if [[ ! -f "$BUILDFILE" ]]; then
+ error "%s does not exist." "$BUILDFILE"
+ exit 1
+ fi
+ case "$BUILDFILE" in
+ */SRCBUILD) srcbuild="$(modified_srcbuild "$BUILDFILE")";;
+ *) srcbuild="$(modified_pkgbuild "$BUILDFILE")";;
+ esac
+ tmpfiles+=("$srcbuild")
+
+ # Mode: checksums ######################################################
+
+ if [[ $mode =~ checksums ]]; then
+ "$makepkg" "${makepkg_opts[@]}" -g -p "$srcbuild" |
+ case ${BUILDFILE##*/} in
+ PKGBUILD) sed -e 's/^[a-z]/mk&/' -e 's/^\s/ &/';;
+ SRCBUILD) cat;;
+ esac
+ exit 0
+ fi
+
+ # Mode: srcbuild #######################################################
+
+ if [[ $mode =~ srcbuild ]]; then
+ cat "$srcbuild"
+ exit 0
+ fi
+
+ ########################################################################
+
+ local src="${extra_opts[0]}"
+ local dst="${extra_opts[1]:-${src##*/}}"
+
+ # Don't canonicalize $src unless mode =~ download, and we've validated
+ # that $MIRRORS is configured.
+
+ # Canonicalize $dst
+ dst="$(realpath -Lm -- "$dst")"
+
+ # Mode: download #######################################################
+
+ if [[ $mode =~ download ]]; then
+ load_files librefetch
+ check_vars librefetch MIRRORS DOWNLOADER || exit 1
+
+ # Canonicalize $src
+ if [[ "$src" == libre://* ]]; then
+ src="${MIRRORS[0]}/${src#libre://}"
+ fi
+
+ # check to see if $src is a candidate for create mode
+ local inmirror=false;
+ local mirror
+ for mirror in "${MIRRORS[@]}"; do
+ if [[ "$src" == "$mirror"* ]]; then
+ inmirror=true
+ break
+ fi
+ done
+ if ! $inmirror; then
+ # inhibit create
+ mode=download
+ fi
+
+ local dlcmd="${DOWNLOADER}"
+ [[ $dlcmd = *%u* ]] || dlcmd="$dlcmd %u"
+ dlcmd="${dlcmd//\%o/\"\$dst\"}"
+ dlcmd="${dlcmd//\%u/\"\$src\"}"
+
+ { eval "$dlcmd"; } >&2 && exit 0
+ fi
+
+ # Mode: create #########################################################
+
+ if [[ $mode =~ create ]]; then
+ local base_dst=${dst%.part}
+ local suffix=${dst#"$base_dst"}
+
+ if [[ $base_dst == *.sig ]]; then
+ if ! [[ -e $base_dst ]]; then
+ extra_opts=("${src%.sig}" "${base_dst%.sig}")
+ doit || exit $?
+ fi
+ create_signature "${base_dst%.sig}" || exit $?
+ if [[ -n $suffix ]]; then
+ mv -f "$base_dst" "$dst"
+ fi
+ else
+ export PKGEXT=${base_dst##*/}
+ export PKGDEST=${dst%/*}
+ export pkg_file=$dst
+
+ cd "$BUILDFILEDIR"
+ "$makepkg" "${makepkg_opts[@]}" -p "$srcbuild" >&2 || exit $?
+ fi
+ fi
+}
+
+# sets the variables BUILDFILE, makepkg_opts, extra_opts, mode
+parse_options() {
+ declare -i ret=0
+ local {shrt,long}{1,2}
+
+ # makepkg options
+ local makepkg_orig="$(which makepkg)"
+ shrt1=($(LC_ALL=C "${makepkg_orig}" -h | sed -rn 's/^ +-(.)(,| [^<]).*/\1/p'))
+ shrt2=($(LC_ALL=C "${makepkg_orig}" -h | sed -rn 's/^ +-(.) <.*/\1/p'))
+ long1=($(LC_ALL=C "${makepkg_orig}" -h | sed -rn -e 's/^ +(-., )?--(\S*) [^<].*/\2/p'))
+ long2=($(LC_ALL=C "${makepkg_orig}" -h | sed -rn 's/^ +--(\S*) <.*/\1/p'))
+
+ # librefetch options
+ shrt1+=(C D g S M h)
+ shrt2+=(p)
+ long1+=(geninteg srcbuild makepkg help)
+ long2+=()
+
+ # Feed the options through getopt (sanitize them)
+ local shrt="$({ printf '%s\0' "${shrt1[@]}"; printf '%s:\0' "${shrt2[@]}"; } | sort -zu | xargs -0 printf '%s')"
+ local long="$({ printf '%s\0' "${long1[@]}"; printf '%s:\0' "${long2[@]}"; } | sort -zu | xargs -0 printf '%s,')"
+ local args="$(getopt -n "$cmd" -o "$shrt" -l "${long%,}" -- "$@")"
+ ret=$?
+ eval set -- "$args"
+ unset shrt long args
+
+ # Parse the options.
+ local opt optarg have_optarg
+ while [[ $# -gt 0 ]]; do
+ opt=$1; shift
+ have_optarg=false
+
+ if { [[ $opt == --?* ]] && in_array "${opt#--}" "${long2[@]}"; } \
+ || { [[ $opt == -? ]] && in_array "${opt#-}" "${shrt2[@]}"; }
+ then
+ optarg=$1; shift
+ have_optarg=true
+ fi
+
+ case "$opt" in
+ -C) mode=create;;
+ -D) mode=download;;
+ -g|--geninteg) mode=checksums;;
+ -S|--srcbuild) mode=srcbuild;;
+ -M|--makepkg) mode=makepkg;;
+ -p) BUILDFILE="$(realpath -Lm -- "$optarg")";;
+ -h|--help) mode=help;;
+ --) break;;
+ *)
+ makepkg_opts+=("$opt")
+ if $have_optarg; then makepkg_opts+=("$optarg"); fi
+ ;;
+ esac
+ done
+ extra_opts+=("$@")
+
+ # check the number of extra_opts
+ case "$mode" in
+ help) # don't worry about it
+ :;;
+ checksums|srcbuild|makepkg) # don't take any extra arguments
+ if [[ ${#extra_opts[@]} != 0 ]]; then
+ print "%s: found extra non-flag arguments: %s" "$cmd" "${extra_opts[*]}" >&2
+ ret=1
+ fi
+ ;;
+ *download*|*create*) # take 1 or 2 extra arguments
+ if [[ ${#extra_opts[@]} != 1 ]] && [[ ${#extra_opts[@]} != 2 ]]; then
+ print "%s: %d non-flag arguments found, expected 1 or 2: %s" "$cmd" ${#extra_opts[@]} >&2
+ ret=1
+ fi
+ ;;
+ esac
+
+ return $ret
+}
+
+# Modify makepkg ###############################################################
+
+modified_makepkg() {
+ local dir="$(mktemp --tmpdir --directory "${cmd}.XXXXXXXXXXX.makepkg")"
+ make -s -f "$(librelib librefetchdir/Makefile)" new="$dir"
+ realpath -es "$dir/makepkg"
+}
+
+# Modify PKGBUILD ##############################################################
+
+# a string to be appended
+pkgbuild_append='
+# do not do split packages
+if [[ ${#pkgname[@]} -gt 1 ]]; then
+ if [[ -n $pkgbase ]]; then
+ pkgname=("$pkgbase")
+ else
+ pkgname=("$pkgname")
+ fi
+fi
+
+# copy source variables
+source=("${mksource[@]}") ; unset "source_${CARCH}"
+noextract=("${mknoextract[@]}")
+
+declare algo
+for algo in "${known_hash_algos[@]}"; do
+ eval "${algo}sums=(\"\${mk${algo}sums[@]}\")"
+ unset "${algo}sums_${CARCH}"
+done
+
+depends=() ; unset "depends_${CARCH}"
+checkdepends=() ; unset "checkdepends_${CARCH}"
+makedepends=("${mkdepends[@]}") ; unset "makedepends_${CARCH}"
+
+####
+options=(!strip docs libtool staticlibs emptydirs !zipman purge !upx !optipng !debug)
+PURGE_TARGETS=(.bzr/ .cvs/ .git/ .hg/ .svn/ .makepkg/)
+
+####
+if ! declare -f mksource >/dev/null; then
+ mksource() { :; }
+fi
+prepare() { :; }
+build() { mksource; }
+check() { :; }
+package() { cp -a "$srcdir"/*/ "$pkgdir/"; }
+'
+
+modified_pkgbuild() {
+ local pkgbuild=$1
+ local srcbuild="$(mktemp "${pkgbuild%/*}/${cmd}.XXXXXXXXXXX.PKGBUILD.to.SRCBUILD")"
+ printf '%s' "$pkgbuild_append" | cat "$pkgbuild" - > "$srcbuild"
+ printf '%s\n' "$srcbuild"
+}
+
+
+# Modify SRCBUILD ##############################################################
+
+modified_srcbuild() {
+ local orig=$1
+ local srcbuild="$(mktemp "${orig%/*}/${cmd}.XXXXXXXXXXX.SRCBUILD.to.SRCBUILD")"
+ sed -e '/PKGDEST=/d' -e '/PKGEXT=/d' < "$orig" > "$new"
+ printf '%s\n' "$new"
+}
+
+################################################################################
+
+# This function is taken almost verbatim from makepkg
+create_signature() {
+ local ret=0
+ local filename="$1"
+ msg "Signing package..."
+
+ local SIGNWITHKEY=()
+ if [[ -n $GPGKEY ]]; then
+ SIGNWITHKEY=(-u "${GPGKEY}")
+ fi
+
+ gpg --detach-sign --use-agent "${SIGNWITHKEY[@]}" --no-armor "$filename" &>/dev/null || ret=$?
+
+
+ if (( ! ret )); then
+ msg2 "Created signature file %s." "$filename.sig"
+ else
+ error "Failed to sign package file."
+ return $ret
+ fi
+}
+
+main "$@"