diff --git a/LICENSE b/LICENSE
index f288702..94a9ed0 100644
--- a/LICENSE
+++ b/LICENSE
@@ -1,7 +1,7 @@
GNU GENERAL PUBLIC LICENSE
Version 3, 29 June 2007
- Copyright (C) 2007 Free Software Foundation, Inc.
+ Copyright (C) 2007 Free Software Foundation, Inc.
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
@@ -645,7 +645,7 @@ the "copyright" line and a pointer to where the full notice is found.
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 .
+ along with this program. If not, see .
Also add information on how to contact you by electronic and paper mail.
@@ -664,11 +664,11 @@ might be different; for a GUI interface, you would use an "about box".
You should also get your employer (if you work as a programmer) or school,
if any, to sign a "copyright disclaimer" for the program, if necessary.
For more information on this, and how to apply and follow the GNU GPL, see
-.
+.
The GNU General Public License does not permit incorporating your program
into proprietary programs. If your program is a subroutine library, you
may consider it more useful to permit linking proprietary applications with
the library. If this is what you want to do, use the GNU Lesser General
Public License instead of this License. But first, please read
-.
+.
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..adf37ba
--- /dev/null
+++ b/README.md
@@ -0,0 +1,2 @@
+# arch-pkgbuilder
+Arch packages builder solution
diff --git a/_dist/arch/PKGBUILD b/_dist/arch/PKGBUILD
new file mode 100644
index 0000000..a608a44
--- /dev/null
+++ b/_dist/arch/PKGBUILD
@@ -0,0 +1,45 @@
+# Maintainer: MatMoul
+
+pkgname=pkgbuilder
+pkgver=0.0.0
+pkgrel=1
+pkgdesc="Arch packages builder solution"
+arch=('any')
+url="https://github.com/MatMoul/arch-pkg-builder"
+license=('GPL3')
+depends=('git' 'pacman-contrib' 'jq')
+optdepends=(
+ 'msmtp-mta: For mail notification'
+ 'postfix: For mail notification'
+ 'apache: Web server for your repos'
+ 'nginx: Web server for your repos'
+ 'pacoloco: Pacman caching proxy server'
+)
+source=("${pkgname}::git+https://github.com/matmoul/arch-pkg-builder.git" 'pkgbuilder.sysusers')
+md5sums=('SKIP' 'SKIP')
+backup=('etc/pkgbuilder/config' 'etc/pkgbuilder/targets/local-test')
+
+package() {
+ install -D -m0644 pkgbuilder.sysusers ${pkgdir}/usr/lib/sysusers.d/pkgbuilder.conf
+ cd ${pkgname}
+ git checkout m3
+ install -d -m0755 ${pkgdir}/etc/pkgbuilder/packages
+ install -d -m0755 ${pkgdir}/etc/pkgbuilder/targets
+ install -d -m0755 ${pkgdir}/usr/share/pkgbuilder
+ install -d -m0755 ${pkgdir}/var/lib/pkgbuilder/packages/local-test
+ install -d -m0755 ${pkgdir}/var/lib/pkgbuilder/repos/local-test
+ install -d -m0755 ${pkgdir}/usr/share/pkgbuilder/plugins
+ install -d -m0755 ${pkgdir}/usr/share/pkgbuilder/models
+ install -d -m0755 ${pkgdir}/usr/share/bash-completion/completions
+ install -d -m0755 ${pkgdir}/usr/lib/systemd/system
+ install -D -m0644 LICENSE ${pkgdir}/usr/share/licenses/pkgbuilder/LICENSE
+ install -D -m0644 config ${pkgdir}/etc/pkgbuilder/config
+ install -D -m0644 plugins/* ${pkgdir}/usr/share/pkgbuilder/plugins
+ #install -D -d -m0644 models/* ${pkgdir}/usr/share/pkgbuilder/models
+ cp -r models/* ${pkgdir}/usr/share/pkgbuilder/models
+ install -D -m0644 targets/local-test ${pkgdir}/etc/pkgbuilder/targets/local-test
+ install -D -m0755 bin/pkgbuilder ${pkgdir}/usr/bin/pkgbuilder
+ install -D -m0755 bin/buildpkg ${pkgdir}/usr/bin/buildpkg
+ install -D -m0644 completion/bash/* ${pkgdir}/usr/share/bash-completion/completions
+ install -D -m0644 systemd/* ${pkgdir}/usr/lib/systemd/system
+}
diff --git a/_dist/arch/pkgbuilder.sysusers b/_dist/arch/pkgbuilder.sysusers
new file mode 100644
index 0000000..d9f4121
--- /dev/null
+++ b/_dist/arch/pkgbuilder.sysusers
@@ -0,0 +1 @@
+u pkgbuilder - "pkgbuilder" /tmp/pkgbuilder /sbin/nologin
diff --git a/bin/buildpkg b/bin/buildpkg
new file mode 100755
index 0000000..7e8ce4a
--- /dev/null
+++ b/bin/buildpkg
@@ -0,0 +1,199 @@
+#!/bin/bash
+
+help() {
+ echo "buildpkg [options] pkgdir"
+ echo "-w | --workdir dir"
+ echo "-b | --basedirname dirname"
+ echo "-u | --builduser username"
+ echo "-m | --mirror url"
+ echo "-d | --mount dir"
+ echo "-r | --repo name"
+ echo "-r | --repo name|url"
+ echo "-p | --pkgs pkglist"
+ echo "-o | --outputdir dir"
+ echo "-n | --nodeps"
+ echo "--dbg"
+ echo "--help"
+}
+
+build() {
+ BASEDIR=${WORKDIR}/${BASEDIRNAME}
+ BUILDDIR=${WORKDIR}/${BUILDDIRNAME}
+ if ! checkbuildbase; then
+ return 1
+ fi
+ if ! createbuildroot; then
+ cleanbuildroot
+ return 1
+ fi
+ if ! configurebuildroot; then
+ cleanbuildroot
+ return 1
+ fi
+ if ! buildpkg; then
+ cleanbuildroot
+ return 1
+ fi
+ cleanbuildroot
+}
+checkbuildbase() {
+ if [ ! -d "${WORKDIR}" ]; then
+ if ! mkdir -p "${WORKDIR}"; then
+ return 1
+ fi
+ fi
+ if [ -d "${BASEDIR}" ]; then
+ cp /etc/resolv.conf "${BASEDIR}"/etc/
+ cp /etc/pacman.d/mirrorlist "${BASEDIR}"/etc/pacman.d/
+ if ! systemd-nspawn -a -D "${BASEDIR}" pacman -Syu --noconfirm; then
+ return 1
+ fi
+ else
+ if [[ $(stat -f -c %T "${WORKDIR}") == "btrfs" ]]; then
+ if ! btrfs subvolume create "${BASEDIR}"; then
+ return 1
+ fi
+ else
+ if ! mkdir -p "${BASEDIR}"; then
+ return 1
+ fi
+ fi
+ mkdir -p "${BASEDIR}"/var/lib/pacman
+ if ! pacman -Sy -r "${BASEDIR}" --noconfirm base-devel; then
+ return 1
+ fi
+ cp /etc/resolv.conf "${BASEDIR}"/etc/
+ cp /etc/pacman.d/mirrorlist "${BASEDIR}"/etc/pacman.d/
+ if ! systemd-nspawn -a -D "${BASEDIR}" pacman-key --init; then
+ return 1
+ fi
+ if ! systemd-nspawn -a -D "${BASEDIR}" pacman-key --populate; then
+ return 1
+ fi
+ fi
+}
+createbuildroot() {
+ if [ -d "${BUILDDIR}" ]; then
+ if ! rm -r "${BUILDDIR}"; then
+ return 1
+ fi
+ fi
+ if [[ $(stat -f -c %T "${WORKDIR}") == "btrfs" ]]; then
+ if ! btrfs subvolume snapshot "${BASEDIR}" "${BUILDDIR}"; then
+ return 1
+ fi
+ else
+ # CAUTION: /tmp is mounted with nosuid and is not useable as is
+ if ! cp -r "${BASEDIR}" "${BUILDDIR}"; then
+ return 1
+ fi
+ fi
+ if [[ "${MOUNTDIR}" != "" ]]; then
+ mkdir -p "${BUILDDIR}${MOUNTDIR}"
+ mount -o bind -o ro "${MOUNTDIR}" "${BUILDDIR}${MOUNTDIR}"
+ fi
+ sed -i -e '/ParallelDownloads/ s/^#*/#/' "${BUILDDIR}"/etc/pacman.conf
+ sed -i -e '/MAKEFLAGS=/ s/^#*/#/' "${BUILDDIR}"/etc/makepkg.conf
+ local -r CPUCORES=$(grep -c ^processor /proc/cpuinfo)
+ sed -i "s/^MAKEFLAGS=.*/MAKEFLAGS=\"-j${CPUCORES}\"/" "${BUILDDIR}"/etc/makepkg.conf
+}
+configurebuildroot() {
+ if ! systemd-nspawn -a -D "${BUILDDIR}" useradd -r -m "${BUILDUSER}"; then
+ return 1
+ fi
+ echo "${BUILDUSER} ALL=(root) NOPASSWD: /usr/bin/pacman" > "${BUILDDIR}"/etc/sudoers.d/"${BUILDUSER}"
+ if ! cp -r "${PKGDIR}" "${BUILDDIR}"/home/"${BUILDUSER}"/pkg; then
+ return 1
+ fi
+ if ! systemd-nspawn -a -D "${BUILDDIR}" chown -R "${BUILDUSER}":"${BUILDUSER}" /home/"${BUILDUSER}"/pkg; then
+ return 1
+ fi
+ if [ "${MIRROR}" != "" ]; then
+ echo "Server = ${MIRROR}" > "${BUILDDIR}"/etc/pacman.d/mirrorlist
+ fi
+
+ if [ "${REPOS}" != "" ]; then
+ for REPODATA in "${REPOS[@]}"; do
+ readarray -d "|" -t REPOITEMS<<<"${REPODATA}"
+ if [ "${REPOITEMS[1]}" == "" ]; then
+ if grep "\[${REPODATA}\]" /etc/pacman.conf; then
+ sed -i -e "/\[${REPODATA}\]/ {s/#//;}" "${BUILDDIR}"/etc/pacman.conf
+ sed -i -e "/\[${REPODATA}\]/ {n;s/#//;}" "${BUILDDIR}"/etc/pacman.conf
+ else
+ echo -e "\n[${REPODATA}]\nInclude = /etc/pacman.d/mirrorlist" >> "${BUILDDIR}"/etc/pacman.conf
+ fi
+ else
+ echo -e "\n[${REPOITEMS[0]}]\nSigLevel = Optional TrustAll\nServer = ${REPOITEMS[1]}" >> "${BUILDDIR}"/etc/pacman.conf
+ fi
+ done
+ if ! systemd-nspawn -a -D "${BUILDDIR}" pacman -Sy; then
+ return 1
+ fi
+ fi
+ if [ "${PKGS}" != "" ]; then
+ if ! systemd-nspawn -a -D "${BUILDDIR}" pacman -S --needed --noconfirm "${PKGS[@]}"; then
+ return 1
+ fi
+ fi
+}
+buildpkg() {
+ if [ ${NODEPS} == 0 ]; then
+ if ! systemd-nspawn -a -D "${BUILDDIR}" --chdir=/home/"${BUILDUSER}"/pkg --user="${BUILDUSER}" makepkg -s --needed --noconfirm; then
+ return 1
+ fi
+ else
+ if ! systemd-nspawn -a -D "${BUILDDIR}" --chdir=/home/"${BUILDUSER}"/pkg --user="${BUILDUSER}" makepkg -s -d --needed --noconfirm; then
+ return 1
+ fi
+ fi
+ if ! cp "${BUILDDIR}"/home/"${BUILDUSER}"/pkg/*.pkg.tar.zst "${OUTPUTDIR}"; then
+ return 1
+ fi
+}
+cleanbuildroot() {
+ if [[ "${MOUNTDIR}" != "" ]]; then
+ umount "${BUILDDIR}${MOUNTDIR}"
+ fi
+ if [ ${DBGMODE} == 0 ]; then
+ rm -r "${BUILDDIR}"
+ fi
+}
+
+if [ ${#} == 0 ]; then
+ help
+ exit 1
+fi
+
+PKGDIR=${*: -1}
+WORKDIR=/var/cache/pkgbuilder/
+BASEDIRNAME=arch-base
+BASEDIR=""
+BUILDDIRNAME=$(date "+%Y-%m-%d_%H-%M-%S")
+BUILDDIR=""
+BUILDUSER=pkgbuilder
+MOUNTDIR=""
+MIRROR=""
+REPOS=()
+PKGS=()
+OUTPUTDIR=$(pwd)
+NODEPS=0
+DBGMODE=0
+
+while [[ ${#} -gt 0 ]]; do
+ case ${1} in
+ --help) help; exit 0;;
+ -w | --workdir) WORKDIR="${2}"; shift; shift;;
+ -b | --basedirname) BASEDIRNAME="${2}"; shift; shift;;
+ -u | --builduser) BUILDUSER="${2}"; shift; shift;;
+ -d | --mount) MOUNTDIR=${2}; shift; shift;;
+ -m | --mirror) MIRROR="${2}"; shift; shift;;
+ -r | --repo) REPOS+=("${2}"); shift; shift;;
+ -p | --pkgs) PKGS+=("${2}"); shift; shift;;
+ -o | --outputdir) OUTPUTDIR="${2}"; shift; shift;;
+ -n | --nodeps) NODEPS=1; shift;;
+ --dbg) DBGMODE=1; shift;;
+ *) shift;;
+ esac
+done
+
+build
diff --git a/bin/pkgbuilder b/bin/pkgbuilder
new file mode 100755
index 0000000..35038cd
--- /dev/null
+++ b/bin/pkgbuilder
@@ -0,0 +1,388 @@
+#!/bin/bash
+
+showHelp() {
+ echo "arch-pkg-builder"
+ echo "----------------"
+ echo "arch-pkg-builder [args] command [args]"
+ echo ""
+ echo "command :"
+ echo " list List packages infos"
+ echo " infos pkgname Display package infos"
+ echo " build pkgname Build and publish package"
+ echo " bump pkgname Bump release and publish package"
+ echo " checkupdate pkgname Check package update"
+ echo " checkupdateall Check all packages update"
+ echo " update pkgname Update package"
+ echo " updateall Update all packages"
+ echo ""
+ echo "args :"
+ echo " --cnf configfile"
+ echo " --notify"
+ echo " --nopush"
+ echo " --dry-run"
+ echo " --dbg"
+}
+
+readSetting() { # $1=filename $2=name $3=defaultvalue
+ local -r LINE=$(grep "^${2}=" "${1}")
+ local -r VALUE=${LINE/${2}=/}
+ if [ "${VALUE}" != "" ]; then
+ echo "${VALUE}"
+ else
+ echo "${3}"
+ fi
+}
+writeSetting() { #$1=filename $2=valuename $3=value
+ local -r LINE=$(grep "^${2}=" "${1}")
+ if [ "${LINE}" != "" ]; then
+ sed -i "s/^${2}=.*/${2}=${3}/" "${1}"
+ else
+ echo "${2}=${3}" >> "${1}"
+ fi
+}
+tblCell() { #$1=Text $2=Size
+ local CELL=""
+ CELL=$(printf "%-${2}s")
+ CELL="${1}${CELL}"
+ CELL=${CELL:0:${2}}
+ echo "${CELL}"
+}
+getPluginFile() { # $1=PKGDIR $2=PKGNAME $3=PLUGINDIR
+ local -r PKGDIR=${1}
+ local -r PKGNAME=${2}
+ local -r PLUGINDIR=${3}
+ local -r PLUGIN=$(readSetting "${PKGDIR}"/"${PKGNAME}"/settings "plugin" "manual")
+ if [ "${PLUGIN}" == "custom" ]; then
+ if [ ! -f "${PKGDIR}"/"${PKGNAME}"/plugin ]; then
+ return 1
+ fi
+ echo "${PKGDIR}"/"${PKGNAME}"/plugin
+ else
+ if [ ! -f "${PLUGINDIR}"/"${PLUGIN}" ]; then
+ return 1
+ fi
+ echo "${PLUGINDIR}"/"${PLUGIN}"
+ fi
+}
+notify() {
+ if [ ${NOTIFY} == 0 ]; then
+ return 0
+ fi
+ if [ "${NOTIFYMSG}" == "" ]; then
+ return 0
+ fi
+ if [ ! -f /usr/bin/sendmail ]; then
+ return 0
+ fi
+ local EMAIL=""
+ EMAIL=$(readSetting "${CNFFILE}" "EMAIL" "")
+ if [ "${EMAIL}" == "" ]; then
+ return 0
+ fi
+ echo -e "subject:PKGBuilder - Notifications\n${NOTIFYMSG}" | sendmail "${EMAIL}"
+}
+
+pkgList() {
+ if [ ! -d "${PKGDIR}" ]; then
+ return 1
+ fi
+ for PKGDIRNAME in "${PKGDIR}"/*; do
+ [[ -e "${PKGDIRNAME}" ]] || break
+ local PKGNAME=""
+ PKGNAME=$(basename "${PKGDIRNAME}")
+ local VALUES=()
+ VALUES+=("$(tblCell "${PKGNAME}" 30)")
+ VALUE=$(tblCell "$(readSetting "${PKGDIRNAME}"/settings version)" 24)
+ VALUES+=("${VALUE}")
+ VALUES+=("$(tblCell "$(readSetting "${PKGDIRNAME}"/settings plugin)" 20)")
+ VALUES+=("$(tblCell "$(readSetting "${PKGDIRNAME}"/settings target)" 20)")
+ VALUE=$(tblCell "$(readSetting "${PKGDIRNAME}"/settings lastbuilddate)" 20)
+ VALUES+=("${VALUE}")
+ VALUES+=("$(readSetting "${PKGDIRNAME}"/settings lastbuildstatus)")
+ echo "${VALUES[@]}"
+ done
+}
+pkgInfos() { # $1=PKGNAME
+ local -r PKGNAME=${1}
+ if [ ! -f "${PKGDIR}"/"${PKGNAME}"/settings ]; then
+ return 1
+ fi
+ cat "${PKGDIR}"/"${PKGNAME}"/settings
+}
+pkgCreate() { # $1=PKGNAME $2=MODELNAME
+ local -r PKGNAME=${1}
+ local -r MODELNAME=${2}
+ if [ ! -d "${MODELDIR}"/"${MODELNAME}" ]; then
+ return 1
+ fi
+ cp -r "${MODELDIR}"/"${MODELNAME}" "${PKGDIR}"/"${PKGNAME}"
+}
+pkgBuild() { # $1=PKGNAME
+ local -r PKGNAME=${1}
+ local -r BUILDDATE=$(date "+%Y.%m.%d %H:%M:%S")
+ if [[ "${DRYRUN}" == "0" ]]; then
+ writeSetting "${PKGDIR}"/"${PKGNAME}"/settings "lastbuilddate" "${BUILDDATE}"
+ fi
+ local PLUGINFILE=""
+ if ! PLUGINFILE=$(getPluginFile "${PKGDIR}" "${PKGNAME}" "${PLUGINDIR}"); then
+ return 1
+ fi
+ . "${PLUGINFILE}"
+ local PKGFILES=""
+ if ! PKGFILES=$(plugin_getpkgfiles "${PKGDIR}" "${PKGNAME}"); then
+ if [[ "${DRYRUN}" == "0" ]]; then
+ writeSetting "${PKGDIR}"/"${PKGNAME}"/settings "lastbuildstatus" "Error - No PKG files provided"
+ fi
+ return 1
+ fi
+ if [ ! -d "${PKGFILES}" ]; then
+ if [[ "${DRYRUN}" == "0" ]]; then
+ writeSetting "${PKGDIR}"/"${PKGNAME}"/settings "lastbuildstatus" "Error - PKG files not found"
+ fi
+ return 1
+ fi
+ mkdir "${WORKDIR}"/.output
+ local BUILDARGS=()
+ BUILDARGS+=(-w "${WORKDIR}")
+ BUILDARGS+=(-d /var/lib/pkgbuilder)
+ BUILDARGS+=(-o "${WORKDIR}"/.output)
+ local -r PKGMIRROR=$(readSetting "${PKGDIR}"/"${PKGNAME}"/settings "mirror" "")
+ if [[ "${PKGMIRROR}" != "" ]]; then
+ BUILDARGS+=(-m "${PKGMIRROR}")
+ fi
+ # shellcheck disable=SC2207
+ local -r PKGPKGS=($(readSetting "${PKGDIR}"/"${PKGNAME}"/settings "pkgs" ""))
+ if [[ "${PKGPKGS[*]}" != "" ]]; then
+ for PKGPKG in "${PKGPKGS[@]}"; do
+ BUILDARGS+=(-p "${PKGPKG}")
+ done
+ fi
+ local -r PKGNODEPS=$(readSetting "${PKGDIR}"/"${PKGNAME}"/settings "nodeps" "")
+ if [[ "${PKGNODEPS}" == "1" ]]; then
+ BUILDARGS+=(-n)
+ fi
+ # shellcheck disable=SC2207
+ local -r PKGREPOS=($(readSetting "${PKGDIR}"/"${PKGNAME}"/settings "repos" ""))
+ if [[ "${PKGREPOS[*]}" != "" ]]; then
+ for PKGREPO in "${PKGREPOS[@]}"; do
+ BUILDARGS+=(-r "${PKGREPO}")
+ done
+ fi
+ if [[ "${DBGMODE}" == "1" ]]; then
+ BUILDARGS+=(--dbg)
+ fi
+ BUILDARGS+=("${PKGFILES}")
+ # shellcheck disable=SC2068
+ if ! buildpkg ${BUILDARGS[@]}; then
+ if [[ "${DRYRUN}" == "0" ]]; then
+ writeSetting "${PKGDIR}"/"${PKGNAME}"/settings "lastbuildstatus" "Error - Build"
+ fi
+ return 1
+ fi
+ local PKGFILENAME=""
+ PKGFILENAME=$(ls "${WORKDIR}"/.output/"${PKGNAME}"*.pkg.tar.zst)
+ local VERSION=""
+ VERSION=$(pacman -Qp "${PKGFILENAME}" | awk -F ' ' '{print $2}')
+ if [[ "${DRYRUN}" == "0" ]]; then
+ writeSetting "${PKGDIR}"/"${PKGNAME}"/settings "version" "${VERSION}"
+ writeSetting "${PKGDIR}"/"${PKGNAME}"/settings "builddate" "${BUILDDATE}"
+ writeSetting "${PKGDIR}"/"${PKGNAME}"/settings "lastbuildstatus" "Ok"
+ fi
+ local -r PKGTARGET=$(readSetting "${PKGDIR}"/"${PKGNAME}"/settings "target" "")
+ if [[ "${DRYRUN}" == "0" ]]; then
+ if [[ "${NOPUSH}" == "0" ]]; then
+ if [ ! -d "${VARDIR}"/packages/"${PKGTARGET}" ]; then
+ mkdir -p "${VARDIR}"/packages/"${PKGTARGET}"
+ fi
+ cp "${PKGFILENAME}" "${VARDIR}"/packages/"${PKGTARGET}"
+ fi
+ fi
+ pkgPush "${PKGNAME}" "${PKGFILENAME}"
+ rm -r "${WORKDIR}"/.output
+}
+pkgPush() { # $1=PKGNAME $2=PKGFILE
+ local -r PKGNAME=${1}
+ local -r PKGFILE=${2}
+
+ if [[ ${NOPUSH} == 0 ]]; then
+ local -r PKGTARGET=$(readSetting "${PKGDIR}"/"${PKGNAME}"/settings "target" "")
+ if [ -f "${TRGDIR}"/"${PKGTARGET}" ]; then
+ local -r PKGTARGETTYPE=$(readSetting "${TRGDIR}"/"${PKGTARGET}" "type" "")
+ local -r TARGETDEST=$(readSetting "${TRGDIR}"/"${PKGTARGET}" "dest" "")
+ if [[ "${DRYRUN}" == "0" ]]; then
+ case ${PKGTARGETTYPE} in
+ dir)
+ if [ -d "${TARGETDEST}" ]; then
+ local -r TARGETFILENAME=${TARGETDEST}/$(basename "${PKGFILE}")
+ cp "${PKGFILE}" "${TARGETFILENAME}"
+ repo-add -n -R "${TARGETDEST}/${PKGTARGET}.db.tar.zst" "${TARGETFILENAME}"
+ fi
+ ;;
+ ssh)
+ local -r TARGETPUBKEY=$(readSetting "${TRGDIR}"/"${PKGTARGET}" "pubkey" "")
+ local -r TARGETSRV=$(awk -F':/' '{print $1}' <<< "${TARGETDEST}")
+ local -r TARGETDIR=/$(awk -F':/' '{print $2}' <<< "${TARGETDEST}")
+ local -r TARGETFILENAME=${TARGETDEST}/$(basename "${PKGFILE}")
+ if [ "${TARGETPUBKEY}" == "" ]; then
+ scp "${PKGFILE}" "${TARGETDEST}"
+ ssh "${TARGETSRV}" repo-add -n -R "${TARGETDIR}"/"${PKGTARGET}".db.tar.zst "${TARGETDIR}"/"$(basename "${TARGETFILENAME}")"
+ else
+ scp -i "${TARGETPUBKEY}" "${PKGFILE}" "${TARGETDEST}"
+ ssh -i "${TARGETPUBKEY}" "${TARGETSRV}" repo-add -n -R "${TARGETDIR}"/"${PKGTARGET}".db.tar.zst "${TARGETDIR}"/"$(basename "${TARGETFILENAME}")"
+ fi
+ ;;
+ esac
+ fi
+ fi
+ fi
+}
+pkgBump() { # $1=PKGNAME
+ local -r PKGNAME=${1}
+
+ local PLUGINFILE=""
+ if ! PLUGINFILE=$(getPluginFile "${PKGDIR}" "${PKGNAME}" "${PLUGINDIR}"); then
+ return 1
+ fi
+ . "${PLUGINFILE}"
+ if ! plugin_isbumpable; then
+ return 1
+ fi
+
+ if [[ "${DRYRUN}" == "0" ]]; then
+ if ! plugin_bump "${PKGDIR}" "${PKGNAME}"; then
+ return 1
+ fi
+ pkgBuild "${PKGNAME}"
+ fi
+}
+pkgCheckUpdate() { # $1=PKGNAME
+ local -r PKGNAME=${1}
+
+ local PLUGINFILE=""
+ if ! PLUGINFILE=$(getPluginFile "${PKGDIR}" "${PKGNAME}" "${PLUGINDIR}"); then
+ return 1
+ fi
+ . "${PLUGINFILE}"
+ local -r PKGVERSION=$(readSetting "${PKGDIR}"/"${PKGNAME}"/settings "version" "0")
+ local -r PKGPLUGIN=$(readSetting "${PKGDIR}"/"${PKGNAME}"/settings "plugin" "")
+ local VALUES=()
+ VALUES+=("$(tblCell "${PKGNAME}" 30)")
+ VALUE=$(tblCell "$(readSetting "${PKGDIR}"/"${PKGNAME}"/settings version)" 24)
+ VALUES+=("${VALUE}")
+ if ! plugin_isupdatable; then
+ VALUES+=(" ")
+ VALUES+=("$(tblCell 'Skipping' 25)")
+ VALUES+=("$(tblCell "${PKGPLUGIN}" 25)")
+ echo "${VALUES[@]}"
+ return 0
+ fi
+ local -r ONLINEVERSION=$(plugin_getlatestversion)
+ if [ "${ONLINEVERSION}" == "" ]; then
+ return 1
+ fi
+ if [[ "${ONLINEVERSION}" != "${PKGVERSION}" ]]; then
+ VALUES+=(" -> ")
+ VALUES+=("$(tblCell "${ONLINEVERSION}" 25)")
+ NOTIFYMSG+="${PKGNAME} ${PKGVERSION} -> ${ONLINEVERSION}\n"
+ else
+ VALUES+=(" ")
+ VALUES+=("$(tblCell 'Up to date' 25)")
+ fi
+ VALUES+=("$(tblCell "${PKGPLUGIN}" 25)")
+ echo "${VALUES[@]}"
+}
+pkgCheckUpdateAll() {
+ if [ ! -d "${PKGDIR}" ]; then
+ return 1
+ fi
+ for PKGDIRNAME in "${PKGDIR}"/*; do
+ [[ -e "${PKGDIRNAME}" ]] || break
+ local PKGNAME=""
+ PKGNAME=$(basename "${PKGDIRNAME}")
+ pkgCheckUpdate "${PKGNAME}"
+ done
+ notify
+}
+pkgUpdate() { # $1=PKGNAME
+ local -r PKGNAME=${1}
+
+ local PLUGINFILE=""
+ if ! PLUGINFILE=$(getPluginFile "${PKGDIR}" "${PKGNAME}" "${PLUGINDIR}"); then
+ return 1
+ fi
+ . "${PLUGINFILE}"
+ if ! plugin_isupdatable; then
+ return 1
+ fi
+
+ local -r ONLINEVERSION=$(plugin_getlatestversion)
+ if [ "${ONLINEVERSION}" == "" ]; then
+ return 1
+ fi
+ local -r PKGVERSION=$(readSetting "${PKGDIR}"/"${PKGNAME}"/settings "version" "0")
+ if [[ "${ONLINEVERSION}" == "${PKGVERSION}" ]]; then
+ return 0
+ fi
+
+ if ! plugin_update; then
+ return 1
+ fi
+
+ pkgBuild "${PKGNAME}"
+}
+pkgUpdateAll() {
+ if [ ! -d "${PKGDIR}" ]; then
+ return 1
+ fi
+ for PKGDIRNAME in "${PKGDIR}"/*; do
+ [[ -e "${PKGDIRNAME}" ]] || break
+ local PKGNAME=""
+ PKGNAME=$(basename "${PKGDIRNAME}")
+ pkgUpdate "${PKGNAME}"
+ done
+}
+
+CNFFILE="/etc/pkgbuilder/config"
+ARGCMD=""
+ARGPKG=""
+ARGMDL=""
+NOTIFYMSG=""
+NOTIFY=0
+NOPUSH=0
+DRYRUN=0
+DBGMODE=0
+
+while [[ ${#} -gt 0 ]]; do
+ case ${1} in
+ --help) showHelp; exit 0;;
+ list | checkupdateall | updateall) ARGCMD="${1}"; shift;;
+ infos | build | bump | checkupdate | update) ARGCMD="${1}"; ARGPKG="${2}"; shift; shift;;
+ create) ARGCMD="${1}"; ARGMDL="${2}"; ARGPKG="${3}"; shift; shift;;
+ --cnf) CNFFILE="${2}"; shift; shift;;
+ --notify) NOTIFY=1; shift;;
+ --nopush) NOPUSH=1; shift;;
+ --dry-run) DRYRUN=1; shift;;
+ --dbg) DBGMODE=1; shift;;
+ *) shift;;
+ esac
+done
+
+PKGDIR=$(readSetting "${CNFFILE}" "PKGDIR" "/etc/pkgbuilder/packages")
+TRGDIR=$(readSetting "${CNFFILE}" "TRGDIR" "/etc/pkgbuilder/targets")
+PLUGINDIR=$(readSetting "${CNFFILE}" "PLUGINDIR" "/usr/share/pkgbuilder/plugins")
+MODELDIR=$(readSetting "${CNFFILE}" "MODELDIR" "/usr/share/pkgbuilder/models")
+WORKDIR=$(readSetting "${CNFFILE}" "WORKDIR" "/var/cache/pkgbuilder")
+VARDIR=$(readSetting "${CNFFILE}" "VARDIR" "/var/lib/pkgbuilder")
+
+case ${ARGCMD} in
+ list) pkgList;;
+ infos) pkgInfos "${ARGPKG}";;
+ create) pkgCreate "${ARGPKG}" "${ARGMDL}";;
+ build) pkgBuild "${ARGPKG}";;
+ bump) pkgBump "${ARGPKG}";;
+ checkupdate) pkgCheckUpdate "${ARGPKG}";;
+ checkupdateall) pkgCheckUpdateAll;;
+ update) pkgUpdate "${ARGPKG}";;
+ updateall) pkgUpdateall;;
+ *) showHelp; exit 1;;
+esac
diff --git a/buildrelease b/buildrelease
new file mode 100755
index 0000000..b1e4eef
--- /dev/null
+++ b/buildrelease
@@ -0,0 +1,54 @@
+#!/bin/bash
+
+readSetting() { # $1=filename $2=name $3=defaultvalue
+ local -r LINE=$(grep "^${2}=" "${1}")
+ local -r VALUE=${LINE/${2}=/}
+ if [ "${VALUE}" != "" ]; then
+ echo "${VALUE}"
+ else
+ echo "${3}"
+ fi
+}
+writeSetting() { #$1=filename $2=valuename $3=value
+ local -r LINE=$(grep "^${2}=" "${1}")
+ if [ "${LINE}" != "" ]; then
+ sed -i "s/^${2}=.*/${2}=${3}/" "${1}"
+ else
+ echo "${2}=${3}" >> "${1}"
+ fi
+}
+
+showHelp() {
+ echo "buildrelease version"
+ local -r PKGBUILD=${BASEDIR}/_dist/arch/PKGBUILD
+ local CURVERSION="0"
+ CURVERSION=$(readSetting "${PKGBUILD}" "pkgver" "0")
+ echo ""
+ echo "Current version : ${CURVERSION}"
+}
+
+buildRelease() {
+ local -r PKGBUILD=${BASEDIR}/_dist/arch/PKGBUILD
+ writeSetting "${PKGBUILD}" "pkgver" "${VERSION}"
+ writeSetting "${PKGBUILD}" "pkgrel" "1"
+ local -r GITBRANCH=$(git rev-parse --abbrev-ref HEAD)
+ git commit -a -m "New release ${VERSION}"
+ git push
+ git checkout main
+ git pull
+ git merge "${GITBRANCH}"
+ git push
+ git tag -a "${VERSION}" -m "Version ${VERSION}"
+ git push --tags
+ git checkout "${GITBRANCH}"
+}
+
+BASEDIR="$(pwd "${BASH_SOURCE[0]}")"
+
+if [ "${1}" == "" ]; then
+ showHelp
+ exit 1
+fi
+
+VERSION="${1}"
+buildRelease
diff --git a/completion/bash/buildpkg b/completion/bash/buildpkg
new file mode 100644
index 0000000..48f202a
--- /dev/null
+++ b/completion/bash/buildpkg
@@ -0,0 +1,41 @@
+#!/bin/bash
+
+_buildpkg() {
+ # shellcheck disable=SC2034
+ local cur prev words cword args
+ _init_completion || return
+
+ local -r cmdargs="-w --workdir -b --basedirname -u --builduser -m --mirror -d --mount -r --repo -p --pkgs -o --output"
+ local -r cnfargs="--help -n --nodeps --dbg"
+
+ if [[ ${COMP_WORDS[*]} == *"--help"* ]]; then
+ return
+ fi
+
+ args=${cmdargs}
+ for arg in ${cmdargs}; do
+ if [[ ${COMP_WORDS[*]} == *" ${arg} "* ]]; then
+ args=""
+ fi
+ done
+ for arg in ${cnfargs}; do
+ if [[ ${COMP_WORDS[*]} != *"${arg}"* ]]; then
+ args+=" ${arg}"
+ fi
+ done
+
+ case $prev in
+ --help)
+ return
+ ;;
+ -w | --workdir | -d | --mount | -o | --output)
+ _filedir -d
+ return
+ ;;
+ *)
+ # shellcheck disable=SC2207
+ COMPREPLY=($(compgen -W "${args}" -- "${COMP_WORDS[COMP_CWORD]}"))
+ return
+ ;;
+ esac
+} && complete -F _buildpkg buildpkg
\ No newline at end of file
diff --git a/completion/bash/pkgbuilder b/completion/bash/pkgbuilder
new file mode 100644
index 0000000..16cf2d4
--- /dev/null
+++ b/completion/bash/pkgbuilder
@@ -0,0 +1,56 @@
+#!/bin/bash
+
+_pkgbuilder() {
+ # shellcheck disable=SC2034
+ local cur prev words cword args
+ _init_completion || return
+
+ local -r cmdargs="list info create build bump checkupdate update checkupdateall updateall"
+ local -r cnfargs="--help --cnf --notify --nopush --dry-run --dbg"
+ #local cnffile=/etc/pkgbuilder/config
+ local pkgdir="/etc/pkgbuilder/packages"
+ local modeldir="/usr/share/pkgbuilder/models"
+
+ if [[ ${COMP_WORDS[*]} == *"--help"* ]]; then
+ return
+ fi
+
+ args=${cmdargs}
+ for arg in ${cmdargs}; do
+ if [[ ${COMP_WORDS[*]} == *" ${arg} "* ]]; then
+ args=""
+ fi
+ done
+ for arg in ${cnfargs}; do
+ if [[ ${COMP_WORDS[*]} != *"${arg}"* ]]; then
+ args+=" ${arg}"
+ fi
+ done
+
+ case $prev in
+ --help)
+ return
+ ;;
+ --cnf)
+ _filedir
+ return
+ ;;
+ create)
+ local -r MDLLIST=$(\ls ${modeldir})
+ # shellcheck disable=SC2207
+ COMPREPLY=($(compgen -W "${MDLLIST}" -- "${COMP_WORDS[COMP_CWORD]}"))
+ return
+ ;;
+ info | build | bump | checkupdate | update)
+ local -r PKGLIST=$(\ls ${pkgdir})
+ # shellcheck disable=SC2207
+ COMPREPLY=($(compgen -W "${PKGLIST}" -- "${COMP_WORDS[COMP_CWORD]}"))
+ return
+ ;;
+ *)
+ # shellcheck disable=SC2207
+ COMPREPLY=($(compgen -W "${args}" -- "${COMP_WORDS[COMP_CWORD]}"))
+ return
+ ;;
+ esac
+} && complete -F _pkgbuilder pkgbuilder
\ No newline at end of file
diff --git a/config b/config
new file mode 100644
index 0000000..219e01d
--- /dev/null
+++ b/config
@@ -0,0 +1,7 @@
+#PKGDIR="/etc/pkgbuilder/packages"
+#TRGDIR="/etc/pkgbuilder/targets"
+#PLUGINDIR="/usr/share/pkgbuilder/plugins"
+#MODELDIR="/usr/share/pkgbuilder/models"
+#WORKDIR="/var/cache/pkgbuilder"
+#VARDIR="/var/lib/pkgbuilder"
+#EMAIL=email@email.com
diff --git a/models/aur/settings b/models/aur/settings
new file mode 100644
index 0000000..9d1400f
--- /dev/null
+++ b/models/aur/settings
@@ -0,0 +1,2 @@
+plugin=aur
+target=local-test
diff --git a/models/custom/files/PKGBUILD b/models/custom/files/PKGBUILD
new file mode 100644
index 0000000..fbc2889
--- /dev/null
+++ b/models/custom/files/PKGBUILD
@@ -0,0 +1,19 @@
+# Maintainer: me
+
+pkgname=pkgname
+pkgver=0.0.0
+pkgrel=0
+pkgdesc="Desc"
+arch=('any')
+url='url'
+license=('GPL3')
+#depends=()
+#makedepends=()
+#optdepends=()
+#source=("${pkgname}::git+https://url.git")
+#md5sums=('SKIP')
+#backup=()
+
+package() {
+ cd ${pkgname}
+}
diff --git a/models/custom/plugin b/models/custom/plugin
new file mode 100644
index 0000000..91b7ccd
--- /dev/null
+++ b/models/custom/plugin
@@ -0,0 +1,25 @@
+#!/bin/bash
+
+custom_plugin_isupdatable() {
+ return 1
+}
+
+custom_plugin_isbumpable() {
+ return 1
+}
+
+custom_plugin_getpkgfiles() {
+ return 1
+}
+
+custom_plugin_bump() {
+ return 1
+}
+
+custom_plugin_getlatestversion() {
+ return 1
+}
+
+custom_plugin_update() {
+ return 1
+}
\ No newline at end of file
diff --git a/models/custom/settings b/models/custom/settings
new file mode 100644
index 0000000..0c87793
--- /dev/null
+++ b/models/custom/settings
@@ -0,0 +1,2 @@
+plugin=custom
+target=local-test
diff --git a/models/github-branch/files/PKGBUILD b/models/github-branch/files/PKGBUILD
new file mode 100644
index 0000000..144b055
--- /dev/null
+++ b/models/github-branch/files/PKGBUILD
@@ -0,0 +1,29 @@
+# Maintainer: user
+
+_githubuser=
+_githubrepo=
+_gitcommit=
+
+pkgname=
+pkgver=0
+pkgrel=0
+pkgdesc='Desc'
+arch=('any')
+url="https://github.com/${_githubuser}/${_githubrepo}"
+#license=('GPL3')
+#depends=()
+makedepends=('git')
+#optdepends=()
+#install="${pkgname}.install"
+#provides=()
+#backup=()
+source=("git+https://github.com/${_githubuser}/${_githubrepo}.git#commit=${_gitcommit}")
+sha256sums=('SKIP')
+
+build() {
+ cd "${_githubrepo}"
+}
+
+package() {
+ cd "${_githubrepo}"
+}
diff --git a/models/github-branch/settings b/models/github-branch/settings
new file mode 100644
index 0000000..4be2037
--- /dev/null
+++ b/models/github-branch/settings
@@ -0,0 +1,10 @@
+plugin=github-branch
+target=local-test
+githubuser=
+githubrepo=
+gitbranch=
+gitcommit=
+pkgrev=0
+pkgver=0
+version=0
+pkgrel=1
diff --git a/models/github-release/files/PKGBUILD b/models/github-release/files/PKGBUILD
new file mode 100644
index 0000000..87e6764
--- /dev/null
+++ b/models/github-release/files/PKGBUILD
@@ -0,0 +1,29 @@
+# Maintainer: user
+
+_githubuser=
+_githubrepo=
+_pkgtagname=
+
+pkgname=
+pkgver=0
+pkgrel=0
+pkgdesc='Desc'
+arch=('any')
+url="https://github.com/${_githubuser}/${_githubrepo}"
+#license=('GPL3')
+#depends=()
+#makedepends=()
+#optdepends=()
+#install="${pkgname}.install"
+#provides=()
+#backup=()
+source=("${_githubrepo}::https://github.com/${_githubuser}/${_githubrepo}/archive/refs/tags/${_pkgtagname}.tar.gz")
+sha256sums=('SKIP')
+
+build() {
+ cd "${_githubrepo}-${pkgver}"
+}
+
+package() {
+ cd "${_githubrepo}-${pkgver}"
+}
diff --git a/models/github-release/settings b/models/github-release/settings
new file mode 100644
index 0000000..87a404c
--- /dev/null
+++ b/models/github-release/settings
@@ -0,0 +1,4 @@
+plugin=github-release
+target=local-test
+githubuser=
+githubrepo=
diff --git a/models/github-tag/files/PKGBUILD b/models/github-tag/files/PKGBUILD
new file mode 100644
index 0000000..87e6764
--- /dev/null
+++ b/models/github-tag/files/PKGBUILD
@@ -0,0 +1,29 @@
+# Maintainer: user
+
+_githubuser=
+_githubrepo=
+_pkgtagname=
+
+pkgname=
+pkgver=0
+pkgrel=0
+pkgdesc='Desc'
+arch=('any')
+url="https://github.com/${_githubuser}/${_githubrepo}"
+#license=('GPL3')
+#depends=()
+#makedepends=()
+#optdepends=()
+#install="${pkgname}.install"
+#provides=()
+#backup=()
+source=("${_githubrepo}::https://github.com/${_githubuser}/${_githubrepo}/archive/refs/tags/${_pkgtagname}.tar.gz")
+sha256sums=('SKIP')
+
+build() {
+ cd "${_githubrepo}-${pkgver}"
+}
+
+package() {
+ cd "${_githubrepo}-${pkgver}"
+}
diff --git a/models/github-tag/settings b/models/github-tag/settings
new file mode 100644
index 0000000..397b52f
--- /dev/null
+++ b/models/github-tag/settings
@@ -0,0 +1,4 @@
+plugin=github-tag
+target=local-test
+githubuser=
+githubrepo=
diff --git a/models/manual/files/PKGBUILD b/models/manual/files/PKGBUILD
new file mode 100644
index 0000000..fbc2889
--- /dev/null
+++ b/models/manual/files/PKGBUILD
@@ -0,0 +1,19 @@
+# Maintainer: me
+
+pkgname=pkgname
+pkgver=0.0.0
+pkgrel=0
+pkgdesc="Desc"
+arch=('any')
+url='url'
+license=('GPL3')
+#depends=()
+#makedepends=()
+#optdepends=()
+#source=("${pkgname}::git+https://url.git")
+#md5sums=('SKIP')
+#backup=()
+
+package() {
+ cd ${pkgname}
+}
diff --git a/models/manual/settings b/models/manual/settings
new file mode 100644
index 0000000..3d12019
--- /dev/null
+++ b/models/manual/settings
@@ -0,0 +1,2 @@
+plugin=manual
+target=local-test
diff --git a/packages/pkgname/settings b/packages/pkgname/settings
new file mode 100644
index 0000000..f4b6337
--- /dev/null
+++ b/packages/pkgname/settings
@@ -0,0 +1,16 @@
+#plugin=manual
+#PluginInfos...
+
+#target=local-test
+
+#base=arch-base
+#mirror=https...
+#repos=testing matmoul|https...)
+#pkgs=git systemd
+#nodeps=1
+#dbgmode=1
+
+#version=0.0.0-0
+#builddate=date
+#lastbuilddate=date
+#lastbuildstatus=Ok|Error
diff --git a/plugins/aur b/plugins/aur
new file mode 100644
index 0000000..8c739d0
--- /dev/null
+++ b/plugins/aur
@@ -0,0 +1,51 @@
+#!/bin/bash
+
+plugin_isupdatable() {
+ return 0
+}
+
+plugin_isbumpable() {
+ return 1
+}
+
+plugin_getpkgfiles() {
+ if [ -d "${PKGDIR}"/"${PKGNAME}"/files ]; then
+ if ! rm -r "${PKGDIR}"/"${PKGNAME}"/files; then
+ return 1
+ fi
+ fi
+ if ! git clone "https://aur@aur.archlinux.org/${PKGNAME}.git" "${PKGDIR}"/"${PKGNAME}"/files; then
+ return 1
+ fi
+ echo "${PKGDIR}/${PKGNAME}/files"
+}
+
+plugin_bump() {
+ return 1
+}
+
+plugin_getlatestversion() {
+ local PKGSRC=""
+ if ! PKGSRC=$(curl -sL https://aur.archlinux.org/cgit/aur.git/plain/.SRCINFO?h=${PKGNAME}); then
+ echo "Error in AUR API"
+ return 1
+ fi
+ ONLINEVER=""
+ if ! ONLINEVER=$(echo "${PKGSRC}" | grep "pkgver =" | sed "s/pkgver =//" | sed -e 's/^[[:space:]]*//')-$(echo "${PKGSRC}" | grep "pkgrel =" | sed "s/pkgrel =//" | sed -e 's/^[[:space:]]*//'); then
+ echo "Error in AUR API"
+ return 1
+ fi
+ if [ "${ONLINEVER}" == "" ]; then
+ echo "Error in AUR API"
+ return 1
+ fi
+ local -r ONLINEEPOCH=$(echo "${PKGSRC}" | grep epoch= | sed s/epoch=//)
+ if [[ ${ONLINEEPOCH} != "" ]]; then
+ ONLINEVER=${ONLINEEPOCH}:${ONLINEVER}
+ fi
+ echo "${ONLINEVER}"
+}
+
+plugin_update() {
+ return 0
+}
diff --git a/plugins/github-branch b/plugins/github-branch
new file mode 100644
index 0000000..c4aaf8a
--- /dev/null
+++ b/plugins/github-branch
@@ -0,0 +1,73 @@
+#!/bin/bash
+
+plugin_isupdatable() {
+ return 0
+}
+
+plugin_isbumpable() {
+ return 0
+}
+
+plugin_getpkgfiles() {
+ echo "${PKGDIR}/${PKGNAME}/files"
+}
+
+plugin_bump() {
+ local -r PKGREL=$(readSetting "${PKGDIR}"/"${PKGNAME}"/files/PKGBUILD "pkgrel" 0)
+ sed -i "s/pkgrel=.*/pkgrel=$((PKGREL+1))/" "${PKGDIR}"/"${PKGNAME}"/files/PKGBUILD
+}
+
+plugin_getlatestversion() {
+ local -r PKGSETTINGS=${PKGDIR}/${PKGNAME}/settings
+ local -r GITHUBUSER=$(readSetting "${PKGSETTINGS}" "githubuser" "")
+ local -r GITHUBREPO=$(readSetting "${PKGSETTINGS}" "githubrepo" "")
+ local -r GITBRANCH=$(readSetting "${PKGSETTINGS}" "gitbranch" "")
+ local -r GITCOMMIT=$(readSetting "${PKGSETTINGS}" "gitcommit" "")
+ local -r GITHUBURL="https://github.com/${GITHUBUSER}/${GITHUBREPO}.git"
+ local -r ONLINECOMMIT=$(git ls-remote "${GITHUBURL}" | grep "${GITBRANCH}$" | cut -f 1)
+ if [[ "${ONLINECOMMIT}" == "" ]]; then
+ echo "Error in Github API"
+ return 1
+ fi
+ if [[ "${GITCOMMIT}" == "${ONLINECOMMIT}" ]]; then
+ readSetting "${PKGSETTINGS}" "version" "0"
+ else
+ local -r PKGVERSION=$(readSetting "${PKGSETTINGS}" "pkgver" "0")
+ local -r PKGREVISION=$(readSetting "${PKGSETTINGS}" "pkgrev" "0")
+ local -r PKGNEWREVISION=$((PKGREVISION + 1))
+ echo "${PKGVERSION}.r${PKGNEWREVISION}.${ONLINECOMMIT:0:7}-1"
+ fi
+}
+
+plugin_update() {
+ local -r PKGSETTINGS=${PKGDIR}/${PKGNAME}/settings
+ local -r GITHUBUSER=$(readSetting "${PKGSETTINGS}" "githubuser" "")
+ local -r GITHUBREPO=$(readSetting "${PKGSETTINGS}" "githubrepo" "")
+ local -r GITBRANCH=$(readSetting "${PKGSETTINGS}" "gitbranch" "")
+ local -r GITCOMMIT=$(readSetting "${PKGSETTINGS}" "gitcommit" "")
+ local -r GITHUBURL="https://github.com/${GITHUBUSER}/${GITHUBREPO}.git"
+ local -r ONLINECOMMIT=$(git ls-remote "${GITHUBURL}" | grep "${GITBRANCH}$" | cut -f 1)
+ if [[ "${ONLINECOMMIT}" == "" ]]; then
+ echo "Error in Github API"
+ return 1
+ fi
+ if [[ "${GITCOMMIT}" == "${ONLINECOMMIT}" ]]; then
+ return 0
+ fi
+
+ writeSetting "${PKGSETTINGS}" "gitcommit" "${ONLINECOMMIT}"
+ local -r PKGREVISION=$(readSetting "${PKGSETTINGS}" "pkgrev" "0")
+ writeSetting "${PKGSETTINGS}" "pkgrev" "$((PKGREVISION + 1))"
+ writeSetting "${PKGSETTINGS}" "pkgrel" "1"
+
+ local -r PKGBUILD="${PKGDIR}/${PKGNAME}/files/PKGBUILD"
+ writeSetting "${PKGBUILD}" "_githubuser" "${GITHUBUSER}"
+ writeSetting "${PKGBUILD}" "_githubrepo" "${GITHUBREPO}"
+ writeSetting "${PKGBUILD}" "_gitcommit" "${ONLINECOMMIT}"
+ writeSetting "${PKGBUILD}" "pkgname" "${PKGNAME}"
+ writeSetting "${PKGBUILD}" "pkgrel" "1"
+ local -r PKGVERSION=$(readSetting "${PKGSETTINGS}" "pkgver" "0")
+ local -r PKGREVISION=$(readSetting "${PKGSETTINGS}" "pkgrev" "0")
+ local -r PKGNEWREVISION=$((PKGREVISION + 1))
+ writeSetting "${PKGBUILD}" "pkgver" "${PKGVERSION}.r${PKGNEWREVISION}.${ONLINECOMMIT:0:7}"
+}
\ No newline at end of file
diff --git a/plugins/github-release b/plugins/github-release
new file mode 100644
index 0000000..a750262
--- /dev/null
+++ b/plugins/github-release
@@ -0,0 +1,86 @@
+#!/bin/bash
+
+plugin_isupdatable() {
+ return 0
+}
+
+plugin_isbumpable() {
+ return 0
+}
+
+plugin_getpkgfiles() {
+ echo "${PKGDIR}/${PKGNAME}/files"
+}
+
+plugin_bump() {
+ local -r PKGREL=$(readSetting "${PKGDIR}"/"${PKGNAME}"/files/PKGBUILD "pkgrel" 0)
+ sed -i "s/pkgrel=.*/pkgrel=$((PKGREL+1))/" "${PKGDIR}"/"${PKGNAME}"/files/PKGBUILD
+}
+
+plugin_getlatestversion() {
+ local -r PKGSETTINGS=${PKGDIR}/${PKGNAME}/settings
+ local -r GITHUBUSER=$(readSetting "${PKGSETTINGS}" "githubuser" "")
+ local -r GITHUBREPO=$(readSetting "${PKGSETTINGS}" "githubrepo" "")
+ local GITHUBTAGNAME=""
+ if ! GITHUBTAGNAME=$(curl -sL "https://api.github.com/repos/${GITHUBUSER}/${GITHUBREPO}/releases/latest" | jq -r ".tag_name"); then
+ echo "Error in Github API"
+ return 1
+ fi
+ if [ "${GITHUBTAGNAME}" == "" ]; then
+ echo "Error in Github API"
+ return 1
+ fi
+ local -r GITHUBVERSION=${GITHUBTAGNAME//[[:alpha:]]/}
+ if [ "${GITHUBVERSION}" == "" ]; then
+ echo "Error in Github API"
+ return 1
+ fi
+ local -r PKGVERSION=$(readSetting "${PKGSETTINGS}" "pkgver" "0")
+ if [[ "${PKGVERSION}" == "${GITHUBVERSION}" ]]; then
+ readSetting "${PKGSETTINGS}" "version" "0"
+ else
+ echo "${GITHUBVERSION}-1"
+ fi
+}
+
+plugin_update() {
+ local -r PKGSETTINGS=${PKGDIR}/${PKGNAME}/settings
+ local -r GITHUBUSER=$(readSetting "${PKGSETTINGS}" "githubuser" "")
+ local -r GITHUBREPO=$(readSetting "${PKGSETTINGS}" "githubrepo" "")
+ local GITHUBTAGNAME=""
+ if ! GITHUBTAGNAME=$(curl -sL "https://api.github.com/repos/${GITHUBUSER}/${GITHUBREPO}/releases/latest" | jq -r ".tag_name"); then
+ echo "Error in Github API"
+ return 1
+ fi
+ if [ "${GITHUBTAGNAME}" == "" ]; then
+ echo "Error in Github API"
+ return 1
+ fi
+ local -r GITHUBVERSION=${GITHUBTAGNAME//[[:alpha:]]/}
+ if [ "${GITHUBVERSION}" == "" ]; then
+ echo "Error in Github API"
+ return 1
+ fi
+ local -r PKGVERSION=$(readSetting "${PKGSETTINGS}" "pkgver" "0")
+ if [[ "${PKGVERSION}" == "${GITHUBVERSION}" ]]; then
+ return 0
+ fi
+
+ writeSetting "${PKGSETTINGS}" "pkgrel" "1"
+
+ local -r PKGBUILD="${PKGDIR}/${PKGNAME}/files/PKGBUILD"
+ writeSetting "${PKGBUILD}" "_githubuser" "${GITHUBUSER}"
+ writeSetting "${PKGBUILD}" "_githubrepo" "${GITHUBREPO}"
+ writeSetting "${PKGBUILD}" "_pkgtagname" "${GITHUBTAGNAME}"
+ writeSetting "${PKGBUILD}" "pkgname" "${PKGNAME}"
+ writeSetting "${PKGBUILD}" "pkgrel" "1"
+ writeSetting "${PKGBUILD}" "pkgver" "${GITHUBVERSION}"
+
+ local TMPDIR=""
+ TMPDIR=$(mktemp -d)
+ cp -r "${PKGDIR}"/"${PKGNAME}"/files/* "${TMPDIR}"
+ chown -R pkgbuilder "${TMPDIR}"
+ sudo -u pkgbuilder updpkgsums "${TMPDIR}"/PKGBUILD
+ cp -r "${TMPDIR}"/PKGBUILD "${PKGDIR}/${PKGNAME}/files/"
+ rm -rf "${TMPDIR}"
+}
\ No newline at end of file
diff --git a/plugins/github-tag b/plugins/github-tag
new file mode 100644
index 0000000..e713892
--- /dev/null
+++ b/plugins/github-tag
@@ -0,0 +1,86 @@
+#!/bin/bash
+
+plugin_isupdatable() {
+ return 0
+}
+
+plugin_isbumpable() {
+ return 0
+}
+
+plugin_getpkgfiles() {
+ echo "${PKGDIR}/${PKGNAME}/files"
+}
+
+plugin_bump() {
+ local -r PKGREL=$(readSetting "${PKGDIR}"/"${PKGNAME}"/files/PKGBUILD "pkgrel" 0)
+ sed -i "s/pkgrel=.*/pkgrel=$((PKGREL+1))/" "${PKGDIR}"/"${PKGNAME}"/files/PKGBUILD
+}
+
+plugin_getlatestversion() {
+ local -r PKGSETTINGS=${PKGDIR}/${PKGNAME}/settings
+ local -r GITHUBUSER=$(readSetting "${PKGSETTINGS}" "githubuser" "")
+ local -r GITHUBREPO=$(readSetting "${PKGSETTINGS}" "githubrepo" "")
+ local GITHUBTAGNAME=""
+ if ! GITHUBTAGNAME=$(curl -sL "https://api.github.com/repos/${GITHUBUSER}/${GITHUBREPO}/tags" | jq -r ".[0].name"); then
+ echo "Error in Github API"
+ return 1
+ fi
+ if [ "${GITHUBTAGNAME}" == "" ]; then
+ echo "Error in Github API"
+ return 1
+ fi
+ local -r GITHUBVERSION=${GITHUBTAGNAME//[[:alpha:]]/}
+ if [ "${GITHUBVERSION}" == "" ]; then
+ echo "Error in Github API"
+ return 1
+ fi
+ local -r PKGVERSION=$(readSetting "${PKGSETTINGS}" "pkgver" "0")
+ if [[ "${PKGVERSION}" == "${GITHUBVERSION}" ]]; then
+ readSetting "${PKGSETTINGS}" "version" "0"
+ else
+ echo "${GITHUBVERSION}-1"
+ fi
+}
+
+plugin_update() {
+ local -r PKGSETTINGS=${PKGDIR}/${PKGNAME}/settings
+ local -r GITHUBUSER=$(readSetting "${PKGSETTINGS}" "githubuser" "")
+ local -r GITHUBREPO=$(readSetting "${PKGSETTINGS}" "githubrepo" "")
+ local GITHUBTAGNAME=""
+ if ! GITHUBTAGNAME=$(curl -sL "https://api.github.com/repos/${GITHUBUSER}/${GITHUBREPO}/tags" | jq -r ".[0].name"); then
+ echo "Error in Github API"
+ return 1
+ fi
+ if [ "${GITHUBTAGNAME}" == "" ]; then
+ echo "Error in Github API"
+ return 1
+ fi
+ local -r GITHUBVERSION=${GITHUBTAGNAME//[[:alpha:]]/}
+ if [ "${GITHUBVERSION}" == "" ]; then
+ echo "Error in Github API"
+ return 1
+ fi
+ local -r PKGVERSION=$(readSetting "${PKGSETTINGS}" "pkgver" "0")
+ if [[ "${PKGVERSION}" == "${GITHUBVERSION}" ]]; then
+ return 0
+ fi
+
+ writeSetting "${PKGSETTINGS}" "pkgrel" "1"
+
+ local -r PKGBUILD="${PKGDIR}/${PKGNAME}/files/PKGBUILD"
+ writeSetting "${PKGBUILD}" "_githubuser" "${GITHUBUSER}"
+ writeSetting "${PKGBUILD}" "_githubrepo" "${GITHUBREPO}"
+ writeSetting "${PKGBUILD}" "_pkgtagname" "${GITHUBTAGNAME}"
+ writeSetting "${PKGBUILD}" "pkgname" "${PKGNAME}"
+ writeSetting "${PKGBUILD}" "pkgrel" "1"
+ writeSetting "${PKGBUILD}" "pkgver" "${GITHUBVERSION}"
+
+ local TMPDIR=""
+ TMPDIR=$(mktemp -d)
+ cp -r "${PKGDIR}"/"${PKGNAME}"/files/* "${TMPDIR}"
+ chown -R pkgbuilder "${TMPDIR}"
+ sudo -u pkgbuilder updpkgsums "${TMPDIR}"/PKGBUILD
+ cp -r "${TMPDIR}"/PKGBUILD "${PKGDIR}/${PKGNAME}/files/"
+ rm -rf "${TMPDIR}"
+}
\ No newline at end of file
diff --git a/plugins/manual b/plugins/manual
new file mode 100644
index 0000000..dd78434
--- /dev/null
+++ b/plugins/manual
@@ -0,0 +1,25 @@
+#!/bin/bash
+
+plugin_isupdatable() {
+ return 1
+}
+
+plugin_isbumpable() {
+ return 0
+}
+
+plugin_getpkgfiles() {
+ local TMPDIR=""
+ TMPDIR=$(mktemp -d)
+ cp -r "${PKGDIR}"/"${PKGNAME}"/files/* "${TMPDIR}"
+ chown -R pkgbuilder "${TMPDIR}"
+ sudo -u pkgbuilder updpkgsums "${TMPDIR}"/PKGBUILD
+ cp -r "${TMPDIR}"/PKGBUILD "${PKGDIR}/${PKGNAME}/files/"
+ rm -rf "${TMPDIR}"
+ echo "${PKGDIR}/${PKGNAME}/files"
+}
+
+plugin_bump() {
+ local -r PKGREL=$(readSetting "${PKGDIR}"/"${PKGNAME}"/files/PKGBUILD "pkgrel" 0)
+ sed -i "s/pkgrel=.*/pkgrel=$((PKGREL+1))/" "${PKGDIR}"/"${PKGNAME}"/files/PKGBUILD
+}
diff --git a/systemd/pkgbuilder.service b/systemd/pkgbuilder.service
new file mode 100644
index 0000000..62f2903
--- /dev/null
+++ b/systemd/pkgbuilder.service
@@ -0,0 +1,6 @@
+[Unit]
+Description=pkgbuilder
+
+[Service]
+Type=simple
+ExecStart=/usr/bin/pkgbuilder checkupdateall --notify
diff --git a/systemd/pkgbuilder.timer b/systemd/pkgbuilder.timer
new file mode 100644
index 0000000..df444bd
--- /dev/null
+++ b/systemd/pkgbuilder.timer
@@ -0,0 +1,8 @@
+[Unit]
+Description=pkgbuilder - check packages update
+
+[Timer]
+OnCalendar=*-*-* 16:00:00
+
+[Install]
+WantedBy=timers.target
\ No newline at end of file
diff --git a/targets/local-test b/targets/local-test
new file mode 100644
index 0000000..45aa51d
--- /dev/null
+++ b/targets/local-test
@@ -0,0 +1,2 @@
+type=dir
+dest=/var/lib/pkgbuilder/repos/local-test