Files
computer-playbook/scripts/tests/deploy/utils/rescue_index.sh
kevinveenbirkenbachandClaude Opus 5 c51105e289 feat(rescue-index): render the collected tree instead of full paths
An opencloud snapshot carried 174 entries, and every line repeated the whole
path - the deepest ran about 150 characters, most of it the same prefix as the
line above. Print the basename at its depth instead, with a glyph per kind:
folder, json, journal or log, plain text.

The separator is swapped for \001 across the sort. Without it a directory and
its children come apart: '/' outranks '.', so a sibling file sorts between the
two and reads as though it lived inside. The swap also makes the order
independent of the locale, which was deciding it before.

The existing cut-short test looked for 'logs/container.log', which no longer
appears, so it now checks the basename; a fourth case pins the structure rather
than the wording - a child is indented deeper than its folder and siblings sit
level.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-01 12:05:16 +02:00

66 lines
1.8 KiB
Bash
Executable File

#!/usr/bin/env bash
# List the collected rescue tree and where to download it.
#
# Arguments:
# $1 DIR rescue directory to index; a missing directory is not an error
# $2 LIMIT max paths to list, default 400
#
# Exit status: always 0.
set -euo pipefail
trap 'exit 0' EXIT
DIR="${1:?usage: rescue_index.sh DIR [LIMIT]}"
LIMIT="${2:-400}"
[ -d "${DIR}" ] || exit 0
if LISTING="$(find "${DIR}" -mindepth 1 -printf '%y %10s %P\n' 2>/dev/null |
tr '/' '\001' | LC_ALL=C sort -k3 | tr '\001' '/')"; then
WALKED=true
else
WALKED=false
fi
if ! SIZE="$(du -sh "${DIR}" 2>/dev/null | cut -f1)"; then
[ -n "${SIZE}" ] || SIZE="unknown size"
fi
ENTRIES=0
[ -z "${LISTING}" ] || ENTRIES="$(printf '%s\n' "${LISTING}" | wc -l)"
FILES="$(printf '%s\n' "${LISTING}" | awk '$1 == "f"' | wc -l)"
echo "🩺 Rescue diagnostics: ${FILES} file(s), ${SIZE}, under ${DIR}"
echo " Download them from the 'rescue-diagnostics-*' artifact on this run's summary page."
echo " The tree below is the artifact root; file contents are NOT printed here."
[ "${WALKED}" = true ] ||
echo " The walk over ${DIR} was cut short; what follows is only what could be read."
[ -z "${LISTING}" ] || printf '%s\n' "${LISTING}" | sed -n "1,${LIMIT}p" | awk '
{
type = $1
size = $2
path = $0
sub(/^[^ ]+[ ]+[^ ]+[ ]+/, "", path)
depth = split(path, part, "/")
indent = " "
for (i = 1; i < depth; i++) {
indent = indent " "
}
name = part[depth]
if (type == "d") {
printf "%s📁 %s/\n", indent, name
} else {
glyph = "📄"
if (name ~ /\.json$/) {
glyph = "🧾"
} else if (name ~ /\.(log|journal|txt)$/ && name ~ /journal|log/) {
glyph = "📜"
}
printf "%s%s %s (%s)\n", indent, glyph, name, size
}
}'
if [ "${ENTRIES}" -gt "${LIMIT}" ]; then
echo " ... $((ENTRIES - LIMIT)) further path(s) not listed; all of them are in the artifact."
fi