add sogrep command

This is the new and improved, canonical sogrep command, now with a valid
license.

The previous version of sogrep had several issues and inefficiencies,
and ultimately wasn't really the finished project I wanted it to be. Due
to a mistake in communication, I was totally unaware it was in the
process of being merged at all, nor that there was a licensing issue, or
I would have recommended waiting for both further improvements, and a
declaration of license intent; nevertheless, here it is now, and I
formally give this over into the GPLv2+ domain.

Signed-off-by: Eli Schwartz <eschwartz@archlinux.org>
This commit is contained in:
Eli Schwartz via arch-projects 2019-03-25 16:32:19 -04:00 committed by Levente Polyak
parent ebba5a5885
commit 1ab9b34c4c
No known key found for this signature in database
GPG Key ID: FC1B547C8D8172C8
1 changed files with 76 additions and 25 deletions

101
sogrep Normal file → Executable file
View File

@ -1,6 +1,24 @@
#!/bin/bash #!/bin/bash
# License: Unspecified #
# sogrep - find shared library links in an Arch Linux repository.
#
# Copyright (c) 2019 by Eli Schwartz <eschwartz@archlinux.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 2 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 <https://www.gnu.org/licenses/>.
#
# globals
: ${SOLINKS_MIRROR:="https://mirror.pkgbuild.com"} : ${SOLINKS_MIRROR:="https://mirror.pkgbuild.com"}
: ${SOCACHE_DIR:="${XDG_CACHE_HOME:-${HOME}/.cache}/sogrep"} : ${SOCACHE_DIR:="${XDG_CACHE_HOME:-${HOME}/.cache}/sogrep"}
repos=('staging' 'testing' 'core' 'extra' repos=('staging' 'testing' 'core' 'extra'
@ -9,54 +27,66 @@ repos=('staging' 'testing' 'core' 'extra'
'gnome-unstable' 'kde-unstable') 'gnome-unstable' 'kde-unstable')
arches=('x86_64') arches=('x86_64')
# options
REFRESH=0
VERBOSE=0
source /usr/share/makepkg/util/parseopts.sh
source /usr/share/makepkg/util/util.sh source /usr/share/makepkg/util/util.sh
recache() { recache() {
local repo arch local repo arch verbosity=-s
(( VERBOSE )) && verbosity=--progress-bar
for repo in "${repos[@]}"; do for repo in "${repos[@]}"; do
for arch in "${arches[@]}"; do for arch in "${arches[@]}"; do
rm -rf "${SOCACHE_DIR}/${arch}/${repo}" rm -rf "${SOCACHE_DIR}/${arch}/${repo}"
mkdir -p "${SOCACHE_DIR}/${arch}/${repo}" mkdir -p "${SOCACHE_DIR}/${arch}/${repo}"
curl "${SOLINKS_MIRROR}/${repo}/os/${arch}/${repo}.links.tar.gz" | bsdtar -xf - -C "${SOCACHE_DIR}/${arch}/${repo}" curl "$verbosity" "${SOLINKS_MIRROR}/${repo}/os/${arch}/${repo}.links.tar.gz" | bsdtar -xf - -C "${SOCACHE_DIR}/${arch}/${repo}"
done done
done done
} }
search() { search() {
local repo=$1 arch lib=$2 local repo=$1 arch lib=$2 srepos=("${repos[@]}")
if [[ $repo != all ]]; then if [[ $repo != all ]]; then
if ! in_array "$repo" "${repos[@]}"; then if ! in_array "${repo}" "${repos[@]}"; then
echo "${BASH_SOURCE[0]##*/}: unrecognized repo '$repo'" echo "${BASH_SOURCE[0]##*/}: unrecognized repo '$repo'"
echo "Try '${BASH_SOURCE[0]##*/} --help' for more information." echo "Try '${BASH_SOURCE[0]##*/} --help' for more information."
exit 1 exit 1
fi fi
local repos=("${repo}") srepos=("${repo}")
fi
if [[ ! -d ${SOCACHE_DIR} ]]; then
recache
fi fi
for arch in "${arches[@]}"; do for arch in "${arches[@]}"; do
for repo in "${repos[@]}"; do for repo in "${srepos[@]}"; do
local prefix=
(( VERBOSE && ${#srepos[@]} > 1 )) && prefix=${repo}/
db=${SOCACHE_DIR}/${arch}/${repo}/ db=${SOCACHE_DIR}/${arch}/${repo}/
if [[ -d ${db} ]]; then if [[ -d ${db} ]]; then
while read -rd '' pkg; do while read -rd '' pkg; do
read -r match
pkg=${pkg#${db}} pkg=${pkg#${db}}
printf '%s/%s\n' "${repo}" "${pkg%-*-*/links}" pkg="${prefix}${pkg%-*-*/links}"
done < <(grep -rlZ "${lib}" "${db}")
if (( VERBOSE )); then
printf '%-35s %s\n' "${pkg}" "${match}"
else
printf '%s\n' "${pkg}"
fi
done < <(grep -rZ "${lib}" "${db}") | sort -u
fi fi
done done
done | sort -u done | resort
} }
usage() { usage() {
cat <<- _EOF_ cat <<- _EOF_
Usage: ${BASH_SOURCE[0]##*/} [OPTIONS] REPO LIBNAME Usage: ${BASH_SOURCE[0]##*/} [OPTIONS] REPO LIBNAME
Check the soname links database for pacman repositories containing Check the soname links database for Arch Linux repositories containing
packages linked to a given shared library. If the repository specified packages linked to a given shared library. If the repository specified
is "all", then all repositories will be searched, otherwise only the is "all", then all repositories will be searched, otherwise only the
named repository will be searched. named repository will be searched.
@ -64,35 +94,56 @@ usage() {
If the links database does not exist, it will be downloaded first. If the links database does not exist, it will be downloaded first.
OPTIONS OPTIONS
-v, --verbose Show matched links in addition to pkgname
-r, --refresh Refresh the links databases -r, --refresh Refresh the links databases
-h, --help Show this help text -h, --help Show this help text
_EOF_ _EOF_
} }
# utility function to resort with multiple repos + no-verbose
resort() { sort -u; }
if (( $# == 0 )); then if (( $# == 0 )); then
echo "error: No arguments passed." echo "error: No arguments passed."
echo "Try '${BASH_SOURCE[0]##*/} --help' for more information." echo "Try '${BASH_SOURCE[0]##*/} --help' for more information."
exit 1 exit 1
fi fi
OPT_SHORT='vrh'
OPT_LONG=('verbose' 'refresh' 'help')
if ! parseopts "$OPT_SHORT" "${OPT_LONG[@]}" -- "$@"; then
exit 1
fi
set -- "${OPTRET[@]}"
while (( $# )); do while :; do
case $1 in case $1 in
-v|--verbose)
resort() { cat; }
VERBOSE=1
;;
-r|--refresh) -r|--refresh)
recache REFRESH=1
;; ;;
-h|--help) -h|--help)
usage usage
exit 0 exit 0
;; ;;
*) --)
if (( $# < 2 )); then shift; break
echo "error: Not enough arguments passed."
echo "Try '${BASH_SOURCE[0]##*/} --help' for more information."
exit 1
fi
search "$@"
exit $?
;; ;;
esac esac
shift shift
done 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
if (( REFRESH )) || [[ ! -d ${SOCACHE_DIR} ]]; then
recache
(( $# == 2 )) || exit 0
fi
search "$@"