Skip to content
115 changes: 77 additions & 38 deletions packer
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
#!/bin/bash
# Copyright Matthew Bruenig <matthewbruenig@gmail.com>
#
# Copyright (C) 2010 Matthew Bruenig <matthewbruenig@gmail.com>
# Copyright (C) 2012 Mateusz Loskot <mateusz@loskot.net>
#
# 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 3 of the License, or
Expand All @@ -15,11 +18,9 @@

[[ $PACMAN ]] || PACMAN="pacman"

# set tmpfile stuff, clean tmpdir
tmpdir="${TMPDIR:-/tmp}/packertmp-$UID"
rm -rf "$tmpdir" &>/dev/null
mkdir -p "$tmpdir"

# configuration files
packerconf='/etc/packer.conf'
userpackerconf="$HOME/.packer.conf"
makepkgconf='/etc/makepkg.conf'
usermakepkgconf="$HOME/.makepkg.conf"
pacmanconf='/etc/pacman.conf'
Expand Down Expand Up @@ -59,6 +60,7 @@ usage() {
echo ' -Ss|-Ssq - searches for package'
echo ' -Si - outputs info for package'
echo ' -G - download and extract aur tarball only'
echo ' -P - purge cache content'
echo
echo ' --quiet - only output package name for searches'
echo ' --ignore - takes a comma-separated list of packages to ignore'
Expand All @@ -84,6 +86,12 @@ runasroot() {
fi
}

# Source packer.conf file
sourcepackerconf() {
[[ -r "$packerconf" ]] && . "$packerconf"
[[ -r "$userpackerconf" ]] && . "$userpackerconf"
}

# Source makepkg.conf file
sourcemakepkgconf() {
. "$makepkgconf"
Expand All @@ -104,7 +112,7 @@ isignored() {
# Tests whether $1 exists on the aur
existsinaur() {
rpcinfo "$1"
[[ "$(jshon -Qe type -u < "$tmpdir/$1.info")" = "info" ]]
[[ "$(jshon -Qe type -u < "$cachedir/$1.info")" = "info" ]]
}

# Tests whether $1 exists in pacman
Expand All @@ -130,7 +138,7 @@ existsinlocal() {
# Scrapes the aur deps from PKGBUILDS and puts in globally available dependencies array
scrapeaurdeps() {
pkginfo "$1" "$preview"
. "$tmpdir/$1.PKGBUILD"
. "$cachedir/$1.PKGBUILD"
IFS=$'\n'
dependencies=( $(echo -e "${depends[*]}\n${makedepends[*]}" | sed -e 's/=.*//' -e 's/>.*//' -e 's/<.*//'| sort -u) )
unset IFS
Expand Down Expand Up @@ -225,26 +233,26 @@ aurbar() {
}

rpcinfo() {
if ! [[ -f "$tmpdir/$1.info" ]]; then
curl -LfGs --data-urlencode "arg=$1" "$RPCURL=info" > "$tmpdir/$1.info"
if ! [[ -f "$cachedir/$1.info" ]]; then
curl -LfGs --data-urlencode "arg=$1" "$RPCURL=info" > "$cachedir/$1.info"
fi
}

pkglink() {
rpcinfo $1
echo "${PKGURL}$(jshon -Q -e results -e URLPath -u < "$tmpdir/$1.info")"
echo "${PKGURL}$(jshon -Q -e results -e URLPath -u < "$cachedir/$1.info")"
}

# downloads pkgbuild ($1), edits if $2 is set
pkginfo() {
if ! [[ -f "$tmpdir/$1.PKGBUILD" ]]; then
if ! [[ -f "$cachedir/$1.PKGBUILD" ]]; then
pkgpath=$(pkglink $1)
curl -Lfs "${pkgpath%/*}/PKGBUILD" > "$tmpdir/$1.PKGBUILD"
curl -Lfs "${pkgpath%/*}/PKGBUILD" > "$cachedir/$1.PKGBUILD"
if [[ $2 ]]; then
# rename for syntax highlighting
ln -sf "$tmpdir/$1.PKGBUILD" "$tmpdir/PKGBUILD"
confirm_edit "${COLOR6}Edit $1 PKGBUILD with \$EDITOR? [Y/n]${ENDCOLOR} " "$tmpdir/PKGBUILD"
rm -f "$tmpdir/PKGBUILD"
ln -sf "$cachedir/$1.PKGBUILD" "$cachedir/PKGBUILD"
confirm_edit "${COLOR6}Edit $1 PKGBUILD with \$EDITOR? [Y/n]${ENDCOLOR} " "$cachedir/PKGBUILD"
rm -f "$cachedir/PKGBUILD"
fi
fi
}
Expand All @@ -254,7 +262,7 @@ aurversionisnewer() {
rpcinfo "$1"
unset aurversion
if existsinaur "$1"; then
aurversion="$(jshon -Q -e results -e Version -u < "$tmpdir/$1.info")"
aurversion="$(jshon -Q -e results -e Version -u < "$cachedir/$1.info")"
if [[ "$(LC_ALL=C vercmp "$aurversion" "$2")" -gt 0 ]]; then
return 0
fi
Expand All @@ -264,7 +272,7 @@ aurversionisnewer() {

isoutofdate() {
rpcinfo "$1"
[[ "$(jshon -Q -e results -e OutOfDate -u < "$tmpdir/$1.info")" = "1" ]]
[[ "$(jshon -Q -e results -e OutOfDate -u < "$cachedir/$1.info")" = "1" ]]
}

# $1 is prompt, $2 is file
Expand All @@ -280,7 +288,7 @@ confirm_edit() {

# Installs packages from aur ($1 is package, $2 is dependency or explicit)
aurinstall() {
dir="${TMPDIR:-/tmp}/packerbuild-$UID/$1"
dir="$PACKER_CACHEDIR/$1"

# Prepare the installation directory
# If there is an old directory and aurversion is not newer, use old directory
Expand Down Expand Up @@ -324,9 +332,9 @@ aurinstall() {

[[ $? -ne 0 ]] && echo "The build failed." && return 1
if [[ $2 = dependency ]]; then
runasroot $PACMAN ${PACOPTS[@]} --asdeps -U $pkgname-*$PKGEXT
runasroot $PACMAN ${PACOPTS[@]} --asdeps -U $pkgname-$pkgver-$pkgrel*$PKGEXT
elif [[ $2 = explicit ]]; then
runasroot $PACMAN ${PACOPTS[@]} -U $pkgname-*$PKGEXT
runasroot $PACMAN ${PACOPTS[@]} -U $pkgname-$pkgver-$pkgrel*$PKGEXT
fi
}

Expand Down Expand Up @@ -446,6 +454,14 @@ installhandling() {
done
}

# Purges cached packages and creates empty cache ($1 cache location)
purgecache() {
echo -e "${COLOR5}:: ${COLOR1}Purging aur cache in '$1'...${ENDCOLOR}"
if [[ -d $1 ]]; then
rm -rf "$1" &>/dev/null
fi
}

# proceed with installation prompt
proceed() {
read -n 1
Expand Down Expand Up @@ -474,6 +490,7 @@ while [[ $1 ]]; do
'-Si') option=info ;;
-S*u*) option=update ; pacmanarg="$1" ;;
'-G') option=download ;;
'-P') option=purgecache ;;
'-h'|'--help') usage ;;
'--quiet') quiet='1' ;;
'--ignore') ignorearg="$2" ; PACOPTS+=("--ignore" "$2") ; shift ;;
Expand All @@ -490,6 +507,28 @@ while [[ $1 ]]; do
shift
done

# Load packer.conf
sourcepackerconf
if [[ -z $PACKER_CACHEDIR ]]; then
PACKER_CACHEDIR="${TMPDIR:-/tmp}/packertmp-$UID"
fi
echo -e "${COLOR5}:: ${COLOR1}Setting aur cache in '$PACKER_CACHEDIR'...${ENDCOLOR}"

# Set cache location
cachedir="$PACKER_CACHEDIR"

# Clean cache, if requested
if [[ $option = purgecache ]]; then
purgecache "$cachedir" || err "Failed to purge cache"
exit
else
if ! $PACKER_KEEP_CACHE; then
purgecache "$cachedir"
fi
fi
# Recreate cache directory
[[ -d "$cachedir" ]] || mkdir -p "$cachedir"

# Sanity checks
[[ $option ]] || option="searchinstall"
[[ $option != "update" && -z $packageargs ]] && err "Must specify a package."
Expand Down Expand Up @@ -532,14 +571,14 @@ if [[ $option = update ]]; then
for ((i=0; i<$total; i++)); do
pkg="${packages[i]%% *}"
ver="${packages[i]##* }"
if [[ ! -s "$tmpdir/$pkg.PKGBUILD" ]]; then
if [[ ! -s "$cachedir/$pkg.PKGBUILD" ]]; then
continue
fi
if isignored "$pkg"; then
continue
fi
unset _darcstrunk _cvsroot _gitroot _svntrunk _bzrtrunk _hgroot
. "$tmpdir/$pkg.PKGBUILD"
. "$cachedir/$pkg.PKGBUILD"
if [[ "$(LC_ALL=C vercmp "$pkgver-$pkgrel" "$ver")" -gt 0 ]]; then
newpackages+=("$pkg")
elif [[ ${_darcstrunk} || ${_cvsroot} || ${_gitroot} || ${_svntrunk} || ${_bzrtrunk} || ${_hgroot} ]]; then
Expand Down Expand Up @@ -626,18 +665,18 @@ if [[ $option = search || $option = searchinstall ]]; then
for package in "${packageargs[@]}"; do
curl -LfGs --data-urlencode "arg=$package" "$RPCURL=search" | \
jshon -Q -e results -a -e Name -u -p -e Version -u -p -e NumVotes -u -p -e Description -u | \
sed 's/^$/-/' | paste -s -d "\t\t\t\n" | sort -nr -k 3 > "$tmpdir/$package.search" &
sed 's/^$/-/' | paste -s -d "\t\t\t\n" | sort -nr -k 3 > "$cachedir/$package.search" &
done
wait
cp "$tmpdir/${packageargs[0]}.search" "$tmpdir/search.results"
cp "$cachedir/${packageargs[0]}.search" "$cachedir/search.results"
for ((i=1 ; i<${#packageargs[@]} ; i++)); do
grep -xFf "$tmpdir/search.results" "$tmpdir/${packageargs[$i]}.search" > "$tmpdir/search.results-2"
mv "$tmpdir/search.results-2" "$tmpdir/search.results"
grep -xFf "$cachedir/search.results" "$cachedir/${packageargs[$i]}.search" > "$cachedir/search.results-2"
mv "$cachedir/search.results-2" "$cachedir/search.results"
done
sed -i '/^$/d' "$tmpdir/search.results"
sed -i '/^$/d' "$cachedir/search.results"

# Prepare tmp file and arrays
IFS=$'\n' read -rd '' -a aurname < <(cut -f 1 "$tmpdir/search.results")
IFS=$'\n' read -rd '' -a aurname < <(cut -f 1 "$cachedir/search.results")
aurtotal="${#aurname[@]}"
alltotal="$(($pactotal+$aurtotal))"
# Echo out the -Ss formatted package information
Expand All @@ -646,15 +685,15 @@ if [[ $option = search || $option = searchinstall ]]; then
if [[ $option = search ]]; then
if [[ $quiet ]]; then
printf "%s\n" ${aurname[@]}
elif [[ -s "$tmpdir/search.results" ]]; then
printf "${COLOR3}aur/${COLOR1}%s ${COLOR2}%s${ENDCOLOR} (%s)\n %s\n" $(cat "$tmpdir/search.results")
elif [[ -s "$cachedir/search.results" ]]; then
printf "${COLOR3}aur/${COLOR1}%s ${COLOR2}%s${ENDCOLOR} (%s)\n %s\n" $(cat "$cachedir/search.results")
fi
else
# interactive
if [[ $quiet ]]; then
nl -v ${pactotal:-0} -w 1 -s ' ' <(cut -f 1 "$tmpdir/search.results")
elif [[ -s "$tmpdir/search.results" ]]; then
printf "%d ${COLOR3}aur/${COLOR1}%s ${COLOR2}%s${ENDCOLOR} (%s)\n %s\n" $(nl -v ${pactotal:-0} -w 1 < "$tmpdir/search.results")
nl -v ${pactotal:-0} -w 1 -s ' ' <(cut -f 1 "$cachedir/search.results")
elif [[ -s "$cachedir/search.results" ]]; then
printf "%d ${COLOR3}aur/${COLOR1}%s ${COLOR2}%s${ENDCOLOR} (%s)\n %s\n" $(nl -v ${pactotal:-0} -w 1 < "$cachedir/search.results")
fi
fi | fmt -"$_WIDTH" -s
unset IFS
Expand Down Expand Up @@ -689,8 +728,8 @@ if [[ $option = search || $option = searchinstall ]]; then
fi

# Remove the tmpfiles
rm -f "$tmpdir/*search" &>/dev/null
rm -f "$tmpdir/search.result" &>/dev/null
rm -f "$cachedir/*search" &>/dev/null
rm -f "$cachedir/search.result" &>/dev/null
exit
fi

Expand All @@ -710,8 +749,8 @@ if [[ $option = info ]]; then
exit
else # Check to see if it is in the aur
pkginfo "$package" "$preview"
[[ -s "$tmpdir/$package.PKGBUILD" ]] || err "${COLOR7}error:${ENDCOLOR} package '$package' was not found"
. "$tmpdir/$package.PKGBUILD"
[[ -s "$cachedir/$package.PKGBUILD" ]] || err "${COLOR7}error:${ENDCOLOR} package '$package' was not found"
. "$cachedir/$package.PKGBUILD"

# Echo out the -Si formatted package information
# Retrieve each element in order and echo them immediately
Expand Down
28 changes: 25 additions & 3 deletions packer.8
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,11 @@ Show information for a package\&.
Download and extract AUR package tarballs, but don\(cqt install anything\&.
.RE
.PP
\fB\-P\fR
.RS 4
Purge cache content\&.
.RE
.PP
\fB\-h\fR
.RS 4
Show packer usage\&.
Expand Down Expand Up @@ -197,7 +202,24 @@ packer \fIname\fR
.RE
.SH "CONFIGURATION"
.sp
Packer uses these settings in /etc/pacman\&.conf:
Optionally, packer uses these settings sourced from global configuration
file in /etc/packer\&.conf or from user's file in ~/.packer.conf:
.sp
\fBPACKER_CACHEDIR\fR
.RS 4
.sp
Cache directory where packages are downloaded and built\&. If not specified,
the TMPDIR variable is used if defined, otherwise cache is created
in /tmp/packertmp-$UID\&.
.RE
.PP
\fBPACKER_KEEP_CACHE\fR
.RS 4
.sp
Flag indicates if cache should be persistent, false by default\&.
.RE
.PP
Packer also uses these settings in /etc/pacman\&.conf:
.sp
.RS 4
.ie n \{\
Expand All @@ -213,11 +235,11 @@ IgnorePkg
Packer output will be colorized unless the environmental variable COLOR is set to `NO'.
.sp
To manually edit files, packer uses the EDITOR variable\&. If EDITOR is not set then the default editor is vi\&.
.sp
Packages are built in the TMPDIR path\&. If the TMPDIR variable is not set then the default path is /tmp
.SH "SEE ALSO"
.sp
\fBpacman\fR(8)
.SH "AUTHORS"
.sp
Matthew Bruenig <matthewbruenig@gmail\&.com>
.sp
Mateusz Loskot <mateusz@loskot\&.net> - packan.conf and configurable cache support
9 changes: 9 additions & 0 deletions packer.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
#
# /etc/packer.conf - global configuration file for packer
#
#-- Cache directory where packages are downloaded and built.
#-- If not specified, the TMPDIR variable is used if defined,
# otherwise cache is created in /tmp/packertmp-$UID.
PACKER_CACHEDIR=${TMPDIR:-/tmp}/packertmp-$UID
#-- Flag indicates if cache should be persistent, false by default.
PACKER_KEEP_CACHE=false