summaryrefslogtreecommitdiff
path: root/src/librefetch
diff options
context:
space:
mode:
Diffstat (limited to 'src/librefetch')
-rw-r--r--src/librefetch/Makefile1
-rwxr-xr-xsrc/librefetch/librefetch331
-rw-r--r--src/librefetch/librefetch.8.ronn162
-rw-r--r--src/librefetch/librefetch.conf2
-rw-r--r--src/librefetch/librefetch.conf.5.ronn36
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)