Construction Kit
an archlinux unofficial repository manager over the ftp transfer protocol
Just an unofficial tool written in bash, to help managing an archlinux repository over the ftp transfer protocol.
#!/bin/bash
#
#
# CKIT - Construction Kit
# Just an unofficial archlinux repository manager
# over the ftp transfer protocol.
#
# Copyright (C) 2009 Dario 'Dax' Vilardi <dax@deelab.org>
#
#
# 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
# (at your option) any later version.
#
# This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
#
#################### SETTINGS ####################
# ftp account
ftpaddress="ftp.deelab.org"
foo=""
bar=""
# remote spot
httpaddress="http://www.deelab.org"
# structure: $httpaddress/arch/$arch/
# sources workspace
builddir="$HOME/pkg/yaourtbuild"
# packages workspace
repodir="$HOME/pkg/CKIT"
# cache
cachedir="$HOME/pkg/cache"
# repo
repo="deelab.db.tar.gz"
# arch
arch="i686"
# editor
editor="geany"
# usefull files
checklog="checklog"
buildlog="buildlog"
updatelog="updatelog"
deletelog="deletelog"
#################### /SETTINGS ####################
#################### PRIVATE INTERFACES ####################
wget_repo(){
cd $repodir
[[ -f $repo ]] && rm $repo
printf "==> Getting $repo... "
wget $httpaddress/arch/$arch/$repo &>/dev/null \
&& echo "done" \
|| echo "failed"
}
wget_tarball(){
pkg=$1
cd $builddir
url="http://aur.archlinux.org/packages/$pkg/$pkg/PKGBUILD"
if PKGBUILD=$(wget -q -O - "$url"); then
printf " -> Getting $pkg from AUR..."
if wget http://aur.archlinux.org/packages/$pkg/$pkg.tar.gz &>/dev/null; then
echo "done"
tar -xf "$pkg.tar.gz"
rm $pkg.tar.gz
else
echo "failed"
fi
else
echo " -> $pkg not found on AUR."
fi
}
lftp_run(){
lftp -u "$foo,$bar" $ftpaddress/arch/$arch -e "$1; exit"
}
lftp_glob_rm(){
item=$(lftp_run "glob echo $1-*.pkg.tar.gz" 2>&1 | grep $1)
RESULT=""
lftp_run "glob rm -f $1-*.pkg.tar.gz" &>/dev/null && RESULT=$item
}
lftp_put_repo(){
printf "==> Uploading db... "
cp "$repo" "$repo"_prev
lftp_run "put $repo" &>/dev/null \
&& echo "done!" \
|| echo "failed!"
wget_repo
i=$(stat -c%s "$repo")
j=$(stat -c%s "$repo"_prev)
[[ $i = $j ]] \
&& echo " -> Size test ok ($i)." \
|| echo " -> Take care: $i ~ $j! restoredb maybe needed."
}
post_build(){
pkg=($1*.pkg.tar.gz)
if [[ -s "${pkg[0]}" ]]; then
echo "==> Yo, $1 done :)"
mv $builddir/$1/$1*.pkg.tar.gz $repodir
echo $1 >> /tmp/CKIT
cat /tmp/CKIT $repodir/$buildlog > /tmp/$buildlog
rm /tmp/CKIT
mv /tmp/$buildlog $repodir/$buildlog
else
echo "==> WTF, package $1 doesn't build :("
fi
}
rmdirsrc(){
[[ -d $builddir/$1/src ]] \
&& rm -rf $builddir/$1/src \
&& echo " -> $builddir/$1/src removed"
}
rmsrc(){
target=( "zip" "ZIP" "rar" "RAR" "bz2" "gz" "part" "jar" "Jar" "deb" "html" "bin")
for i in "${target[@]}"; do
rm $builddir/$1/*$i &>/dev/null && echo " -> $i removed"
done
}
die(){
echo "$@"
exit 1
}
copy_log_to_pkgs(){
IFS=$'\n'
[[ -s $repodir/$1 ]] && pkgs=($(< $repodir/$1)) || die "==> $1 empty"
}
#################### /PRIVATE INTERFACES ####################
#################### PUBLIC INTERFACES ####################
# DELETESRC
deletesrc(){
if [[ $FROMLOG == 0 ]] && (( ${#pkgs[@]} == 0 )); then
copy_log_to_pkgs $deletelog
else
(( ${#pkgs[@]} == 0 )) && die "==> Packages needed!"
fi
for pkg in "${pkgs[@]}"; do
[[ -d $builddir/$pkg ]] \
&& echo "==> Cleaning $pkg directory" \
&& rmdirsrc $pkg \
&& rmsrc $pkg
done
}
# /DELETESRC
# EDITPKG
editpkg(){
read -p "==> Package to edit: " pkg
if [[ -d $builddir/$pkg ]]; then
echo "==> $pkg:"
cd $builddir/$pkg
for file in *; do
[[ -f $file ]] && echo " -> $file"
done
read -p "==> Which one want you edit? " file
if [[ -f $builddir/$pkg/$file ]]; then
echo "==> Editing $pkg/$file"
$editor "$builddir/$pkg/$file" && echo " -> Done."
else
echo "==> $file not found."
fi
else
echo "==> $pkg not found."
fi
}
# /EDITPKG
# EDITLOG
editlog(){
echo "==> Available logs:"
cd $repodir
for file in *log; do
echo " -> $file"
done
read -p "==> Which one to edit? " log
if [[ -f $repodir/$log ]]; then
echo "==> Editing $repodir/$log"
$editor $repodir/$log && echo " -> Done."
else
echo "==> $log not found."
fi
}
# /EDITLOG
# OWNPKG
ownpkg(){
read -p "==> Package to own: " pkg
if [[ -d $builddir/$pkg ]]; then
echo " -> Owning $pkg "
sudo chown -R $USER $builddir/$pkg && echo " -> Done."
else
echo " -> $pkg not found."
fi
}
# /OWNPKG
# CLEARCACHE
clearcache(){
rm $cachedir/*
}
# /CLEARCACHE
# RESTOREDB
restoredb(){
cd $repodir
echo "==> Restoring db from latest backup."
cp "$repo"_prev "$repo"
lftp_run "put $repo" &>/dev/null \
&& echo " -> Done!" \
|| echo " -> Failed!"
}
# /RESTOREDB
# CHECK
check(){
[[ -f $repodir/$checklog ]] && rm $repodir/$checklog;
touch $repodir/$checklog
cd $repodir
wget_repo
echo "==> Checking for outdated's versions of packages."
REGEX=".*-(svn|cvs|hg|git|bzr|darcs|devel)"
while read -r line; do
[[ $line = */ ]] || continue
i="${line%/}"
pkg=${i%-*-*}
repover=${i#$pkg-}
# AUR check
url="http://aur.archlinux.org/packages/$pkg/$pkg/PKGBUILD"
if PKGBUILD=$(wget -q -O - "$url"); then
aurver="$(eval "$PKGBUILD" &>/dev/null; echo "$pkgver-$pkgrel")"
else
aurver="Null"
fi
# local check
if pacman -Q $pkg &> /dev/null; then
localver="$(LANG=C pacman -Qi "$pkg" | awk '/^Version/ {print $3}')"
else
localver="Null"
fi
# devel check
if [[ "$pkg" =~ $REGEX && -d $builddir/$pkg ]]; then
cd "$builddir/$pkg" || warn "==> $pkg not available."
# awk -v foo=something assigns an awk variable
# $0 being the whole line, $1 being the first field
develver=$(makepkg -o 2>&1 | awk -v "pkg=$pkg" '$0 ~ pkg {print $6}')
cd ~-
result=$(vercmp "$repover" "$develver")
else
develver="Null"
result=$(vercmp "$repover" "$aurver")
fi
if [[ "$result" < 0 ]]; then
echo " -> $pkg REPO:$repover LOCAL:$localver AUR:$aurver DEVEL:$develver"
echo $pkg >> /tmp/CKIT
cat /tmp/CKIT $repodir/$checklog > /tmp/$checklog
rm /tmp/CKIT
mv /tmp/$checklog $repodir/$checklog
fi
done < <(tar ztf $repo)
}
# /CHECK
# UPDATEPKGBUILD
updatepkgbuild(){
echo "==> Updating local PKGBUILD from AUR."
(( ${#pkgs[@]} == 0 )) \
&& [[ $FROMLOG == 0 ]] \
&& copy_log_to_pkgs "$updatelog"
if (( ${#pkgs[@]} == 0 )); then
wget_repo
IFS=$'\n' read -d '' -a lines < <(tar ztf "$repo")
for line in "${lines[@]}"; do
#for i in $(tar -tf $repo | sed -n '/\/$/s/.$//p'); do
[[ $line = */ ]] || continue
i="${line%/}"
pkg=${i%-*-*}
read -p " -> $pkg: update? (y/n) " answer
[[ "$answer" == "y" ]] && wget_tarball "$pkg"
done
else
for pkg in "${pkgs[@]}"; do
wget_tarball "$pkg"
done
fi
}
# /UPDATEPKGBUILD
# BUILD
build(){
# filter & replace $pkgs from checklog if asked
if (( ${#pkgs[@]} == 0 )); then
if [[ $FROMLOG == "0" ]]; then
copy_log_to_pkgs "$checklog"
else
die "==> Nothing to build."
fi
fi
for pkg in "${pkgs[@]}"; do
sudo=""
asroot=""
i=""
echo "==> $pkg"
cd $builddir
if [[ $noconfirm == 0 ]]; then
# aur
[[ $aur == "0" ]] && wget_tarball $pkg
# root
[[ $root == "0" ]] && sudo="sudo" && asroot="--asroot"
# install
[[ $install == "0" ]] && i="-i"
# skipmd5sums
[[ $skipmd5sums == "0" ]] && skipinteg="--skipinteg"
# makepkg
cd $pkg && $sudo makepkg $i -s $asroot $skipinteg
post_build $pkg
else
# build?
read -p " -> do you want upgrade? (y/n) " answer
if [[ "$answer" == "y" ]]; then
# aur
if [[ $aur == "0" ]]; then
wget_tarball $pkg
else
read -p " -> Do you want get tarball from AUR? (y/n) " answer
[[ "$answer" == "y" ]] && wget_tarball $pkg
fi
# root
if [[ $root == "0" ]]; then
sudo="sudo"
asroot="--asroot"
else
read -p " -> Do you want build as root? (y/n) " answer
[[ "$answer" == "y" ]] && sudo="sudo" && asroot="--asroot"
fi
# install
if [[ $install == "0" ]]; then
i="-i"
else
read -p " -> Do you want install package after build? (y/n) " answer
[[ "$answer" == "y" ]] && i="-i"
fi
# skipmd5sums
if [[ $skipmd5sums == "0" ]]; then
skipinteg="--skipinteg"
else
read -p " -> Do you want skip md5sums check? (y/n) " answer
[[ "$answer" == "y" ]] && skipinteg="--skipinteg"
fi
# makepkg
cd $pkg && $sudo makepkg $i -s $asroot $skipinteg
post_build $pkg
fi
fi
done
# show built packages
copy_log_to_pkgs "$buildlog"
echo "==> Packages waiting to be added:"
for pkg in "${pkgs[@]}"; do
echo " -> $pkg"
done
}
# /BUILD
# ADD
add(){
cd $repodir
# init
[[ ! -s $repodir/$buildlog ]] \
&& die "==> Nothing to add, ckit -B packages needed!"
wget_repo
# repo-add
echo "==> Adding packages queued"
for file in *.pkg.tar.gz; do
printf " -> $file... "
repo-add $repo $file &>/dev/null && \
echo "done!" || \
echo "failed!"
done
# db
lftp_put_repo
# delete previous packages
echo "==> Deleting previous packages"
copy_log_to_pkgs "$buildlog"
for pkg in "${pkgs[@]}"; do
lftp_glob_rm "$pkg" &>/dev/null
[[ "$RESULT" != "" ]] && \
echo " -> $RESULT done!" || \
echo " -> $pkg not found."
done
rm $buildlog $checklog
#invio i nuovi
echo "==> Uploading packages"
for file in *.pkg.tar.gz; do
printf " -> $file... "
if lftp_run "put $file" &>/dev/null; then
echo "done!"
mv $file $cachedir
else
echo "failed!"
fi
done
echo "==> Repository updated! Gj, see ya."
}
# /ADD
# REMOVE
remove(){
# init
(( ${#pkgs[@]} == 0 )) && die "==> Packages needed!"
cd $repodir
wget_repo
echo "==> Removing from db"
for pkg in "${pkgs[@]}"; do
printf " -> $pkg... "
repo-remove $repo $pkg &>/dev/null \
&& echo "done!" \
|| echo "failed!"
done
lftp_put_repo
echo "==> Removing from ftp"
for pkg in "${pkgs[@]}"; do
lftp_glob_rm "$pkg" &>/dev/null
[[ "$RESULT" != "" ]] && \
echo " -> $RESULT done!" || \
echo " -> $pkg not found."
done
}
# /REMOVE
# HELP
help(){
echo "==> CKIT - Construction KIT!"
echo "==> Preprocessing:"
echo " -> -D packages: delete sources from package's directory"
echo " -> -U[L]: Update tarball from AUR"
echo " -> -UL: Update tarball from AUR by updatelog"
echo " -> -O: Own package"
echo " -> -E: Edit a file from package"
echo " -> -h: This help"
echo "==> Processing:"
echo " -> -B[b][a][r][i][s][n][L] packages: build packages."
echo " -> -Bb: build all packages, don't need with -n"
echo " -> -Ba: get tarball from AUR"
echo " -> -Br: build as root"
echo " -> -Bi: install packages after builds"
echo " -> -Bs: skip integrity check"
echo " -> -Bn: don't ask confirm"
echo " -> -BL: build from checklog"
echo " -> -L: edit log files"
echo " -> -C: check for newer version of packages"
echo " -> -R packages: remove packages from repository"
echo "==> Postprocessing:"
echo " -> -A: add built packages"
echo " -> -H: clear cache"
echo " -> -T: restore remote db from a failed upload"
}
# /HELP
#################### /PUBLIC INTERFACES ####################
#################### MAIN ####################
logs=( "$buildlog" "$checklog" "$updatelog" "$deletelog" )
for log in "${logs[@]}"; do
[[ ! -f $repodir/$log ]] && touch $repodir/$log
done
test -z "$1" && die "==> RTFM, see ya!"
# primary
ADD=1
BUILD=1
CHECK=1
REMOVE=1
BUILDFROMCHECK=1
UPDATEPKGBUILD=1
CLEARCACHE=1
RESTOREDB=1
OWNPKG=1
EDITPKG=1
DELETESRC=1
HELP=1
FROMLOG=1
# secondary
buildall=1
aur=1
root=1
install=1
skipmd5sums=1
noconfirm=1
x=1 # Avoids an error if we get no options at all.
while getopts "ABarisnCRUHLTOEDh" opt; do
case "$opt" in
A) ADD=0;;
B) BUILD=0;;
a) aur=0;;
r) root=0;;
i) install=0;;
s) skipmd5sums=0;;
n) noconfirm=0;;
C) CHECK=0;;
R) REMOVE=0;;
U) UPDATEPKGBUILD=0;;
H) CLEARCACHE=0;;
L) FROMLOG=0;;
T) RESTOREDB=0;;
O) OWNPKG=0;;
E) EDITPKG=0;;
D) DELETESRC=0;;
h) HELP=0;;
esac
x=$OPTIND
done
shift $(($x-1))
pkgs=("$@")
# rule
if [[ $REMOVE == "0" ]]; then
[[ $BUILD == "0" ]] && die "==> Not allowed."
[[ $RESTOREDB == "0" ]] && die "==> Not allowed."
[[ $ADD == "0" ]] && die "==> Not allowed."
fi
[[ $DELETESRC == "0" ]] && [[ $UPDATEPKGBUILD == "0" ]] && die "==> Not allowed."
# preproccessing
[[ $FROMLOG == 0 ]] && [[ $UPDATEPKGBUILD == 1 ]] && [[ $BUILD == 1 ]] && [[ $DELETESRC == 1 ]] && editlog
[[ $UPDATEPKGBUILD == 0 ]] && updatepkgbuild
[[ $OWNPKG == 0 ]] && ownpkg
[[ $EDITPKG == 0 ]] && editpkg
[[ $DELETESRC == 0 ]] && deletesrc
[[ $HELP == 0 ]] && help
# processing
[[ $BUILD == 0 ]] && build
[[ $CHECK == 0 ]] && check
[[ $REMOVE == 0 ]] && remove
# postprocessing
[[ $ADD == 0 ]] && add
[[ $CLEARCACHE == 0 ]] && clearcache
[[ $RESTOREDB == 0 ]] && restoredb
#################### /MAIN ####################