mirror of
https://relay.ngit.dev/npub15qydau2hjma6ngxkl2cyar74wzyjshvl65za5k5rl69264ar2exs5cyejr/ngit-grasp.git
synced 2026-10-05 15:08:24 +00:00
fix migration scripts for non-interactive SSH and bash 5.3
01-fetch-events.sh: nak buffers output when stdout is not a TTY, causing
it to hang silently in non-interactive SSH sessions. Wrap with 'script'
to provide a pseudo-TTY, then strip the injected carriage returns and
connection banner line from the output.
40-classify-actions.sh: bash 5.3 treats ${#assoc[@]} and array iteration
as unbound variable errors under set -u when arrays are empty. Replace
${#assoc[@]} with explicit counters and guard array iterations with
set +u/set -u.
This commit is contained in:
@@ -124,7 +124,14 @@ fetch_kind() {
|
|||||||
|
|
||||||
# Use --paginate to ensure we get all events, not just first page
|
# Use --paginate to ensure we get all events, not just first page
|
||||||
# nak outputs one event per line (JSONL format)
|
# nak outputs one event per line (JSONL format)
|
||||||
if ! nak req -k "$kind" --paginate "$relay" > "$output_file" 2>/dev/null; then
|
# NOTE: nak buffers output when stdout is not a TTY (e.g. non-interactive SSH).
|
||||||
|
# Use 'script' to provide a pseudo-TTY so nak flushes each line immediately.
|
||||||
|
# Then strip the nak connection banner ("connecting to ...") and carriage returns
|
||||||
|
# that 'script' injects into the output stream.
|
||||||
|
if ! script -q -c "nak req -k $kind --paginate $relay" /dev/null 2>/dev/null \
|
||||||
|
| tr -d '\r' \
|
||||||
|
| grep -v '^connecting to ' \
|
||||||
|
> "$output_file"; then
|
||||||
log_error "Failed to fetch $description from $relay"
|
log_error "Failed to fetch $description from $relay"
|
||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
|
|||||||
@@ -103,11 +103,13 @@ log_info "Building lookup tables..."
|
|||||||
|
|
||||||
# Build prod category lookup: repo|npub -> category
|
# Build prod category lookup: repo|npub -> category
|
||||||
declare -A PROD_CAT
|
declare -A PROD_CAT
|
||||||
|
PROD_CAT_COUNT=0
|
||||||
while IFS='|' read -r repo npub rest || [[ -n "$repo" ]]; do
|
while IFS='|' read -r repo npub rest || [[ -n "$repo" ]]; do
|
||||||
repo="${repo// /}" # Remove all spaces
|
repo="${repo// /}" # Remove all spaces
|
||||||
npub="${npub// /}" # Remove all spaces
|
npub="${npub// /}" # Remove all spaces
|
||||||
[[ -z "$repo" || -z "$npub" ]] && continue
|
[[ -z "$repo" || -z "$npub" ]] && continue
|
||||||
PROD_CAT["$repo|$npub"]="cat1"
|
PROD_CAT["$repo|$npub"]="cat1"
|
||||||
|
PROD_CAT_COUNT=$((PROD_CAT_COUNT + 1))
|
||||||
done < "$PROD_DIR/category1-complete-match.txt"
|
done < "$PROD_DIR/category1-complete-match.txt"
|
||||||
|
|
||||||
while IFS='|' read -r repo npub rest || [[ -n "$repo" ]]; do
|
while IFS='|' read -r repo npub rest || [[ -n "$repo" ]]; do
|
||||||
@@ -115,6 +117,7 @@ while IFS='|' read -r repo npub rest || [[ -n "$repo" ]]; do
|
|||||||
npub="${npub// /}"
|
npub="${npub// /}"
|
||||||
[[ -z "$repo" || -z "$npub" ]] && continue
|
[[ -z "$repo" || -z "$npub" ]] && continue
|
||||||
PROD_CAT["$repo|$npub"]="cat2"
|
PROD_CAT["$repo|$npub"]="cat2"
|
||||||
|
PROD_CAT_COUNT=$((PROD_CAT_COUNT + 1))
|
||||||
done < "$PROD_DIR/category2-empty-blank.txt"
|
done < "$PROD_DIR/category2-empty-blank.txt"
|
||||||
|
|
||||||
while IFS='|' read -r repo npub rest || [[ -n "$repo" ]]; do
|
while IFS='|' read -r repo npub rest || [[ -n "$repo" ]]; do
|
||||||
@@ -122,6 +125,7 @@ while IFS='|' read -r repo npub rest || [[ -n "$repo" ]]; do
|
|||||||
npub="${npub// /}"
|
npub="${npub// /}"
|
||||||
[[ -z "$repo" || -z "$npub" ]] && continue
|
[[ -z "$repo" || -z "$npub" ]] && continue
|
||||||
PROD_CAT["$repo|$npub"]="cat3"
|
PROD_CAT["$repo|$npub"]="cat3"
|
||||||
|
PROD_CAT_COUNT=$((PROD_CAT_COUNT + 1))
|
||||||
done < "$PROD_DIR/category3-partial-match.txt"
|
done < "$PROD_DIR/category3-partial-match.txt"
|
||||||
|
|
||||||
while IFS='|' read -r repo npub rest || [[ -n "$repo" ]]; do
|
while IFS='|' read -r repo npub rest || [[ -n "$repo" ]]; do
|
||||||
@@ -129,17 +133,20 @@ while IFS='|' read -r repo npub rest || [[ -n "$repo" ]]; do
|
|||||||
npub="${npub// /}"
|
npub="${npub// /}"
|
||||||
[[ -z "$repo" || -z "$npub" ]] && continue
|
[[ -z "$repo" || -z "$npub" ]] && continue
|
||||||
PROD_CAT["$repo|$npub"]="cat4"
|
PROD_CAT["$repo|$npub"]="cat4"
|
||||||
|
PROD_CAT_COUNT=$((PROD_CAT_COUNT + 1))
|
||||||
done < "$PROD_DIR/category4-no-match.txt"
|
done < "$PROD_DIR/category4-no-match.txt"
|
||||||
|
|
||||||
log_info "Loaded ${#PROD_CAT[@]} prod entries"
|
log_info "Loaded $PROD_CAT_COUNT prod entries"
|
||||||
|
|
||||||
# Build archive category lookup: repo|npub -> category
|
# Build archive category lookup: repo|npub -> category
|
||||||
declare -A ARCHIVE_CAT
|
declare -A ARCHIVE_CAT
|
||||||
|
ARCHIVE_CAT_COUNT=0
|
||||||
while IFS='|' read -r repo npub rest; do
|
while IFS='|' read -r repo npub rest; do
|
||||||
repo="${repo// /}"
|
repo="${repo// /}"
|
||||||
npub="${npub// /}"
|
npub="${npub// /}"
|
||||||
[[ -z "$repo" || -z "$npub" ]] && continue
|
[[ -z "$repo" || -z "$npub" ]] && continue
|
||||||
ARCHIVE_CAT["$repo|$npub"]="cat1"
|
ARCHIVE_CAT["$repo|$npub"]="cat1"
|
||||||
|
ARCHIVE_CAT_COUNT=$((ARCHIVE_CAT_COUNT + 1))
|
||||||
done < "$ARCHIVE_DIR/category1-complete-match.txt"
|
done < "$ARCHIVE_DIR/category1-complete-match.txt"
|
||||||
|
|
||||||
while IFS='|' read -r repo npub rest; do
|
while IFS='|' read -r repo npub rest; do
|
||||||
@@ -147,6 +154,7 @@ while IFS='|' read -r repo npub rest; do
|
|||||||
npub="${npub// /}"
|
npub="${npub// /}"
|
||||||
[[ -z "$repo" || -z "$npub" ]] && continue
|
[[ -z "$repo" || -z "$npub" ]] && continue
|
||||||
ARCHIVE_CAT["$repo|$npub"]="cat2"
|
ARCHIVE_CAT["$repo|$npub"]="cat2"
|
||||||
|
ARCHIVE_CAT_COUNT=$((ARCHIVE_CAT_COUNT + 1))
|
||||||
done < "$ARCHIVE_DIR/category2-empty-blank.txt"
|
done < "$ARCHIVE_DIR/category2-empty-blank.txt"
|
||||||
|
|
||||||
while IFS='|' read -r repo npub rest; do
|
while IFS='|' read -r repo npub rest; do
|
||||||
@@ -154,6 +162,7 @@ while IFS='|' read -r repo npub rest; do
|
|||||||
npub="${npub// /}"
|
npub="${npub// /}"
|
||||||
[[ -z "$repo" || -z "$npub" ]] && continue
|
[[ -z "$repo" || -z "$npub" ]] && continue
|
||||||
ARCHIVE_CAT["$repo|$npub"]="cat3"
|
ARCHIVE_CAT["$repo|$npub"]="cat3"
|
||||||
|
ARCHIVE_CAT_COUNT=$((ARCHIVE_CAT_COUNT + 1))
|
||||||
done < "$ARCHIVE_DIR/category3-partial-match.txt"
|
done < "$ARCHIVE_DIR/category3-partial-match.txt"
|
||||||
|
|
||||||
while IFS='|' read -r repo npub rest; do
|
while IFS='|' read -r repo npub rest; do
|
||||||
@@ -161,9 +170,10 @@ while IFS='|' read -r repo npub rest; do
|
|||||||
npub="${npub// /}"
|
npub="${npub// /}"
|
||||||
[[ -z "$repo" || -z "$npub" ]] && continue
|
[[ -z "$repo" || -z "$npub" ]] && continue
|
||||||
ARCHIVE_CAT["$repo|$npub"]="cat4"
|
ARCHIVE_CAT["$repo|$npub"]="cat4"
|
||||||
|
ARCHIVE_CAT_COUNT=$((ARCHIVE_CAT_COUNT + 1))
|
||||||
done < "$ARCHIVE_DIR/category4-no-match.txt"
|
done < "$ARCHIVE_DIR/category4-no-match.txt"
|
||||||
|
|
||||||
log_info "Loaded ${#ARCHIVE_CAT[@]} archive entries"
|
log_info "Loaded $ARCHIVE_CAT_COUNT archive entries"
|
||||||
|
|
||||||
# Build purgatory lookup: repo|npub -> 1 (if purgatory expired)
|
# Build purgatory lookup: repo|npub -> 1 (if purgatory expired)
|
||||||
declare -A PURGATORY
|
declare -A PURGATORY
|
||||||
@@ -237,7 +247,7 @@ process_deletions() {
|
|||||||
process_deletions "$PROD_DIR/raw/deletions.json"
|
process_deletions "$PROD_DIR/raw/deletions.json"
|
||||||
process_deletions "$ARCHIVE_DIR/raw/deletions.json"
|
process_deletions "$ARCHIVE_DIR/raw/deletions.json"
|
||||||
DELETED_COUNT=0
|
DELETED_COUNT=0
|
||||||
[[ ${#DELETED[@]} -gt 0 ]] && DELETED_COUNT=${#DELETED[@]}
|
for _k in "${!DELETED[@]}"; do DELETED_COUNT=$((DELETED_COUNT + 1)); done
|
||||||
log_info "Loaded $DELETED_COUNT deletion entries"
|
log_info "Loaded $DELETED_COUNT deletion entries"
|
||||||
|
|
||||||
# Build git ancestry lookup: repo|npub -> relationship (archive-ahead, prod-ahead, diverged, etc.)
|
# Build git ancestry lookup: repo|npub -> relationship (archive-ahead, prod-ahead, diverged, etc.)
|
||||||
@@ -266,17 +276,20 @@ fi
|
|||||||
log_info "Building unique repo list..."
|
log_info "Building unique repo list..."
|
||||||
|
|
||||||
declare -A ALL_REPOS
|
declare -A ALL_REPOS
|
||||||
|
ALL_REPOS_COUNT=0
|
||||||
|
set +u
|
||||||
for key in "${!PROD_CAT[@]}"; do
|
for key in "${!PROD_CAT[@]}"; do
|
||||||
ALL_REPOS["$key"]=1
|
[[ -z "${ALL_REPOS[$key]+x}" ]] && { ALL_REPOS["$key"]=1; ALL_REPOS_COUNT=$((ALL_REPOS_COUNT + 1)); }
|
||||||
done
|
done
|
||||||
for key in "${!ARCHIVE_CAT[@]}"; do
|
for key in "${!ARCHIVE_CAT[@]}"; do
|
||||||
ALL_REPOS["$key"]=1
|
[[ -z "${ALL_REPOS[$key]+x}" ]] && { ALL_REPOS["$key"]=1; ALL_REPOS_COUNT=$((ALL_REPOS_COUNT + 1)); }
|
||||||
done
|
done
|
||||||
for key in "${!PURGATORY[@]}"; do
|
for key in "${!PURGATORY[@]}"; do
|
||||||
ALL_REPOS["$key"]=1
|
[[ -z "${ALL_REPOS[$key]+x}" ]] && { ALL_REPOS["$key"]=1; ALL_REPOS_COUNT=$((ALL_REPOS_COUNT + 1)); }
|
||||||
done
|
done
|
||||||
|
set -u
|
||||||
|
|
||||||
log_info "Total unique repos: ${#ALL_REPOS[@]}"
|
log_info "Total unique repos: $ALL_REPOS_COUNT"
|
||||||
|
|
||||||
# ============================================================================
|
# ============================================================================
|
||||||
# Phase 3: Classify each repo according to revised decision tree
|
# Phase 3: Classify each repo according to revised decision tree
|
||||||
@@ -351,6 +364,7 @@ cat_to_status() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
LOOP_COUNT=0
|
LOOP_COUNT=0
|
||||||
|
set +u
|
||||||
for key in "${!ALL_REPOS[@]}"; do
|
for key in "${!ALL_REPOS[@]}"; do
|
||||||
LOOP_COUNT=$((LOOP_COUNT + 1))
|
LOOP_COUNT=$((LOOP_COUNT + 1))
|
||||||
[[ $((LOOP_COUNT % 100)) -eq 0 ]] && log_info "Processed $LOOP_COUNT repos..."
|
[[ $((LOOP_COUNT % 100)) -eq 0 ]] && log_info "Processed $LOOP_COUNT repos..."
|
||||||
@@ -473,6 +487,7 @@ for key in "${!ALL_REPOS[@]}"; do
|
|||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
done
|
done
|
||||||
|
set -u
|
||||||
|
|
||||||
# ============================================================================
|
# ============================================================================
|
||||||
# Phase 4: Write output files
|
# Phase 4: Write output files
|
||||||
@@ -488,9 +503,11 @@ TIMESTAMP=$(date -u +"%Y-%m-%dT%H:%M:%S+00:00")
|
|||||||
echo "# Generated: $TIMESTAMP"
|
echo "# Generated: $TIMESTAMP"
|
||||||
echo "# Format: repo | npub | prod_status | archive_status | context | reason"
|
echo "# Format: repo | npub | prod_status | archive_status | context | reason"
|
||||||
echo "#"
|
echo "#"
|
||||||
|
set +u
|
||||||
for line in "${READY_LINES[@]}"; do
|
for line in "${READY_LINES[@]}"; do
|
||||||
echo "$line"
|
echo "$line"
|
||||||
done
|
done
|
||||||
|
set -u
|
||||||
} > "$READY_FILE"
|
} > "$READY_FILE"
|
||||||
|
|
||||||
# Write needs-resync.txt
|
# Write needs-resync.txt
|
||||||
@@ -503,9 +520,11 @@ TIMESTAMP=$(date -u +"%Y-%m-%dT%H:%M:%S+00:00")
|
|||||||
echo "# purgatory-expired = archive tried to sync but failed (30min timeout)"
|
echo "# purgatory-expired = archive tried to sync but failed (30min timeout)"
|
||||||
echo "# none = archive never tried or announcement missing"
|
echo "# none = archive never tried or announcement missing"
|
||||||
echo "#"
|
echo "#"
|
||||||
|
set +u
|
||||||
for line in "${RESYNC_LINES[@]}"; do
|
for line in "${RESYNC_LINES[@]}"; do
|
||||||
echo "$line"
|
echo "$line"
|
||||||
done
|
done
|
||||||
|
set -u
|
||||||
} > "$RESYNC_FILE"
|
} > "$RESYNC_FILE"
|
||||||
|
|
||||||
# Write manual-review.txt
|
# Write manual-review.txt
|
||||||
@@ -514,9 +533,11 @@ TIMESTAMP=$(date -u +"%Y-%m-%dT%H:%M:%S+00:00")
|
|||||||
echo "# Generated: $TIMESTAMP"
|
echo "# Generated: $TIMESTAMP"
|
||||||
echo "# Format: repo | npub | prod_status | archive_status | context | reason"
|
echo "# Format: repo | npub | prod_status | archive_status | context | reason"
|
||||||
echo "#"
|
echo "#"
|
||||||
|
set +u
|
||||||
for line in "${REVIEW_LINES[@]}"; do
|
for line in "${REVIEW_LINES[@]}"; do
|
||||||
echo "$line"
|
echo "$line"
|
||||||
done
|
done
|
||||||
|
set -u
|
||||||
} > "$REVIEW_FILE"
|
} > "$REVIEW_FILE"
|
||||||
|
|
||||||
# ============================================================================
|
# ============================================================================
|
||||||
@@ -525,9 +546,11 @@ TIMESTAMP=$(date -u +"%Y-%m-%dT%H:%M:%S+00:00")
|
|||||||
|
|
||||||
log_info "Generating summary..."
|
log_info "Generating summary..."
|
||||||
|
|
||||||
|
set +u
|
||||||
TOTAL_READY="${#READY_LINES[@]}"
|
TOTAL_READY="${#READY_LINES[@]}"
|
||||||
TOTAL_RESYNC="${#RESYNC_LINES[@]}"
|
TOTAL_RESYNC="${#RESYNC_LINES[@]}"
|
||||||
TOTAL_REVIEW="${#REVIEW_LINES[@]}"
|
TOTAL_REVIEW="${#REVIEW_LINES[@]}"
|
||||||
|
set -u
|
||||||
TOTAL=$((TOTAL_READY + TOTAL_RESYNC + TOTAL_REVIEW))
|
TOTAL=$((TOTAL_READY + TOTAL_RESYNC + TOTAL_REVIEW))
|
||||||
|
|
||||||
# Calculate percentages
|
# Calculate percentages
|
||||||
|
|||||||
Reference in New Issue
Block a user