diff options
| author | DanConwayDev <DanConwayDev@protonmail.com> | 2026-02-03 14:41:46 +0000 |
|---|---|---|
| committer | DanConwayDev <DanConwayDev@protonmail.com> | 2026-02-03 14:46:09 +0000 |
| commit | 92a9a3bfe0bc522e8ae411991a366a3a6310d525 (patch) | |
| tree | 9fc5045a9df0ef56cc8ad37afaef09fad37d95ed /docs/how-to/migration-scripts/20-categorize.sh | |
| parent | f148b3a0e4b032c0acf835cda6d2935e19b9f67e (diff) | |
docs: archive relay.ngit.dev migration materials for reference
Move migration guide and scripts to docs/archive/2026-01-relay-ngit-dev-migration/
with clear warnings that these are reference-only materials from a specific
migration context, not general-purpose tools.
These materials document the relay.ngit.dev migration from ngit-relay to
ngit-grasp in January 2026. The scripts were developed iteratively during
the migration and are specific to that context. They are preserved for:
- Historical reference
- Context for production fixes in this branch
- Inspiration for future migrations (not direct reuse)
The migration uncovered critical bugs now fixed in this branch:
- Git protocol error handling
- Naughty list false positives
- Purgatory event tracking
- Sync startup issues
- Configuration management
Diffstat (limited to 'docs/how-to/migration-scripts/20-categorize.sh')
| -rwxr-xr-x | docs/how-to/migration-scripts/20-categorize.sh | 212 |
1 files changed, 0 insertions, 212 deletions
diff --git a/docs/how-to/migration-scripts/20-categorize.sh b/docs/how-to/migration-scripts/20-categorize.sh deleted file mode 100755 index b38dc00..0000000 --- a/docs/how-to/migration-scripts/20-categorize.sh +++ /dev/null | |||
| @@ -1,212 +0,0 @@ | |||
| 1 | #!/usr/bin/env bash | ||
| 2 | # | ||
| 3 | # 20-categorize.sh - Categorize git sync status into 4 categories | ||
| 4 | # | ||
| 5 | # PHASE 3a of the GRASP relay to ngit-grasp migration analysis pipeline. | ||
| 6 | # Takes git-sync-status.tsv from Phase 2 and categorizes into 4 files. | ||
| 7 | # | ||
| 8 | # USAGE: | ||
| 9 | # ./20-categorize.sh <git-sync-status.tsv> <output-dir> | ||
| 10 | # | ||
| 11 | # EXAMPLES: | ||
| 12 | # ./20-categorize.sh output/prod/git-sync-status.tsv output/prod | ||
| 13 | # ./20-categorize.sh output/archive/git-sync-status.tsv output/archive | ||
| 14 | # | ||
| 15 | # INPUT FORMAT (git-sync-status.tsv): | ||
| 16 | # Tab-separated values with columns: | ||
| 17 | # repo<TAB>npub<TAB>state_refs<TAB>git_refs<TAB>matches<TAB>reason | ||
| 18 | # | ||
| 19 | # Where reason is optional and can be: no_git_dir, empty_refs, no_state_refs | ||
| 20 | # | ||
| 21 | # OUTPUT: | ||
| 22 | # <output-dir>/category1-complete-match.txt - All refs match perfectly | ||
| 23 | # <output-dir>/category2-empty-blank.txt - No git data available | ||
| 24 | # <output-dir>/category3-partial-match.txt - Some refs match | ||
| 25 | # <output-dir>/category4-no-match.txt - Git exists but refs don't match | ||
| 26 | # | ||
| 27 | # OUTPUT FORMAT: | ||
| 28 | # repo | npub | state_refs=N | git_refs=N | matches=N [| reason=X] | ||
| 29 | # | ||
| 30 | # CATEGORIES: | ||
| 31 | # 1. Complete Match: state_refs == git_refs == matches (all > 0) | ||
| 32 | # 2. Empty/Blank: git_refs == 0 OR reason in (no_git_dir, empty_refs, no_state_refs) | ||
| 33 | # 3. Partial Match: matches > 0 AND matches < state_refs | ||
| 34 | # 4. No Match: git_refs > 0 AND matches == 0 | ||
| 35 | # | ||
| 36 | # PREREQUISITES: | ||
| 37 | # - awk (standard Unix tool) | ||
| 38 | # | ||
| 39 | # RUNTIME: < 1 second (local processing only) | ||
| 40 | # | ||
| 41 | # SEE ALSO: | ||
| 42 | # docs/how-to/migrate-to-ngit-grasp.md - Full migration guide | ||
| 43 | # 10-check-git-sync.sh - Phase 2 script that produces input for this script | ||
| 44 | # | ||
| 45 | |||
| 46 | set -euo pipefail | ||
| 47 | |||
| 48 | # Colors for output (disabled if not a terminal) | ||
| 49 | if [[ -t 1 ]]; then | ||
| 50 | RED='\033[0;31m' | ||
| 51 | GREEN='\033[0;32m' | ||
| 52 | YELLOW='\033[0;33m' | ||
| 53 | BLUE='\033[0;34m' | ||
| 54 | NC='\033[0m' | ||
| 55 | else | ||
| 56 | RED='' | ||
| 57 | GREEN='' | ||
| 58 | YELLOW='' | ||
| 59 | BLUE='' | ||
| 60 | NC='' | ||
| 61 | fi | ||
| 62 | |||
| 63 | log_info() { | ||
| 64 | echo -e "${BLUE}[INFO]${NC} $*" >&2 | ||
| 65 | } | ||
| 66 | |||
| 67 | log_success() { | ||
| 68 | echo -e "${GREEN}[OK]${NC} $*" >&2 | ||
| 69 | } | ||
| 70 | |||
| 71 | log_warn() { | ||
| 72 | echo -e "${YELLOW}[WARN]${NC} $*" >&2 | ||
| 73 | } | ||
| 74 | |||
| 75 | log_error() { | ||
| 76 | echo -e "${RED}[ERROR]${NC} $*" >&2 | ||
| 77 | } | ||
| 78 | |||
| 79 | usage() { | ||
| 80 | echo "Usage: $0 <git-sync-status.tsv> <output-dir>" | ||
| 81 | echo "" | ||
| 82 | echo "Arguments:" | ||
| 83 | echo " git-sync-status.tsv TSV file from Phase 2 (10-check-git-sync.sh)" | ||
| 84 | echo " output-dir Directory to store categorized output" | ||
| 85 | echo "" | ||
| 86 | echo "Examples:" | ||
| 87 | echo " $0 output/prod/git-sync-status.tsv output/prod" | ||
| 88 | echo " $0 output/archive/git-sync-status.tsv output/archive" | ||
| 89 | echo "" | ||
| 90 | echo "Input format (TSV):" | ||
| 91 | echo " repo<TAB>npub<TAB>state_refs<TAB>git_refs<TAB>matches<TAB>reason" | ||
| 92 | echo "" | ||
| 93 | echo "Output files:" | ||
| 94 | echo " category1-complete-match.txt - All refs match" | ||
| 95 | echo " category2-empty-blank.txt - No git data" | ||
| 96 | echo " category3-partial-match.txt - Some refs match" | ||
| 97 | echo " category4-no-match.txt - Git exists, refs don't match" | ||
| 98 | exit 1 | ||
| 99 | } | ||
| 100 | |||
| 101 | # Main | ||
| 102 | main() { | ||
| 103 | if [[ $# -ne 2 ]]; then | ||
| 104 | usage | ||
| 105 | fi | ||
| 106 | |||
| 107 | local input_file="$1" | ||
| 108 | local output_dir="$2" | ||
| 109 | |||
| 110 | # Validate input file | ||
| 111 | if [[ ! -f "$input_file" ]]; then | ||
| 112 | log_error "Input file not found: $input_file" | ||
| 113 | exit 1 | ||
| 114 | fi | ||
| 115 | |||
| 116 | log_info "Categorizing git sync status" | ||
| 117 | log_info "Input: $input_file" | ||
| 118 | log_info "Output: $output_dir" | ||
| 119 | |||
| 120 | # Create output directory | ||
| 121 | mkdir -p "$output_dir" | ||
| 122 | |||
| 123 | # Output files | ||
| 124 | local cat1="$output_dir/category1-complete-match.txt" | ||
| 125 | local cat2="$output_dir/category2-empty-blank.txt" | ||
| 126 | local cat3="$output_dir/category3-partial-match.txt" | ||
| 127 | local cat4="$output_dir/category4-no-match.txt" | ||
| 128 | |||
| 129 | # Clear previous results | ||
| 130 | > "$cat1" | ||
| 131 | > "$cat2" | ||
| 132 | > "$cat3" | ||
| 133 | > "$cat4" | ||
| 134 | |||
| 135 | # Process input file with awk | ||
| 136 | # Input: repo<TAB>npub<TAB>state_refs<TAB>git_refs<TAB>matches<TAB>reason | ||
| 137 | awk -F'\t' -v cat1="$cat1" -v cat2="$cat2" -v cat3="$cat3" -v cat4="$cat4" ' | ||
| 138 | BEGIN { | ||
| 139 | count1 = 0; count2 = 0; count3 = 0; count4 = 0 | ||
| 140 | } | ||
| 141 | NR == 1 && /^repo/ { next } # Skip header if present | ||
| 142 | NF >= 5 { | ||
| 143 | repo = $1 | ||
| 144 | npub = $2 | ||
| 145 | state_refs = int($3) | ||
| 146 | git_refs = int($4) | ||
| 147 | matches = int($5) | ||
| 148 | reason = (NF >= 6) ? $6 : "" | ||
| 149 | |||
| 150 | # Format output line | ||
| 151 | if (reason != "") { | ||
| 152 | line = repo " | " npub " | state_refs=" state_refs " | git_refs=" git_refs " | matches=" matches " | reason=" reason | ||
| 153 | } else { | ||
| 154 | line = repo " | " npub " | state_refs=" state_refs " | git_refs=" git_refs " | matches=" matches | ||
| 155 | } | ||
| 156 | |||
| 157 | # Categorize | ||
| 158 | if (reason == "no_git_dir" || reason == "empty_refs" || reason == "no_state_refs" || git_refs == 0) { | ||
| 159 | # Category 2: Empty/Blank | ||
| 160 | print line >> cat2 | ||
| 161 | count2++ | ||
| 162 | } else if (state_refs > 0 && state_refs == git_refs && matches == state_refs) { | ||
| 163 | # Category 1: Complete Match | ||
| 164 | print line >> cat1 | ||
| 165 | count1++ | ||
| 166 | } else if (matches > 0 && matches < state_refs) { | ||
| 167 | # Category 3: Partial Match | ||
| 168 | print line >> cat3 | ||
| 169 | count3++ | ||
| 170 | } else if (git_refs > 0 && matches == 0) { | ||
| 171 | # Category 4: No Match | ||
| 172 | print line >> cat4 | ||
| 173 | count4++ | ||
| 174 | } else if (matches > 0) { | ||
| 175 | # Edge case: matches > 0 but does not fit other categories | ||
| 176 | # This can happen when git_refs > state_refs but all state refs match | ||
| 177 | # Treat as partial match | ||
| 178 | print line >> cat3 | ||
| 179 | count3++ | ||
| 180 | } else { | ||
| 181 | # Fallback: treat as category 2 (empty/blank) | ||
| 182 | print line >> cat2 | ||
| 183 | count2++ | ||
| 184 | } | ||
| 185 | } | ||
| 186 | END { | ||
| 187 | total = count1 + count2 + count3 + count4 | ||
| 188 | print "COUNTS:" count1 ":" count2 ":" count3 ":" count4 ":" total | ||
| 189 | } | ||
| 190 | ' "$input_file" 2>&1 | while IFS= read -r line; do | ||
| 191 | if [[ "$line" =~ ^COUNTS: ]]; then | ||
| 192 | # Parse counts from awk output | ||
| 193 | IFS=':' read -r _ c1 c2 c3 c4 total <<< "$line" | ||
| 194 | |||
| 195 | echo "" | ||
| 196 | log_info "=== Categorization Summary ===" | ||
| 197 | log_info "Total entries: $total" | ||
| 198 | log_success "Category 1 (Complete Match): $c1" | ||
| 199 | log_warn "Category 2 (Empty/Blank): $c2" | ||
| 200 | log_warn "Category 3 (Partial Match): $c3" | ||
| 201 | log_error "Category 4 (No Match): $c4" | ||
| 202 | echo "" | ||
| 203 | log_info "Output files:" | ||
| 204 | echo " $cat1" | ||
| 205 | echo " $cat2" | ||
| 206 | echo " $cat3" | ||
| 207 | echo " $cat4" | ||
| 208 | fi | ||
| 209 | done | ||
| 210 | } | ||
| 211 | |||
| 212 | main "$@" | ||