summaryrefslogtreecommitdiff
path: root/src/sogrep.in
diff options
context:
space:
mode:
Diffstat (limited to 'src/sogrep.in')
-rw-r--r--src/sogrep.in170
1 files changed, 170 insertions, 0 deletions
diff --git a/src/sogrep.in b/src/sogrep.in
new file mode 100644
index 0000000..d1ca1a1
--- /dev/null
+++ b/src/sogrep.in
@@ -0,0 +1,170 @@
+#!/bin/bash
+#
+# sogrep - find shared library links in an Arch Linux repository.
+#
+# Copyright (c) 2019 by Eli Schwartz <eschwartz@archlinux.org>
+#
+# SPDX-License-Identifier: GPL-3.0-or-later
+
+m4_include(lib/common.sh)
+
+# globals
+: ${SOLINKS_MIRROR:="https://mirror.pkgbuild.com"}
+: ${SOCACHE_DIR:="${XDG_CACHE_HOME:-${HOME}/.cache}/sogrep"}
+
+m4_include(lib/valid-repos.sh)
+arches=('x86_64')
+
+# options
+REFRESH=0
+VERBOSE=0
+
+source /usr/share/makepkg/util/parseopts.sh
+source /usr/share/makepkg/util/util.sh
+
+recache() {
+ local repo arch verbosity=-s
+
+ (( VERBOSE )) && verbosity=--progress-bar
+
+ for repo in "${_repos[@]}"; do
+ for arch in "${arches[@]}"; do
+ # delete extracted tarballs from previous sogrep versions
+ rm -rf "${SOCACHE_DIR}/${arch}/${repo}"
+
+ # fetch repo links database if newer than our cached copy
+ local dbpath=${SOCACHE_DIR}/${arch}/${repo}.links.tar.gz
+ mkdir -p "${dbpath%/*}"
+ (( VERBOSE )) && echo "Fetching ${repo}.links.tar.gz..."
+ if ! curl -fLR "${verbosity}" -o "${dbpath}" -z "${dbpath}" \
+ "${SOLINKS_MIRROR}/${repo}/os/${arch}/${repo}.links.tar.gz"; then
+ echo "error: failed to download links database for repo ${repo}"
+ exit 1
+ fi
+ done
+ done
+}
+
+is_outdated_cache() {
+ local repo arch
+
+ # links databases are generated at about the same time every day; we should
+ # attempt to check for new database files if any of them are over a day old
+
+ for repo in "${_repos[@]}"; do
+ for arch in "${arches[@]}"; do
+ local dbpath=${SOCACHE_DIR}/${arch}/${repo}.links.tar.gz
+ if [[ ! -f ${dbpath} ]] || [[ $(find "${dbpath}" -mtime +0) ]]; then
+ return 0
+ fi
+ done
+ done
+
+ return 1
+}
+
+search() {
+ local repo=$1 arch lib=$2 srepos=("${_repos[@]}")
+
+ if [[ $repo != all ]]; then
+ if ! in_array "${repo}" "${_repos[@]}"; then
+ echo "${BASH_SOURCE[0]##*/}: unrecognized repo '$repo'"
+ echo "Try '${BASH_SOURCE[0]##*/} --help' for more information."
+ exit 1
+ fi
+ srepos=("${repo}")
+ fi
+
+ setup_workdir
+
+ for arch in "${arches[@]}"; do
+ for repo in "${srepos[@]}"; do
+ local prefix=
+ (( VERBOSE && ${#srepos[@]} > 1 )) && prefix=${repo}/
+ local db=${SOCACHE_DIR}/${arch}/${repo}.links.tar.gz
+ if [[ -f ${db} ]]; then
+ local extracted=${WORKDIR}/${arch}/${repo}
+ mkdir -p "${extracted}"
+ bsdtar -C "${extracted}" -xf "${db}"
+ while read -rd '' pkg; do
+ read -r match
+ pkg=${pkg#${extracted}/}
+ pkg="${prefix}${pkg%-*-*/links}"
+
+ if (( VERBOSE )); then
+ printf '%-35s %s\n' "${pkg}" "${match}"
+ else
+ printf '%s\n' "${pkg}"
+ fi
+ done < <(grep -rZ "${lib}" "${extracted}") | sort -u
+ fi
+ done
+ done | resort
+}
+
+usage() {
+ cat <<- _EOF_
+ Usage: ${BASH_SOURCE[0]##*/} [OPTIONS] REPO LIBNAME
+
+ Check the soname links database for Arch Linux repositories containing
+ packages linked to a given shared library. If the repository specified
+ is "all", then all repositories will be searched, otherwise only the
+ named repository will be searched.
+
+ If the links database does not exist, it will be downloaded first.
+
+ OPTIONS
+ -v, --verbose Show matched links in addition to pkgname
+ -r, --refresh Refresh the links databases
+ -h, --help Show this help text
+_EOF_
+}
+
+# utility function to resort with multiple repos + no-verbose
+resort() { sort -u; }
+
+if (( $# == 0 )); then
+ echo "error: No arguments passed."
+ echo "Try '${BASH_SOURCE[0]##*/} --help' for more information."
+ exit 1
+fi
+OPT_SHORT='vrh'
+OPT_LONG=('verbose' 'refresh' 'help')
+if ! parseopts "$OPT_SHORT" "${OPT_LONG[@]}" -- "$@"; then
+ exit 1
+fi
+set -- "${OPTRET[@]}"
+
+while :; do
+ case $1 in
+ -v|--verbose)
+ resort() { cat; }
+ VERBOSE=1
+ ;;
+ -r|--refresh)
+ REFRESH=1
+ ;;
+ -h|--help)
+ usage
+ exit 0
+ ;;
+ --)
+ shift; break
+ ;;
+ esac
+ shift
+done
+
+if ! (( ( REFRESH && $# == 0 ) || $# == 2 )); then
+ echo "error: Incorrect number of arguments passed."
+ echo "Try '${BASH_SOURCE[0]##*/} --help' for more information."
+ exit 1
+fi
+
+# trigger a refresh if requested explicitly or the cached dbs might be outdated
+if (( REFRESH )) || [[ ! -d ${SOCACHE_DIR} ]] || is_outdated_cache; then
+ recache
+ (( $# == 2 )) || exit 0
+fi
+
+search "$@"