#!/usr/bin/env bash

# Print all (transitive) dependencies of the specified go package.

set -euo pipefail

if [ $# -gt 1 ]; then
    echo "Usage: $0 [root]" >&2
    exit 64
fi
declare -r MODULE=${1:-github.com/linkerd/linkerd2}

GRAPH=$(go mod graph)
declare -r GRAPH

deps_of() {
    local pkg=$1
    echo "$GRAPH" | awk '$1 == "'"$pkg"'" { print $2 }' | sort | uniq
}

declare -A PKGS=()
subtree() {
    local pkg=$1
    local namepfx=${2:-}
    local pfx=${3:-}
    # If the package has already been printed, then print it with an
    # asterisk and skip printing its dependencies
    if (( ${PKGS[$pkg]:-0} )); then
        echo "$namepfx$pkg (*)"
    else
        # Otherwise, print the package, mark it as printed, and the
        # dependency tree for each of its depndencies
        echo "$namepfx$pkg"
        PKGS[$pkg]=1
        local dep=''
        for d in $(deps_of "$pkg") ; do
            if [ -n "$dep" ]; then  subtree "$dep" "$pfx├── " "$pfx│   " ; fi
            dep=$d
        done
        if [ -n "$dep" ]; then subtree "$dep" "$pfx└── " "$pfx    " ; fi
    fi
}

if [[ "$MODULE" == *@* ]]; then
    # The root specifies an exact version, so print its dependencies.
    subtree "$MODULE"
elif [ -n "$(echo "$GRAPH" | awk '$1 == "'"$MODULE"'" { print $0 }' | head -n 1)" ]; then
    # The root does not specify an exact version, but that is how the
    # package is listed in go.mod.
    subtree "$MODULE"
else
    # The root does not specify an exact version, find all versions of the
    # package and print their depdencies.
    first=1
    for pkg in $(echo "$GRAPH" | awk '{ print $1 }' | sort | uniq) ; do
        if [ "${pkg%@*}" = "$MODULE" ]; then
            if (( first )); then first=0; else echo; fi
            subtree "$pkg"
        fi
    done
fi
