mirror of
https://github.com/moparisthebest/arch-ppa
synced 2024-11-21 16:25:00 -05:00
Initial
This commit is contained in:
commit
0bb0b0294e
3
.gitignore
vendored
Normal file
3
.gitignore
vendored
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
chroot
|
||||||
|
*~
|
||||||
|
pkg
|
132
README.md
Normal file
132
README.md
Normal file
@ -0,0 +1,132 @@
|
|||||||
|
arch-ppa
|
||||||
|
========
|
||||||
|
|
||||||
|
arch-ppa is a tool that easily creates and maintains your own Arch
|
||||||
|
package repositories. Kind of like the Personal Package Archives (PPA)
|
||||||
|
that Ubuntu has, but way easier.
|
||||||
|
|
||||||
|
The Arch User Repository (AUR) is convenient, has tons of software, is
|
||||||
|
generally awesome, but is inherently insecure. Anyone can upload
|
||||||
|
anything they want to the AUR. This is why I don't like to use AUR
|
||||||
|
helpers like `yaourt` or `pacaur`. Using the AUR with a helper
|
||||||
|
requires you to be diligent in reviewing the PKGBUILDs it downloads,
|
||||||
|
in order to make sure it doesn't include things like viruses or
|
||||||
|
trojans, or downloading from a weird URL.
|
||||||
|
|
||||||
|
I wanted a way to maintain my own repository of PKGBUILDs, downloaded
|
||||||
|
from the AUR, that I have manually verified. Building and installing
|
||||||
|
packages built from those pre-verified PKGBUILDs resolves the
|
||||||
|
insecurity of the AUR in my mind. This gives me the full power of the
|
||||||
|
AUR, but allows me to automate my package installs in a way that I
|
||||||
|
never felt comfortable with before. Seriously, why does pacaur have a
|
||||||
|
`--noconfirm` option? That's scary.
|
||||||
|
|
||||||
|
The packages this tool builds can be hosted as a regular arch
|
||||||
|
repository, which you put into your `/etc/pacman.conf`. The added
|
||||||
|
convenience here is that although the packages came from the AUR, your
|
||||||
|
clients install it through regular-old pacman.
|
||||||
|
|
||||||
|
|
||||||
|
Usage
|
||||||
|
-----
|
||||||
|
|
||||||
|
Clone this repo somewhere. Everything will be self contained in this
|
||||||
|
directory wherever you put it.
|
||||||
|
|
||||||
|
arch-ppa should not be run as root, but the user that does run it does
|
||||||
|
need sudo privileges as the underlying devtools need it.
|
||||||
|
|
||||||
|
Run setup:
|
||||||
|
|
||||||
|
./arch-ppa setup
|
||||||
|
|
||||||
|
The setup installs a few dependencies like `devtools` and `git`. It
|
||||||
|
also creates a chroot directory which is a container that will be used
|
||||||
|
to build packages in a completely clean environment using
|
||||||
|
`systemd-nspawn`.
|
||||||
|
|
||||||
|
Add packages from the AUR:
|
||||||
|
|
||||||
|
./arch-ppa add cower curlbomb pasystray
|
||||||
|
|
||||||
|
This downloads PKGBUILDs from the AUR for the listed packages: cower,
|
||||||
|
curlbomb, pasystray, as well as all of their AUR dependencies, and
|
||||||
|
placed into the `src` directory. You can put PKGBUILDs from other
|
||||||
|
sources in the src directory too; they don't have to be from the
|
||||||
|
AUR. Note that any PKGBUILD that lists a dependency of another
|
||||||
|
package, that is not found in one of the arch repositories, needs to
|
||||||
|
have it's own PKGBUILD in the `src` directory too. (The `add` command
|
||||||
|
does this for you automatically, thanks to `cower -d -d`)
|
||||||
|
|
||||||
|
Build everything:
|
||||||
|
|
||||||
|
./arch-ppa clean ryan
|
||||||
|
./arch-ppa build ryan
|
||||||
|
|
||||||
|
The build process operates on a single repository, in this example
|
||||||
|
called `ryan`. You can maintain several repositories, each containing
|
||||||
|
different sets of packages. Just make sure to give each repository a
|
||||||
|
unique name.
|
||||||
|
|
||||||
|
The clean process removes the repository directory containing all the
|
||||||
|
built packages. It also deletes the chroot for the repository from the
|
||||||
|
`chroot` directory.
|
||||||
|
|
||||||
|
The build process creates a new package repository called `ryan` (or
|
||||||
|
whatever you called yours.) It finds PKGBUILD files in the `src`
|
||||||
|
directory and figures out the dependency chain and builds all the
|
||||||
|
packages in the correct order. Additionally, you can specify
|
||||||
|
individual package names after the repository name if you only wish to
|
||||||
|
build certain packages. If you do specify package names, make sure to
|
||||||
|
include all dependencies, as they will not be included otherwise.
|
||||||
|
|
||||||
|
The repository directory can be listed in your /etc/pacman.conf like this:
|
||||||
|
|
||||||
|
[ryan]
|
||||||
|
Server = file:///home/ryan/git/arch-ppa/ryan
|
||||||
|
SigLevel = Required TrustedOnly
|
||||||
|
|
||||||
|
This is the full path to the ryan repository just created. Run `pacman
|
||||||
|
-Sy` and you should see pacman synchronize with the new repository
|
||||||
|
name. Alternatively, upload the directory to a webserver and share it
|
||||||
|
with all your friends.
|
||||||
|
|
||||||
|
The SigLevel option specifies how pacman should trust our
|
||||||
|
repository. `Required TruestedOnly` is a strict rule that the key must
|
||||||
|
be in the local pacman keyring and be assigned a trust level. Pacman
|
||||||
|
will usually download the key without a problem, but you will still
|
||||||
|
need to locally sign the key to trust it.
|
||||||
|
|
||||||
|
Mini gpg tutorial
|
||||||
|
-----------------
|
||||||
|
View your key information:
|
||||||
|
|
||||||
|
gpg -K
|
||||||
|
|
||||||
|
This should output something like this:
|
||||||
|
|
||||||
|
/home/ryan/.gnupg/pubring.kbx
|
||||||
|
-----------------------------
|
||||||
|
sec rsa2048/4BAACCF8 2016-04-15 [SC]
|
||||||
|
uid [ultimate] test guy <ryantest@enigmacurry.com>
|
||||||
|
ssb rsa2048/C22BDAA5 2016-04-15 [E]
|
||||||
|
|
||||||
|
My public key ID is 4BAACCF8. Always omit the part before the
|
||||||
|
slash. If it didn't output any key information at all, this means you
|
||||||
|
don't have a key yet. Create one and follow the prompts:
|
||||||
|
|
||||||
|
gpg --gen-key
|
||||||
|
|
||||||
|
Send your public key to the keyserver (replace with your ID):
|
||||||
|
|
||||||
|
gpg --send-keys 4BAACCF8
|
||||||
|
|
||||||
|
On each machine you will use your package repository, run the
|
||||||
|
following to import the key and to locally sign (assign trust) the
|
||||||
|
key (again, replace with your key ID):
|
||||||
|
|
||||||
|
sudo pacman-key -r 4BAACCF8
|
||||||
|
sudo pacman-key --lsign-key 4BAACCF8
|
||||||
|
|
||||||
|
If you don't sign the key, pacman will complain that your packages are
|
||||||
|
not trusted.
|
211
arch-ppa
Executable file
211
arch-ppa
Executable file
@ -0,0 +1,211 @@
|
|||||||
|
BASEDIR=$(cd $(dirname $0); pwd)
|
||||||
|
CHROOT=$BASEDIR/chroot
|
||||||
|
|
||||||
|
if [ `whoami` == 'root' ]; then
|
||||||
|
echo "Must not be run as root."
|
||||||
|
exit 1;
|
||||||
|
fi
|
||||||
|
|
||||||
|
exe() { echo "\$ $@" ; "$@" ; }
|
||||||
|
|
||||||
|
create_chroot() {
|
||||||
|
(
|
||||||
|
set -e
|
||||||
|
if [ ! -d $CHROOT ]; then
|
||||||
|
echo "## Creating arch chroot ..."
|
||||||
|
exe mkdir $CHROOT
|
||||||
|
exe mkarchroot $CHROOT/root base-devel
|
||||||
|
# install cower:
|
||||||
|
TMP_BUILD=`mktemp -d`
|
||||||
|
exe cd $TMP_BUILD
|
||||||
|
curl https://aur.archlinux.org/cgit/aur.git/snapshot/cower.tar.gz | tar xz
|
||||||
|
exe cd cower
|
||||||
|
exe makechrootpkg -r $CHROOT -l root -- -i
|
||||||
|
exe rm -rf $TMP_BUILD
|
||||||
|
echo "## Root chroot build complete."
|
||||||
|
fi
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
install_system_deps() {
|
||||||
|
(
|
||||||
|
set -e
|
||||||
|
pkg_dep() {
|
||||||
|
if !(pacman -Q $1 > /dev/null 2>&1); then
|
||||||
|
echo "Installing $1..."
|
||||||
|
exe sudo pacman -S --noconfirm $1
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
pkg_dep devtools
|
||||||
|
pkg_dep git
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
package_build() {
|
||||||
|
# Build a package in a container. $1=container $2=package
|
||||||
|
# PKGBUILD must already exist in src/
|
||||||
|
# If package has dependencies we also maintain in src/, recursively build those first.
|
||||||
|
(
|
||||||
|
set -e
|
||||||
|
if [ "$#" -ne 2 ]; then
|
||||||
|
echo "package_build takes two args: repo_name and package_name"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
repo_name=$1
|
||||||
|
package_name=$2
|
||||||
|
setup
|
||||||
|
pkgdir=$BASEDIR/src/$package_name
|
||||||
|
if [ ! -d $pkgdir ]; then
|
||||||
|
echo "Package $package_name not found in $pkgdir"
|
||||||
|
echo "Try running: package_add $package_name"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
if [ ! -f $pkgdir/PKGBUILD ]; then
|
||||||
|
echo "Cannot find PKGBUILD in $pkgdir"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
if (arch-nspawn $CHROOT/$repo_name pacman -Q $package_name > /dev/null 2>&1); then
|
||||||
|
echo "Package $package_name already built"
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
# Find and build dependencies:
|
||||||
|
find_deps $package_name | while read dep; do
|
||||||
|
# Build the dep if we haven't already yet:
|
||||||
|
if !(arch-nspawn $CHROOT/$repo_name pacman -Q $dep > /dev/null 2>&1); then
|
||||||
|
package_build $repo_name $dep
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
# Build package:
|
||||||
|
cd $pkgdir
|
||||||
|
rm -f *.pkg.tar.xz
|
||||||
|
mkdir -p $BASEDIR/$repo_name
|
||||||
|
exe makechrootpkg -r $CHROOT -l $repo_name -- -i
|
||||||
|
exe mv *.pkg.tar.xz $BASEDIR/$repo_name
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
sign_packages() {
|
||||||
|
if [ "$#" -lt 1 ]; then
|
||||||
|
echo "sign_packages requires specifying the list of packages to sign"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
(
|
||||||
|
set -e
|
||||||
|
cd $(dirname $1)
|
||||||
|
for pkg in "$@"; do
|
||||||
|
gpg --detach-sign --use-agent $pkg
|
||||||
|
done
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
find_deps() {
|
||||||
|
# Inspect package srcinfo and pull out the dependencies that we maintain in src
|
||||||
|
(
|
||||||
|
set -e
|
||||||
|
setup
|
||||||
|
cat $BASEDIR/src/$1/.SRCINFO | sed -nr 's/^\W*depends = ([-a-zA-Z0-9]+).*$/\1/p' | while read dep; do
|
||||||
|
if [ -d $BASEDIR/src/$dep ]; then
|
||||||
|
echo $dep
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
add() {
|
||||||
|
# Add packages and their AUR dependencies to src
|
||||||
|
(
|
||||||
|
set -e
|
||||||
|
if [ "$#" -lt 1 ]; then
|
||||||
|
echo "Must specify package(s) to add"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
setup
|
||||||
|
if [ ! -d $BASEDIR/src ]; then
|
||||||
|
mkdir $BASEDIR/src
|
||||||
|
fi
|
||||||
|
for pkg in "$@"; do
|
||||||
|
arch-nspawn $CHROOT/root --bind=$BASEDIR/src:/src cower -q -t /src -d -d $pkg
|
||||||
|
done
|
||||||
|
sudo chown $USER -R $BASEDIR/src
|
||||||
|
echo "## All requested packages added"
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
list() {
|
||||||
|
if [ "$#" -ne 1 ]; then
|
||||||
|
echo "Must specify repository name to list"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
setup
|
||||||
|
arch-nspawn $CHROOT/$1 pacman -Qm
|
||||||
|
}
|
||||||
|
|
||||||
|
setup() {
|
||||||
|
mkdir -p $BASEDIR/src
|
||||||
|
install_system_deps
|
||||||
|
create_chroot
|
||||||
|
}
|
||||||
|
|
||||||
|
clean() {
|
||||||
|
(
|
||||||
|
set -e
|
||||||
|
if [ "$#" -lt 1 ]; then
|
||||||
|
echo "Must specify repository names to clean"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
for repo in "$@"; do
|
||||||
|
# Clean repository and chroot
|
||||||
|
if [ -d $BASEDIR/chroot/$repo ]; then
|
||||||
|
exe sudo rm -rf $BASEDIR/chroot/$repo $BASEDIR/chroot/$repo.lock
|
||||||
|
fi
|
||||||
|
if [ -d $BASEDIR/$repo ]; then
|
||||||
|
exe rm -rf $BASEDIR/$repo
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
build() {
|
||||||
|
(
|
||||||
|
set -e
|
||||||
|
if [ "$#" -lt 1 ]; then
|
||||||
|
echo "Must specify repository name to build (and optional package list to include)"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
setup
|
||||||
|
repo_name=$1
|
||||||
|
mkdir -p $BASEDIR/$repo_name
|
||||||
|
shift
|
||||||
|
if [ "$#" -gt 0 ]; then
|
||||||
|
# Build only requested packages
|
||||||
|
for pkg in "$@"; do
|
||||||
|
package_build $repo_name $pkg
|
||||||
|
done
|
||||||
|
echo "## All requested packages built"
|
||||||
|
else
|
||||||
|
# Build all packages:
|
||||||
|
cd $BASEDIR/src
|
||||||
|
find -type d | sed 's/\.\///' | tail -n +2 | while read pkg; do
|
||||||
|
package_build $repo_name $pkg
|
||||||
|
done
|
||||||
|
echo "## All packages built"
|
||||||
|
fi
|
||||||
|
echo "## Updating repository database"
|
||||||
|
cd $BASEDIR/$repo_name
|
||||||
|
if [ `ls *.pkg.tar.xz 2> /dev/null | wc -l` -lt 1 ]; then
|
||||||
|
echo "No packages found in $BASEDIR/$repo_name"
|
||||||
|
return 1;
|
||||||
|
fi
|
||||||
|
sign_packages *.pkg.tar.xz
|
||||||
|
repo-add $repo_name.db.tar.gz *.pkg.tar.xz
|
||||||
|
sign_packages $repo_name.db
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if [ "$#" -gt 0 ]; then
|
||||||
|
$*
|
||||||
|
else
|
||||||
|
echo "Must specify a command, eg: add, build, list, clean"
|
||||||
|
exit 1
|
||||||
|
fi
|
Loading…
Reference in New Issue
Block a user