Skip to content

Instantly share code, notes, and snippets.

@robin-a-meade
Last active March 30, 2024 19:49
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save robin-a-meade/a1237d7ff7cbe6dc159fa32a81c12948 to your computer and use it in GitHub Desktop.
Save robin-a-meade/a1237d7ff7cbe6dc159fa32a81c12948 to your computer and use it in GitHub Desktop.
resolve dependencies and print classpath. This is a wrapper around `jbang info classpath`.
#!/bin/bash
# NAME
# deps_to_classpath - resolve dependencies and print classpath
#
# SYNOPSIS
# deps_to_classpath [OPTIONS] DEP...
#
# EXAMPLE
# Suppose you are evaluating different HTML parsers to use with saxon. You
# could do this:
#
# DEPS=(
# net.sf.saxon:Saxon-HE:12.4
# org.ccil.cowan.tagsoup:tagsoup:1.2.1
# nu.validator:htmlparser:1.4.16
# )
# CP=$(deps_to_classpath --quiet "${DEPS[@]}")
# java -cp "${CP}" net.sf.saxon.Query -x:org.ccil.cowan.tagsoup.Parser -s:doc.html -qs:.
# java -cp "${CP}" net.sf.saxon.Query -x:nu.validator.htmlparser.sax.HtmlParser -s:doc.html -qs:.
#
#
# ALTERNATIVES
#
# 1) `jbang deps-to-classpath@robin-a-meade DEP...`
# https://github.com/robin-a-meade/jbang-catalog
#
# 2) `jbang jecho@robin-a-meade "%{deps:$(IFS=,; echo "${DEPS[*]}")}"`
# This uses the `%{deps:...}` syntax added in pull request
# https://github.com/jbangdev/jbang/pull/1707
#
# CAVEAT
# This script assumes the `:` classpath separator. This script does not
# support Windows.
#
# IMPLEMENTATION NOTES
# ====================
#
# This is a wrapper around `jbang info classpath`.
#
# jbang info classpath OPTIONS <scriptOrFile>
# https://www.jbang.dev/documentation/guide/latest/cli/jbang-info-classpath.html
#
# A complication is that the <scriptOrFile> argument is required.
#
# Trick: We can specify /dev/null as the file
#
# But we'll then need to remove the bogus classpath element it creates.
#
# Fortunately, the bogus classpath element is always the first classpath
# element. This makes it easy to remove.
#
# One way to remove this bogus classpath element would be to pipe it into sed
# as follows:
#
# jbang info classpath --deps "$(IFS=,; echo "$*")" /dev/null | sed 's/^[^:]*://'
#
# Another way would be to capture the output in a bash variable and use bash
# parameter expansion `${var#*:}`. We take this latter approach because it
# offers greater flexibility in error handling.
PROGNAME=$(basename "$0")
die () { echo "$PROGNAME: $@"; exit 1; }
# Test if jbang is on PATH
# https://unix.stackexchange.com/q/4988#comment1329942_4991
if ! type -P jbang >/dev/null; then
die "couldn't find jbang executable on PATH"
fi
# Collect any options, so that we can pass them along later in the invocation
# For example, the user may wish to use the `--fresh` and/or `--quiet` options.
declare -a OPTIONS=()
while :; do
case $1 in
--)
# POSIX convention of '--' signifying end of options
OPTIONS+=($1)
shift
break
;;
-*)
# Found an option
OPTIONS+=($1)
shift
continue
;;
*)
# This is not an option
# Must be a dependency argument
# We're done collecting options
break
esac
done
# The remaining arguments are dependencies
#
# Call `jbang info classpath`
#
if result=$(jbang info classpath "${OPTIONS[@]}" --deps "$(IFS=,; echo "$*")" /dev/null); then
result=${result#*:} # Chop off the bogus classpath element corresponding to /dev/null
echo "$result"
else
die "an error occurred"
fi
# NOTE TO SELF: Yes, it is OK to use an assignment of a command substitution as
# the condition for an if statement (as long as you don't use `local` at the
# same time).
# https://unix.stackexchange.com/a/234651
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment