diff options
Diffstat (limited to 'src/librefetch')
-rw-r--r-- | src/librefetch/Makefile | 1 | ||||
-rwxr-xr-x | src/librefetch/librefetch | 331 | ||||
-rw-r--r-- | src/librefetch/librefetch.8.ronn | 162 | ||||
-rw-r--r-- | src/librefetch/librefetch.conf | 2 | ||||
-rw-r--r-- | src/librefetch/librefetch.conf.5.ronn | 36 |
5 files changed, 532 insertions, 0 deletions
diff --git a/src/librefetch/Makefile b/src/librefetch/Makefile new file mode 100644 index 0000000..2c76089 --- /dev/null +++ b/src/librefetch/Makefile @@ -0,0 +1 @@ +include ../../common.mk diff --git a/src/librefetch/librefetch b/src/librefetch/librefetch new file mode 100755 index 0000000..086a5e9 --- /dev/null +++ b/src/librefetch/librefetch @@ -0,0 +1,331 @@ +#!/usr/bin/env bash +# librefetch +# +# Copyright 2013 Luke Shumaker <lukeshu@sbcglobal.net> +# +# This file is part of Parabola. +# +# Parabola 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. +# +# Parabola 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 Parabola. If not, see <http://www.gnu.org/licenses/>. + +. $(librelib conf.sh) +. libremessages + +declare -r tempdir="$(mktemp -d --tmpdir ${0##*/}.XXXXXXXXXXX)" +cleanup() { rm -rf -- "$tempdir"; } +trap cleanup EXIT + +cmd=${0##*/} +usage() { + print "Usage: %s [options] <source-url> [<output-file>]" "$cmd" + print "Usage: %s -[g|P|V|h]" "$cmd" + print "Downloads or creates a liberated source tarball." + echo + print "The default mode is to create <output-file>, first by trying download" + print "mode, then create mode." + echo + print "If <output-file> isn't specified, it defaults to the non-directory" + print "part of <source-url>, in the current directory." + echo + print "In download mode, the glob '*://' is stripped from the beginning of" + print "<source-url>, and the resulting path is attempted to be downloaded" + print "from the configured mirror." + echo + print "In create mode, it looks at a build script, and uses that to create" + print "the source tarball. <source-url> is ignored, except that it is used" + print "to set the default value of <output-file>." + echo + print "The default build script is 'PKGBUILD', or 'SRCBUILD' if it exists." + echo + print "Unrecognized options are passed straight to makepkg." + echo + print "Example usage:" + print ' $ %s libre://mypackage-1.0.tar.gz' "$cmd" + echo + print "Options:" + print " Settings:" + print " -C Force create mode (don't download)" + print " -D Force download mode (don't create)" + print " -p <file> Use an alternate build script (instead of 'PKGBUILD')" + print " If an SRCBUILD exists in the same directory, it is used" + print " instead" + print " Alternate modes:" + print " -g, --geninteg Generage integrity checks for source files" + print " -P, --print Print the effective build script (SRCBUILD)" + print " -V, --version Show version information" + print " -h, --help Show this message" +} + +version() { + print "librefetch (libretools) beta 4" + echo + print "Copyright (C) 2013 Luke Shumaksr <lukeshu@sbcglobal.net>" + print "This is free software; see the source for copying conditions." + print "There is NO WARRANTY, to the extent permitted by law." +} + +main() { + BUILDFILE="$(readlink -m PKGBUILD)" + makepkg_opts=() + extra_opts=() + mode=download-create + parse_options "$@" + + # Mode: version, help ################################################## + + if [[ $mode =~ version ]]; then + version + return 0 + fi + if [[ $mode =~ help ]]; then + usage + return 0 + fi + + ######################################################################## + + local BUILDFILEDIR="${BUILDFILE%/*}" + if [[ -f "${BUILDFILEDIR}/SRCBUILD" ]]; then + BUILDFILE="${BUILDFILEDIR}/SRCBUILD" + srcbuild="$(modified_srcbuild "$BUILDFILE")" + else + srcbuild="$(modified_pkgbuild "$BUILDFILE")" + fi + makepkg="$(modified_makepkg "$(which makepkg)")" + + # Mode: checksums ###################################################### + + if [[ $mode =~ checksums ]]; then + if [[ ${#extra_opts[@]} != 0 ]]; then + print "%s: found extra non-flag arguments: %s" "$cmd" "${extra_opts[*]}" >> /dev/stderr + usage >> /dev/stderr + return 1 + fi + "$makepkg" "${makepkg_opts[@]}" -g -p "$srcbuild" | + case ${BUILDFILE##*/} in + PKGBUILD) sed -e 's/^[a-z]/mk&/' -e 's/^\s/ &/';; + SRCBUILD) cat;; + esac + return 0 + fi + + # Mode: print ########################################################## + + if [[ $mode =~ print ]]; then + if [[ ${#extra_opts[@]} != 0 ]]; then + print "%s: found extra non-flag arguments: %s" "$cmd" "${extra_opts[*]}" >> /dev/stderr + usage >> /dev/stderr + return 1 + fi + cat "$srcbuild" + return 0 + fi + + ######################################################################## + + local src dst + case ${#extra_opts[@]} in + 1) + src="${extra_opts[0]#*://}" + dst="$(readlink -m -- "${src##*/}")" + ;; + 2) + src="${extra_opts[0]#*://}" + dst="$(readlink -m -- "${extra_opts[1]}")" + ;; + *) + print "%s: %d non-flag arguments found, expected 1 or 2: %s" "$cmd" ${#extra_opts[@]} >> /dev/stderr + usage >> /dev/stderr + return 1 + esac + + # Mode: download ####################################################### + + if [[ $mode =~ download ]]; then + load_files librefetch + check_vars librefetch MIRROR DOWNLOADER || return 1 + + local url="${MIRROR}/${src}" + + local dlcmd="${DOWNLOADER}" + dlcmd="${dlcmd//\%o/\"$dst\"}" + dlcmd="${dlcmd//\%u/\"$url\"}" + { eval "$dlcmd"; } >> /dev/stderr && return 0 + fi + + # Mode: create ######################################################### + + if [[ $mode =~ create ]]; then + PKGEXT=${dst##*/} + export PKGEXT=${PKGEXT%.part} + export PKGDEST=${dst%/*} + export pkg_file=$dst + + cd "$BUILDFILEDIR" + "$makepkg" "${makepkg_opts[@]}" -p "$srcbuild" >> /dev/stderr || return $? + fi +} + +# sets the variables BUILDFILE, makepkg_opts, extra_opts, mode +parse_options() { + # Detect makepkg options that take a second argument + local makepkg_orig="$(which "${MAKEPKG:-makepkg}")" + local makepkg_opt2long=($("${makepkg_orig}" -h | sed -rn 's/\s*(--\S*) <.*/\1/p')) + local makepkg_opt2short=($("${makepkg_orig}" -h | sed -rn 's/\s*(-.) <.*/\1/p')) + + local opt + local have_opt + while [[ $# -gt 0 ]]; do + arg=$1 + have_opt=false + if in_array "${arg%%=*}" "${makepkg_opt2long[@]}"; then + opt="${arg#*=}" + arg="${arg%%=*}" + have_opt=true + fi + if in_array "${arg}" "${makepkg_opt2short[@]}"; then + shift + opt=$1 + have_opt=true + fi + case "$arg" in + -C) mode=create;; + -D) mode=download;; + -g|--geninteg) mode=checksums;; + -P|--print) mode=print;; + -p) BUILDFILE="$(readlink -m -- "$opt")";; + -V|--version) mode=version;; + -h|--help) mode=help;; + -*) + makepkg_opts+=("$arg") + $have_opt && makepkg_opts+=("$opt") + ;; + --) shift; break;; + *) extra_opts+=("$arg");; + esac + shift + done + extra_opts+=("$@") +} + +# Modify makepkg ############################################################### + +# an ERE +makepkg_modify=' +/create_package\(\) \{/,/^\}$/ { + /pkg_file=/d # allow us to set pkg_file + s/"?\$\{comp_files\[@\]\}"?// # do not include .{PKGINFO,INSTALL,CHANGELOG} + s/bsdtar /&--format=ustar / # ustar, not pax + s/create_signature .*/&; return $?/ # do not procede to create symlinks +} + +/tidy_install\(\) \{/,/^\}$/ { + /for .*PURGE_TARGETS/itidy_install_purge + /for .*PURGE_TARGETS/,/done/d + /^\}$/ifind . -exec touch --date="1990-01-01 0:0:0 +0" {} + +} + +s|srcdir=.*|&-libre| +s|pkgdirbase=.*|&-libre| +s|check_build_status$|:| +' + +tidy_install_purge() { + local pt + for pt in "${PURGE_TARGETS[@]}"; do + if [[ ${pt} = "${pt%/}" ]]; then + if [[ ${pt} = "${pt//\/}" ]]; then + find . ! -type d -name "${pt}" -exec rm -f -- '{}' + + else + rm -f "${pt}" + fi + else + if [[ ${pt%/} = "${pt//\/}" ]]; then + find . -type d -name "${pt%/}" -exec rm -rf -- '{}' + + else + rm -rf "${pt}" + fi + fi + done +} + +modified_makepkg() { + local makepkg_orig=$1 + local makepkg_mine="$tempdir/makepkg" + { + echo '#!/bin/bash' + declare -f tidy_install_purge + sed -r "$makepkg_modify" < "$makepkg_orig" + } > "$makepkg_mine" + chmod 755 "$makepkg_mine" + printf "%s\n" "$makepkg_mine" +} + +# 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[@]}") +noextract=("${mknoextract[@]}") +md5sums=("${mkmd5sums[@]}") +sha1sums=("${mksha1sums[@]}") +sha256sums=("${mksha256sums[@]}") +sha384sums=("${mksha384sums[@]}") +sha512sums=("${mksha512sums[@]}") + +depends=() +checkdepends=() +makedepends=("${mkdepends[@]}") + +#### +options+=(!strip docs libtool emptydirs !zipman purge !upx) +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="$tempdir/SRCBUILD" + printf '%s' "$pkgbuild_append" | cat "$pkgbuild" - > "$srcbuild" + printf '%s\n' "$srcbuild" +} + + +# Modify SRCBUILD ############################################################## + +modified_srcbuild() { + local orig=$1 + local new="$tempdir/SRCBUILD" + sed -e '/PKGDEST=/d' -e '/PKGEXT=/d' < "$orig" > "$new" + printf '%s\n' "$new" +} + +main "$@" diff --git a/src/librefetch/librefetch.8.ronn b/src/librefetch/librefetch.8.ronn new file mode 100644 index 0000000..7fa15d4 --- /dev/null +++ b/src/librefetch/librefetch.8.ronn @@ -0,0 +1,162 @@ +librefetch(8) -- downloads or creates a liberated source tarball +================================================================ + +## SYNOPSIS + +`librefetch` [options] <source-url> [<output-file>]<br> +`librefetch` -[g|V|h] + +## DESCRIPTION + +`librefetch` is a program to streamline creation of custom source +tarballs for `PKGBUILD(5)` files. + +To automatically use `librefetch` to download or create a source +tarball, you can add `libre://FILENAME.tar.gz` to the source array in +your `PKGBUILD`. This works because a post-install script for the +package adds `librefetch` as a download agent for `libre://` to +`makepkg.conf`. Because of this, it is almost never necessary to call +`librefetch` manually. + +There are 7 modes: + + * `download-create`: The default mode. First try `download` mode, + then `create` mode. + * `download`: Download the tarball from the configured mirror. + * `create`: Create the tarball from a `PKGBUILD`/`SRCBUILD`. + * `checksums`: Generate integrity checks for source files. + * `print`: Print the effective build script. + * `version`: Print `librefetch` version information. + * `help`: Print `librefetch` usage information. + +## OPTIONS + + * `-C`: Force `create` mode (don't download) + * `-D`: Force `download` mode (don't create) + * `-p` <file>: Use an alternate build script for `create` mode + (instead of `PKGBUILD`). If an `SRCBUILD` file exists in the same + directory, it is used instead. + * `-g` | `--geninteg`: Use `checksums` mode: Generate integrity + checks for source files. + * `-P` | `--print`: Use `print` mode: print the effective build script. + * `-V` | `--version`: Use `version` mode: Show version information. + * `-h` | `--help`: Use `help` mode: Show useage information. + +## CREATE MODE + +The principle of `create` mode is that a special `PKGBUILD(5)`, called +a `SRCBUILD(5)`, installs source files to `$pkgdir`, and the resulting +"package" is then used as a source tarball. The `SRCBUILD` exists in +the same directory as the `PKGBUILD`. It can be created manually, or +generated on-the-fly from the `PKGBUILD`. Extra steps are taken to +ensure that as long as the same directory contents go in, an identical +tarball will come out--the checksum of the file should not change +based on when it is built or who builds it. + +The `SRCBUILD` is either created, or sanitized if it already exists, +then fed to a modified version of `makepkg(8)`. + +The purpose of the modified `makepkg` is so that the resulting tarball +doesn't contain package metadata, doesn't end with a .pkg file +extension, and always produces an identicle tarball. + +When this documentation speaks of a file being modified, it is a +temporary copy of the file that is modified, your original file will +remain intact. + +## SRCBUILD GENERATION + +As explained in the `CREATE MODE` section, in `create` mode, this +program generates an `SRCBUILD` file. For debugging purposes, this +file can be printed instead of executed with `print` mode. + +### PRE-EXISTING SRCBUILD + +The use of `SRCBUILD` files pre-dates `librefetch`. By convention, +they set `PKGDEST` and `PKGEXT` in `package()` in order to modify the +behavior of `makepkg`. Because a modified version of `makepkg` is +used, this interferes with the correct behavior. To compensate for +this, lines containing "`PKGDEST=`" or "`PKGEXT=`" are deleted from +the `SRCBUILD`. + +The general idea is that `build()` makes any modifications to the +source, then `package()` copies it from `$srcdir` to `$pkgdir`. + +### SRCBUILD FROM PKGBUILD + +Possibly more elegant than having a separate `SRCBUILD` file is having +an `mksource()` function in the main `PKGBUILD`. This results in less +boilerplate and fewer files to edit. + +Note that this only happens if a file named `SRCBUILD` doesn't already +exist; when migrating a package from a manually created `SRCBUILD` to +this method, the `SRCBUILD` must be deleted (or renamed) for this to +work. + +The dynamically created `SRCBUILD` is created by copying `PKGBUILD` to +a temorary file, then re-setting variables and re-defining functions. +Following is a table of the translations. + + Variables + source = mksource + noextract = mknoextract + *sums = mk*sums (md5, sha1, sha256, sha384, sha512) + depends = <empty> + checkdepends = <empty> + makedepends = mkdepends + Functions + prepare() { :; } + build() { mksource; } + check() { :; } + package() { cp -a "$srcdir"/*/ "$pkgdir/"; } + +The `mksource()` function does not need to be defined. If it isn't +defined, then no transformations will be made to the source between it +being extracted to `$srcdir` and copied to `$pkgdir`. + +In summary: + + * Set `mksource=()` and `mkmd5sums=(`) to act as `source=(`) and + `md5sums=()` + * Declare a `mksource()` function to make modifications to the + source, if nescessary. + +Other changes: + + * `pkgname` is set to `pkgbase`, or the first element of the + `pkgname` array. + * `options=()` is set have `makepkg` avoid making changes to + `$pkgdir`. The exact change is: + + options+=(!strip docs libtool emptydirs !zipman purge !upx) + + * `PURGE_TARGETS=()` has vcs directories added to it: + + PURGE_TARGETS+=(.bzr/ .cvs/ .git/ .hg/ .svn/ .makepkg/) + +### MAKEPKG MODIFICATIONS + +The following modifications are made to makepkg: + + * Allow us to manipulate the output file (`$pkg_file`) + * Do not include metadata in the output file (`${comp_files[@]}`) + * Force 'ustar' tar format, don't allow it to upgrade to 'pax' to + store extended file attributes. + * Don't symlink the resulting file into the current directory. + * `PURGE_TARGETS` interprets an item as a directory if it ends with a + slash ("/"). + * Timestamps in `$pkgdir` are reset to "1990-01-01 0:0:0 +0", so that + the resulting tarball will be the same, regardless of when it was + created. + * append `-libre` to `$srcdir` + * append `-libre` to `$pkgbasedir` (which becomes `$pkgdir`) + * Don't check if the package has already been built. + +## CONFIGURATION + +See `librefetch.conf(5)` for details on configuring librefetch using +the `librefetch.conf` file. + +## SEE ALSO + +librefetch.conf(5), makepkg(8), PKGBUILD(5), SRCBUILD(5) diff --git a/src/librefetch/librefetch.conf b/src/librefetch/librefetch.conf new file mode 100644 index 0000000..40d2078 --- /dev/null +++ b/src/librefetch/librefetch.conf @@ -0,0 +1,2 @@ +MIRROR='https://repo.parabolagnulinux.org/sources/' +DOWNLOADER='/usr/bin/curl -fLC - --retry 3 --retry-delay 3 -o %o %u' diff --git a/src/librefetch/librefetch.conf.5.ronn b/src/librefetch/librefetch.conf.5.ronn new file mode 100644 index 0000000..3d80ab5 --- /dev/null +++ b/src/librefetch/librefetch.conf.5.ronn @@ -0,0 +1,36 @@ +librefetch.conf(5) -- librefetch configuration file +=================================================== + +## SYNOPSIS + +`/etc/libretools.d/librefetch.conf`, `~/.config/libretools/librefetch.conf` + +## DESCRIPTION + +Configuration for librefetch is stored in `librefetch.conf`. The +several places it looks for the file are: + + * `/etc/libretools.d/librefetch.conf` + * `$XDG_CONFIG_HOME/libretools/librefetch.conf` + +The later files take precidence over earlier files, but earlier files +are loaded, so that later files only need to set the values they want +to override. + +If `$XDG_CONFIG_HOME` is not set, a default value is set: + + * if `$SUDO_USER` is set: `$(eval echo ~$SUDO_USER)/.config` + * else: `$HOME/.config` + +## OPTIONS + + * `MIRROR='https://repo.parabolagnulinux.org/sources/'`: + The location to download pre-built source tarball in download + mode. + * `DOWNLOADER='/usr/bin/curl -fLC - --retry 3 --retry-delay 3 -o %o %u'`: + The HTTP client to use when downloading pre-built source tarballs + in download mode. + +## SEE ALSO + +librefetch(8) |