SPS · log · files · refs · tags · releases · people · languages · GitHub · file
bin/src
25104 bytes at 2909919 · GitHub
#!/bin/sh
sps_prog=src
sps_bin_dir=$(CDPATH= cd -P "$(dirname "$0")" 2>/dev/null && pwd) ||
exit 1
if [ -z "${SPS_LIBDIR+x}" ]; then
if [ -r "$sps_bin_dir/../lib/common.sh" ]; then
SPS_LIBDIR=$sps_bin_dir/../lib
else
SPS_LIBDIR=$sps_bin_dir/../lib/sps
fi
fi
if ! . "$SPS_LIBDIR/common.sh"; then
printf '%s\n' "src: cannot load $SPS_LIBDIR/common.sh" >&2
exit 1
fi
sps_load_config || exit $?
sps_index_dir=$SPS_CACHE/indexes
sps_index=$sps_index_dir/packages.index
sps_tab=$(printf '\tX')
sps_tab=${sps_tab%X}
src_quiet=0
src_usage()
{
printf '%s\n' 'usage: src [-q|--quiet] update'
printf '%s\n' ' src check RECIPE... [--deps]'
printf '%s\n' ' src search PATTERN [--raw]'
printf '%s\n' ' src show PACKAGE [--raw]'
printf '%s\n' ' src which PACKAGE'
printf '%s\n' ' src list [--raw]'
printf '%s\n' ' src status [--raw]'
}
src_progress()
{
[ "${src_quiet:-0}" -eq 0 ] || return 0
printf '%s: %s\n' "$sps_prog" "$*" >&2
}
# True when the package directory has files/, patches/, or hooks/ (including
# a dangling symlink of those names). Those still need the full definition
# hasher; recipe-only packages can share one sha256sum batch.
src_recipe_needs_support()
{
src_support_dir=$1
for src_support_name in files patches hooks; do
if [ -e "$src_support_dir/$src_support_name" ] ||
[ -L "$src_support_dir/$src_support_name" ]; then
return 0
fi
done
return 1
}
# Print hashing progress. Small repositories still log every recipe; large
# ones log the first, last, and every 25th so stderr stays useful without
# becoming the slow path.
src_progress_hash()
{
src_ph_repo=$1
src_ph_n=$2
src_ph_total=$3
src_ph_label=$4
if [ "$src_ph_total" -le 8 ] ||
[ "$src_ph_n" -eq 1 ] ||
[ "$src_ph_n" -eq "$src_ph_total" ] ||
[ $((src_ph_n % 25)) -eq 0 ]; then
src_progress "$src_ph_repo $src_ph_n/$src_ph_total $src_ph_label"
fi
}
src_need_index()
{
[ -r "$sps_index" ] ||
sps_die "$SPS_EX_NOTFOUND" "repository index not found; run 'src update'"
}
src_cleanup_update()
{
if [ -n "${src_clone_work:-}" ]; then
rm -rf "$src_clone_work"
src_clone_work=
fi
if [ -n "${src_work:-}" ]; then
rm -f "$src_work/repos.raw" "$src_work/repos" \
"$src_work/recipes.unsorted" "$src_work/recipes" \
"$src_work/simple" "$src_work/simple.raw" \
"$src_work/digests" "$src_work/packages.index"
rmdir "$src_work" 2>/dev/null || :
src_work=
fi
sps_lock_release
}
src_git_verify_checkout()
{
src_verify_checkout=$1
src_verify_source=$2
[ -d "$src_verify_checkout" ] && [ ! -L "$src_verify_checkout" ] ||
return 1
src_verify_top=$(git -C "$src_verify_checkout" rev-parse --show-toplevel \
2>/dev/null) || return 1
src_verify_top=$(CDPATH= cd -P "$src_verify_top" 2>/dev/null && pwd -P) ||
return 1
src_verify_expected=$(CDPATH= cd -P "$src_verify_checkout" 2>/dev/null &&
pwd -P) || return 1
[ "$src_verify_top" = "$src_verify_expected" ] || return 1
src_verify_origin=$(git -C "$src_verify_checkout" remote get-url origin \
2>/dev/null) || return 1
[ "$src_verify_origin" = "$src_verify_source" ]
}
src_sync_git()
{
src_git_name=$1
src_git_source=$2
src_git_checkout=$3
sps_require_cmd git
src_git_parent=${src_git_checkout%/*}
[ -n "$src_git_parent" ] || src_git_parent=/
sps_mkdir "$src_git_parent"
GIT_TERMINAL_PROMPT=0
export GIT_TERMINAL_PROMPT
if [ ! -e "$src_git_checkout" ] && [ ! -L "$src_git_checkout" ]; then
src_clone_work=$(sps_mktemp_dir "$src_git_parent" \
"clone-$src_git_name")
src_clone_checkout=$src_clone_work/repository
src_progress "cloning '$src_git_name'"
# Depth 1 is enough for recipes. Later fetches stay full so
# fast-forward and divergence checks keep working.
# --no-tags skips tag objects that would otherwise bloat fetch
# on remotes with a long tag history. Branch tips are still
# fetched. --progress keeps clone/fetch from looking hung when
# stderr is not a terminal (setup, logs, scripted live installs).
if ! git clone --depth 1 --single-branch --no-tags --progress -- \
"$src_git_source" "$src_clone_checkout"; then
sps_die "$SPS_EX_NETWORK" \
"cannot clone repository '$src_git_name'"
fi
if ! src_git_verify_checkout "$src_clone_checkout" "$src_git_source"; then
sps_die "$SPS_EX_PACKAGE" \
"cloned repository '$src_git_name' failed checkout verification"
fi
if [ -e "$src_git_checkout" ] || [ -L "$src_git_checkout" ]; then
sps_die "$SPS_EX_CONFLICT" \
"repository checkout appeared while cloning: $src_git_checkout"
fi
if ! mv "$src_clone_checkout" "$src_git_checkout"; then
sps_die "$SPS_EX_PERMISSION" \
"cannot commit repository checkout: $src_git_checkout"
fi
rmdir "$src_clone_work" 2>/dev/null || :
src_clone_work=
printf "%s: cloned repository '%s' into %s\n" \
"$sps_prog" "$src_git_name" "$src_git_checkout" >&2
return 0
fi
if ! src_git_verify_checkout "$src_git_checkout" "$src_git_source"; then
if [ -d "$src_git_checkout" ] && [ ! -L "$src_git_checkout" ] &&
git -C "$src_git_checkout" rev-parse --is-inside-work-tree \
>/dev/null 2>&1; then
sps_die "$SPS_EX_CONFLICT" \
"repository '$src_git_name' origin does not match its configured source"
fi
sps_die "$SPS_EX_CONFLICT" \
"repository checkout is not the expected Git worktree: $src_git_checkout"
fi
src_git_dirty=$(git -C "$src_git_checkout" status --porcelain \
--untracked-files=normal) ||
sps_die "$SPS_EX_PACKAGE" \
"cannot inspect repository '$src_git_name'"
if [ -n "$src_git_dirty" ]; then
sps_die "$SPS_EX_CONFLICT" \
"repository '$src_git_name' has local modifications; refusing to update $src_git_checkout"
fi
src_progress "fetching '$src_git_name'"
if ! git -C "$src_git_checkout" fetch --no-tags --progress origin; then
sps_die "$SPS_EX_NETWORK" \
"cannot fetch repository '$src_git_name'"
fi
if ! src_git_branch=$(git -C "$src_git_checkout" symbolic-ref -q \
--short HEAD 2>/dev/null); then
printf "%s: repository '%s' is detached and remains pinned at %s\n" \
"$sps_prog" "$src_git_name" \
"$(git -C "$src_git_checkout" rev-parse --short HEAD)" >&2
return 0
fi
if ! src_git_upstream=$(git -C "$src_git_checkout" rev-parse \
--abbrev-ref --symbolic-full-name '@{upstream}' 2>/dev/null); then
printf "%s: repository '%s' branch '%s' has no upstream and remains pinned\n" \
"$sps_prog" "$src_git_name" "$src_git_branch" >&2
return 0
fi
case $src_git_upstream in
origin/*) ;;
*)
printf "%s: repository '%s' tracks '%s', not origin, and remains pinned\n" \
"$sps_prog" "$src_git_name" "$src_git_upstream" >&2
return 0
;;
esac
src_git_head=$(git -C "$src_git_checkout" rev-parse HEAD) ||
sps_die "$SPS_EX_PACKAGE" "cannot read HEAD for repository '$src_git_name'"
src_git_upstream_head=$(git -C "$src_git_checkout" rev-parse \
"$src_git_upstream") ||
sps_die "$SPS_EX_PACKAGE" \
"cannot read upstream for repository '$src_git_name'"
if [ "$src_git_head" = "$src_git_upstream_head" ]; then
src_progress "repository '$src_git_name' is up to date"
return 0
fi
if git -C "$src_git_checkout" merge-base --is-ancestor \
"$src_git_head" "$src_git_upstream_head"; then
src_progress "fast-forwarding '$src_git_name'"
if ! git -C "$src_git_checkout" merge --ff-only \
"$src_git_upstream" >&2; then
sps_die "$SPS_EX_CONFLICT" \
"cannot fast-forward repository '$src_git_name'"
fi
return 0
fi
if git -C "$src_git_checkout" merge-base --is-ancestor \
"$src_git_upstream_head" "$src_git_head"; then
printf "%s: repository '%s' is ahead of %s and was left unchanged\n" \
"$sps_prog" "$src_git_name" "$src_git_upstream" >&2
return 0
fi
sps_die "$SPS_EX_CONFLICT" \
"repository '$src_git_name' has diverged from $src_git_upstream; refusing to update"
}
src_update()
{
while [ "$#" -gt 0 ]; do
case $1 in
-q|--quiet) src_quiet=1; shift ;;
-v|--verbose) src_quiet=0; shift ;;
*) break ;;
esac
done
[ "$#" -eq 0 ] || {
src_usage >&2
exit "$SPS_EX_USAGE"
}
src_progress "updating package index"
sps_mkdir "$sps_index_dir"
src_work=
src_clone_work=
sps_lock_acquire "$SPS_CACHE" .src-update 'repository update' ||
sps_die "$SPS_EX_CONFLICT" "another repository update is active"
trap src_cleanup_update 0
trap 'exit 129' 1
trap 'exit 130' 2
trap 'exit 131' 3
trap 'exit 143' 15
src_work=$(sps_mktemp_dir "$sps_index_dir" update)
if ! sps_repo_lines > "$src_work/repos.raw"; then
sps_die "$SPS_EX_USAGE" "cannot read repository configuration"
fi
if ! awk -v action=normalize -v program=src \
-v repo_root="$SPS_REPO_ROOT" \
-f "$SPS_LIBDIR/repository.awk" "$src_work/repos.raw" \
> "$src_work/repos"; then
sps_die "$SPS_EX_USAGE" "invalid repository configuration"
fi
: > "$src_work/packages.index" ||
sps_die "$SPS_EX_PERMISSION" "cannot create repository index"
: > "$src_work/digests" ||
sps_die "$SPS_EX_PERMISSION" "cannot create recipe digest map"
src_default_arch=$SPS_ARCH
src_repo_count=0
src_package_count=0
src_failed=0
while IFS="$sps_tab" read -r src_repo_kind src_repo_name \
src_repo_source src_repo_path src_repo_priority src_repo_order
do
[ -n "$src_repo_name" ] || continue
src_progress "repository '$src_repo_name' ($src_repo_kind)"
case $src_repo_kind in
git) src_sync_git "$src_repo_name" "$src_repo_source" "$src_repo_path" ;;
dir) ;;
*)
printf "%s: internal error: unsupported repository kind '%s'\n" \
"$sps_prog" "$src_repo_kind" >&2
src_failed=1
break
;;
esac
if [ ! -d "$src_repo_path" ]; then
printf "%s: repository '%s' is not a local directory: %s\n" \
"$sps_prog" "$src_repo_name" "$src_repo_path" >&2
src_failed=1
break
fi
src_repo_absolute=$(CDPATH= cd -P "$src_repo_path" 2>/dev/null &&
pwd -P) || {
printf "%s: cannot enter repository '%s': %s\n" \
"$sps_prog" "$src_repo_name" "$src_repo_path" >&2
src_failed=1
break
}
src_progress "scanning recipes in '$src_repo_name'"
if ! find "$src_repo_absolute" \
\( -type d \( -name .git -o -name files -o -name patches -o \
-name hooks \) -prune \) -o \
\( -type f -name recipe -print \) \
> "$src_work/recipes.unsorted"; then
printf "%s: cannot scan repository '%s': %s\n" \
"$sps_prog" "$src_repo_name" "$src_repo_absolute" >&2
src_failed=1
break
fi
if ! LC_ALL=C sort "$src_work/recipes.unsorted" \
> "$src_work/recipes"; then
printf "%s: cannot sort recipes for repository '%s'\n" \
"$sps_prog" "$src_repo_name" >&2
src_failed=1
break
fi
: > "$src_work/digests" || {
printf "%s: cannot create recipe digest map\n" "$sps_prog" >&2
src_failed=1
break
}
: > "$src_work/simple" || {
printf "%s: cannot create recipe hash list\n" "$sps_prog" >&2
src_failed=1
break
}
src_repo_packages=0
src_recipe_total=$(awk 'END { print NR + 0 }' "$src_work/recipes")
src_progress "indexing '$src_repo_name' ($src_recipe_total recipes)"
while IFS= read -r src_recipe || [ -n "$src_recipe" ]
do
[ -n "$src_recipe" ] || continue
if src_recipe_needs_support "${src_recipe%/*}"; then
continue
fi
printf '%s\n' "$src_recipe" >> "$src_work/simple" || {
printf "%s: cannot record recipe hash list: %s\n" \
"$sps_prog" "$src_recipe" >&2
src_failed=1
break
}
done < "$src_work/recipes"
[ "$src_failed" -eq 0 ] || break
src_batch_ok=0
if command -v sha256sum >/dev/null 2>&1 &&
command -v xargs >/dev/null 2>&1 &&
[ -s "$src_work/simple" ]; then
if tr '\n' '\0' < "$src_work/simple" |
xargs -0 sha256sum -- > "$src_work/simple.raw"; then
src_simple_n=$(awk 'END { print NR + 0 }' "$src_work/simple")
src_hash_n=$(awk 'END { print NR + 0 }' "$src_work/simple.raw")
if [ "$src_simple_n" -eq "$src_hash_n" ]; then
src_batch_ok=1
fi
fi
fi
if [ "$src_batch_ok" -eq 1 ]; then
exec 3< "$src_work/simple.raw" || {
printf "%s: cannot read batched recipe hashes\n" \
"$sps_prog" >&2
src_failed=1
break
}
fi
while IFS= read -r src_recipe || [ -n "$src_recipe" ]
do
[ -n "$src_recipe" ] || continue
if ! sps_tab_safe "$src_recipe"; then
printf "%s: recipe path contains a tab or newline: %s\n" \
"$sps_prog" "$src_recipe" >&2
src_failed=1
break
fi
if [ "$src_batch_ok" -eq 1 ] &&
! src_recipe_needs_support "${src_recipe%/*}"; then
read -r src_file_hash src_hash_rest <&3 || {
printf "%s: batched recipe hash missing: %s\n" \
"$sps_prog" "$src_recipe" >&2
src_failed=1
break
}
src_digest=$(sps_definition_from_recipe_file_hash \
"$src_file_hash") || {
printf "%s: cannot hash package definition: %s\n" \
"$sps_prog" "$src_recipe" >&2
src_failed=1
break
}
else
src_digest=$(sps_definition_sha256 "$src_recipe") || {
printf "%s: cannot hash package definition: %s\n" \
"$sps_prog" "$src_recipe" >&2
src_failed=1
break
}
fi
case $src_digest in
''|*[!0123456789abcdefABCDEF]*)
printf "%s: invalid package definition SHA-256: %s\n" \
"$sps_prog" "$src_recipe" >&2
src_failed=1
break
;;
esac
if [ "${#src_digest}" -ne 64 ]; then
printf "%s: invalid package definition SHA-256: %s\n" \
"$sps_prog" "$src_recipe" >&2
src_failed=1
break
fi
printf '%s\t%s\n' "$src_recipe" "$src_digest" \
>> "$src_work/digests" || {
printf "%s: cannot record recipe digest: %s\n" \
"$sps_prog" "$src_recipe" >&2
src_failed=1
break
}
src_repo_packages=$((src_repo_packages + 1))
src_recipe_label=${src_recipe%/*}
src_recipe_label=${src_recipe_label##*/}
src_progress_hash "$src_repo_name" "$src_repo_packages" \
"$src_recipe_total" "$src_recipe_label"
done < "$src_work/recipes"
if [ "$src_batch_ok" -eq 1 ]; then
exec 3<&-
fi
[ "$src_failed" -eq 0 ] || break
if [ "$src_repo_packages" -gt 0 ]; then
src_progress "parsing recipes in '$src_repo_name'"
if ! awk -v recipe_repo="$src_repo_name" \
-v recipe_priority="$src_repo_priority" \
-v recipe_digest_map="$src_work/digests" \
-v recipe_file_list="$src_work/recipes" \
-v recipe_default_arch="$src_default_arch" \
-f "$SPS_LIBDIR/recipe.awk" \
>> "$src_work/packages.index"; then
src_failed=1
break
fi
fi
src_package_count=$((src_package_count + src_repo_packages))
src_repo_count=$((src_repo_count + 1))
done < "$src_work/repos"
if [ "$src_failed" -ne 0 ]; then
sps_die "$SPS_EX_PACKAGE" \
"repository update failed; previous index was preserved"
fi
src_progress "validating index"
if ! awk -v action=validate -v program=src \
-f "$SPS_LIBDIR/index.awk" "$src_work/packages.index"; then
sps_die "$SPS_EX_PACKAGE" \
"generated repository index is malformed"
fi
src_progress "validating dependency graph"
if ! awk -v action=validate -v include_build=1 -v program=src \
-f "$SPS_LIBDIR/version.awk" -f "$SPS_LIBDIR/deps.awk" \
"$src_work/packages.index"; then
sps_die "$SPS_EX_DEPENDENCY" \
"generated repository dependency graph is invalid"
fi
if ! mv "$src_work/packages.index" "$sps_index"; then
sps_die "$SPS_EX_PERMISSION" "cannot commit repository index"
fi
printf 'updated %d repositories, %d package records\n' \
"$src_repo_count" "$src_package_count"
src_cleanup_update
trap - 0 1 2 3 15
}
src_repositories()
{
src_repo_action=$1
shift
src_raw=0
case ${1-} in
--raw) src_raw=1; shift ;;
esac
[ "$#" -eq 0 ] || {
src_usage >&2
exit "$SPS_EX_USAGE"
}
if [ "$src_repo_action" = list ]; then
[ "$src_raw" -eq 0 ] || src_repo_action=raw
else
[ "$src_raw" -eq 0 ] || src_repo_action=status_raw
fi
sps_repo_lines |
awk -v action="$src_repo_action" -v program=src \
-v repo_root="$SPS_REPO_ROOT" \
-v index_file="$sps_index" \
-f "$SPS_LIBDIR/repository.awk"
}
src_query()
{
src_action=$1
shift
sps_need_arg "$src_action" "${1-}"
src_query_value=$1
shift
src_raw=0
case ${1-} in
--raw) src_raw=1; shift ;;
esac
[ "$#" -eq 0 ] || {
src_usage >&2
exit "$SPS_EX_USAGE"
}
src_need_index
case $src_action in
search)
sps_tab_safe "$src_query_value" ||
sps_die "$SPS_EX_USAGE" "search pattern contains a tab or newline"
[ "$src_raw" -eq 0 ] ||
src_action=search_raw
;;
show)
sps_validate_package_name "$src_query_value" ||
sps_die "$SPS_EX_USAGE" \
"invalid package name '$src_query_value'"
[ "$src_raw" -eq 0 ] ||
src_action=exact
;;
which)
sps_validate_package_name "$src_query_value" ||
sps_die "$SPS_EX_USAGE" \
"invalid package name '$src_query_value'"
[ "$src_raw" -eq 0 ] ||
sps_die "$SPS_EX_USAGE" "'src which' does not accept --raw"
;;
esac
awk -v action="$src_action" -v query="$src_query_value" \
-v program=src -f "$SPS_LIBDIR/index.awk" "$sps_index"
}
# src_check validates one or more recipes with the same parser that src update
# uses, without downloading sources or running any build phase. It accepts a
# recipe file or a directory containing a 'recipe' file. A failed recipe is
# reported and the command exits nonzero, so it is safe to gate automation on.
src_check()
{
src_check_deps=0
src_check_recipes_file=
src_check_work=
src_check_cleanup()
{
[ -n "${src_check_recipes_file:-}" ] &&
rm -f "$src_check_recipes_file"
src_check_recipes_file=
if [ -n "${src_check_work:-}" ]; then
rm -f "$src_check_work/packages.index"
rmdir "$src_check_work" 2>/dev/null || :
src_check_work=
fi
}
src_check_recipes_file=$(mktemp "${TMPDIR:-/tmp}/sps-src-check.XXXXXX") ||
exit "$SPS_EX_PERMISSION"
trap src_check_cleanup 0
trap 'exit 129' 1
trap 'exit 130' 2
trap 'exit 131' 3
trap 'exit 143' 15
while [ "$#" -gt 0 ]; do
case $1 in
--deps)
src_check_deps=1
;;
--help|-h)
printf '%s\n' 'usage: src check RECIPE... [--deps]'
src_check_cleanup
trap - 0 1 2 3 15
exit 0
;;
-*)
src_usage >&2
src_check_cleanup
trap - 0 1 2 3 15
exit "$SPS_EX_USAGE"
;;
*)
if [ -d "$1" ] && [ ! -L "$1" ]; then
src_check_resolve="$1/recipe"
else
src_check_resolve=$1
fi
if [ ! -f "$src_check_resolve" ] ||
[ -L "$src_check_resolve" ] ||
[ ! -r "$src_check_resolve" ]; then
src_check_cleanup
trap - 0 1 2 3 15
sps_die "$SPS_EX_NOTFOUND" \
"no readable recipe file at '$1'"
fi
printf '%s\n' "$src_check_resolve" >>"$src_check_recipes_file" ||
sps_die "$SPS_EX_PERMISSION" "cannot record recipe path"
;;
esac
shift
done
if [ ! -s "$src_check_recipes_file" ]; then
printf '%s\n' 'usage: src check RECIPE... [--deps]' >&2
src_check_cleanup
trap - 0 1 2 3 15
exit "$SPS_EX_USAGE"
fi
if [ "$src_check_deps" -eq 1 ]; then
src_check_work=$(sps_mktemp_dir "$SPS_BUILD/.check") || exit $?
src_check_index=$src_check_work/packages.index
else
src_check_index=/dev/null
fi
src_check_failed=0
src_check_count=0
src_check_arch=${SPS_ARCH:-$(uname -m 2>/dev/null || printf unknown)}
while IFS= read -r src_check_recipe || [ -n "$src_check_recipe" ]
do
[ -n "$src_check_recipe" ] || continue
src_check_count=$((src_check_count + 1))
src_check_digest=$(sps_definition_sha256 "$src_check_recipe") || {
printf 'check: FAILED %s (definition digest)\n' \
"$src_check_recipe" >&2
src_check_failed=1
continue
}
src_check_name=$(awk -v recipe_path="$src_check_recipe" '
/^[ \t]*name[ \t]+/ {
line = $0
sub(/^[ \t]*name[ \t]+/, "", line)
sub(/[ \t\r]+$/, "", line)
print line
exit
}
' "$src_check_recipe")
if [ "$src_check_deps" -eq 1 ]; then
src_check_target=$src_check_index
else
src_check_target=/dev/null
fi
if awk -v recipe_repo=check -v recipe_priority=100 \
-v recipe_path="$src_check_recipe" \
-v recipe_sha256="$src_check_digest" \
-v recipe_default_arch="$src_check_arch" \
-f "$SPS_LIBDIR/recipe.awk" "$src_check_recipe" \
>> "$src_check_target" 2>/dev/null; then
printf 'check: ok %s (%s)\n' "$src_check_recipe" \
"$src_check_name"
else
printf 'check: FAILED %s (%s)\n' "$src_check_recipe" \
"$src_check_name" >&2
src_check_failed=1
fi
done < "$src_check_recipes_file"
if [ "$src_check_failed" -ne 0 ]; then
src_check_cleanup
trap - 0 1 2 3 15
sps_die "$SPS_EX_PACKAGE" \
"$src_check_count recipe(s) checked: at least one failed"
fi
if [ "$src_check_deps" -eq 1 ]; then
if ! awk -v action=validate -v program=src \
-f "$SPS_LIBDIR/index.awk" "$src_check_index"; then
src_check_cleanup
trap - 0 1 2 3 15
sps_die "$SPS_EX_PACKAGE" "generated check index is malformed"
fi
if ! awk -v action=validate -v program=src \
-f "$SPS_LIBDIR/version.awk" -f "$SPS_LIBDIR/deps.awk" \
"$src_check_index"; then
src_check_cleanup
trap - 0 1 2 3 15
sps_die "$SPS_EX_DEPENDENCY" "checked dependency graph is invalid"
fi
fi
printf 'checked %d recipe(s)\n' "$src_check_count"
src_check_cleanup
trap - 0 1 2 3 15
}
while [ "$#" -gt 0 ]; do
case $1 in
-q|--quiet) src_quiet=1; shift ;;
-v|--verbose) src_quiet=0; shift ;;
-h|--help)
src_usage
exit 0
;;
--) shift; break ;;
-*)
src_usage >&2
exit "$SPS_EX_USAGE"
;;
*) break ;;
esac
done
case ${1-} in
update)
shift
src_update "$@"
;;
check)
shift
src_check "$@"
;;
search|show|which)
src_command=$1
shift
src_query "$src_command" "$@"
;;
list|status)
src_command=$1
shift
src_repositories "$src_command" "$@"
;;
-h|--help)
src_usage
;;
*)
src_usage >&2
exit "$SPS_EX_USAGE"
;;
esac