#!/usr/bin/env bash set -eu # source makepkg.conf to use PACKAGER . /etc/makepkg.conf # shellcheck source=/dev/null [ -f "${HOME}/.makepkg.conf" ] && . "${HOME}/.makepkg.conf" package_dir_base="${HOME}/packages/" nvchecker_dir_base="${HOME}/.config/nvchecker/" repo="" package="" mode="" new_package=0 declare -A upstreams=( ["aur"]="aur@aur.archlinux.org" ["community"]="svn+ssh://svn-community@repos.archlinux.org/srv/repos/svn-community/svn" ["core"]="svn+ssh://svn-packages@repos.archlinux.org/srv/repos/svn-packages/svn" ["extra"]="svn+ssh://svn-packages@repos.archlinux.org/srv/repos/svn-packages/svn" ) declare -A package_lists=( ["aur"]="$HOME/.config/packages/aur.txt" ["community"]="$HOME/.config/packages/community.txt" ["core"]="$HOME/.config/packages/core.txt" ["extra"]="$HOME/.config/packages/extra.txt" ) declare -A package_dirs=( ["aur"]="${package_dir_base}aur" ["community"]="${package_dir_base}community" ["core"]="${package_dir_base}core" ["extra"]="${package_dir_base}extra" ) check_dependencies() { # check whether required commands are installed local _commands=('svn' 'git') local _command for _command in "${_commands[@]}"; do if ! command -v "${_command}" > /dev/null; then printf "The required command %s can not be found. Exiting...\n" "$_command" exit 1 fi done } create_tmp_packagelist() { local list_file="" list_file=$(basename "$1") mktemp -p "$XDG_RUNTIME_DIR/" "$list_file.XXXX" } add_package() { local name="$1" local tmp_file="" tmp_file=$(create_tmp_packagelist "${package_lists[$repo]}") if [[ ! -f "${package_lists[$repo]}" ]]; then echo "Adding initial package list: ${package_lists[$repo]}" touch "${package_lists[$repo]}" fi echo "Adding $package to list of $repo packages." echo "$name" | cat "${package_lists[$repo]}" - |uniq |sort > "$tmp_file" cat "$tmp_file" > "${package_lists[$repo]}" rm "$tmp_file" } create_nvchecker_config() { if [[ ! -d "${nvchecker_dir_base}" ]]; then mkdir -p "${nvchecker_dir_base}" fi if [[ ! -f "${nvchecker_dir_base}${repo}.toml" ]]; then printf "[__config__]\noldver = \"%s.old.json\"\nnewver = \"%s.new.json\"\n" "${repo}" "${repo}" \ > "${nvchecker_dir_base}${repo}.toml" fi } create_package() { local name="$1" local pkgbuild="" create_repo_dir cd "${package_dirs[$repo]}" if [ "$repo" == "aur" ]; then git clone "${upstreams[$repo]}:${name}" pkgbuild="${name}/PKGBUILD" else svn update "${name}" if [[ ! -d "${name}" ]]; then mkdir -p "${name}"/{trunk,repos} pkgbuild="${name}/trunk/PKGBUILD" fi fi if [[ -n "${pkgbuild}" ]] && [[ ! -f "${pkgbuild}" ]]; then cp /usr/share/pacman/PKGBUILD.proto "${pkgbuild}" sed -e "s/NAME/$name/g" \ -e "1i# Maintainer: ${PACKAGER:-}" \ -e '/#/d' \ -i "${pkgbuild}" fi create_nvchecker_config if ! grep -q "\[$name\]" "${nvchecker_dir_base}${repo}.toml"; then printf '\n[%s]\n\n' "${name}" >> "${nvchecker_dir_base}${repo}.toml" fi } remove_package() { local name="$1" local tmp_file="" tmp_file=$(create_tmp_packagelist "${package_lists[$repo]}") echo "Removing $package from list of $repo packages." cat "${package_lists[$repo]}" |grep -vE "^$name$" |uniq |sort > "$tmp_file" cat "$tmp_file" > "${package_lists[$repo]}" rm "$tmp_file" if [[ "$repo" == aur ]]; then rm -rf "${package_dirs[$repo]:?}/$name" fi # TODO: remove package dirs from svn # remove entry from nvchecker config if grep -q "\[$name\]" "${nvchecker_dir_base}${repo}.toml"; then sed -e "/^\[$name\]/,/^\[/{/^\[/!d};/^\[$name\]/d" \ -i "${nvchecker_dir_base}${repo}.toml" fi } check_mode_set(){ if [ -n "$mode" ]; then echo "Error: A mode can only be set once." exit 1 fi } check_repo_set(){ if [ -n "$repo" ]; then echo "Error: A repo can only be set once." exit 1 fi } create_repo_dir() { if [ ! -d "${package_dirs[$repo]}" ];then if [ "$repo" == "aur" ]; then echo "Creating directory for $repo." mkdir -pv "${package_dirs[$repo]}" else ( echo "Checking out $repo directory." mkdir -pv "$(dirname "${package_dirs[$repo]}")" cd "$(dirname "${package_dirs[$repo]}")" svn checkout -N "${upstreams[$repo]}" \ "$(basename "${package_dirs[$repo]}")" ) fi fi } print_help() { echo "Usage: pkgs -" } clean_packages() { if [ -d "${package_dirs[$repo]}" ]; then cd "${package_dirs[$repo]}" for package in $(cat "${package_lists[$repo]}"); do if [ -d "$package" ]; then ( cd "$package" echo "Cleaning package $repo/$package." if [ "$repo" == "aur" ]; then git clean -f else svn cleanup --remove-unversioned . fi ) fi done else echo "Package dir for $repo is empty." exit 1 fi } update_packages() { create_repo_dir cd "${package_dirs[$repo]}" for package in $(cat "${package_lists[$repo]}"); do if [ "$repo" == "aur" ]; then if [ -d "$package" ]; then ( echo "Pulling package: $package." cd "$package" git pull ) else echo "Cloning package '$package'." git clone "${upstreams[$repo]}:$package" fi else svn update "$package" fi done } if [ ${#@} -gt 0 ]; then while getopts ':a:chlnur:ACEP' flag; do case "${flag}" in a) check_mode_set mode="add" if [ -n "${OPTARG}" ]; then package="${OPTARG}" else echo "Package name can not be empty." exit 1 fi ;; c) check_mode_set mode="clean" ;; h) print_help ;; l) check_mode_set mode="list" ;; n) new_package=1 ;; # TODO: introduce -m flag for moving package (e.g. community2extra, extra2community) r) check_mode_set mode="remove" if [ -n "${OPTARG}" ]; then package="${OPTARG}" else echo "Package name can not be empty." exit 1 fi ;; u) check_mode_set mode="update" ;; A) check_repo_set repo="aur" ;; C) check_repo_set repo="community" ;; E) check_repo_set repo="extra" ;; P) check_repo_set repo="core" ;; *) echo "Error. Unrecognized option: ${flag}." exit 1 ;; esac done else print_help fi case "${mode}" in add) if [ -z "$repo" ]; then echo "A repository must be defined for adding a package." exit 1 elif [ -z "$package" ]; then echo "A package must be defined for adding a package." exit 1 else check_dependencies add_package "$package" [ $new_package -gt 0 ] && create_package "$package" fi ;; remove) if [ -z "$repo" ]; then echo "A repository must be defined for removing a package." print_help exit 1 elif [ -z "$package" ]; then echo "A package must be defined for removing a package." exit 1 else check_dependencies remove_package "$package" fi ;; update) check_dependencies if [ -z "$repo" ];then for list in aur community core extra; do if [ -f "${package_lists[$list]}" ]; then repo="$list" update_packages fi done else update_packages fi ;; list) if [ -z "$repo" ]; then for list in aur community core extra; do if [ -f "${package_lists[$list]}" ]; then cat "${package_lists[$list]}" fi done else if [ -f "${package_lists[$repo]}" ]; then cat "${package_lists[$repo]}" fi fi ;; clean) check_dependencies if [ -z "$repo" ]; then for list in aur community core extra; do repo="$list" clean_packages done else clean_packages fi ;; esac exit 0