-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathfix-local-remotes.sh
More file actions
executable file
·141 lines (121 loc) · 4.07 KB
/
fix-local-remotes.sh
File metadata and controls
executable file
·141 lines (121 loc) · 4.07 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
#!/usr/bin/env bash
# fix-local-remotes.sh
# Usage:
# fix-local-remotes.sh <local-clone-root> [--execute] [--debug]
#
# Notes:
# - Bash 3.2 compatible (macOS default).
# - Reads TSV mapping from ~/.fork_transfer_map.tsv with lines "old_full<TAB>new_full".
# - Assumes local clone directory name == repo name (e.g., ~/code/<reponame>).
# - Dry-run by default. Pass --execute to actually change remotes.
# - --debug enables xtrace and logs to ~/fix-remotes-debug.log (while printing to console).
set -euo pipefail
LOCAL_ROOT="${1:-.}"
# Parse flags (order-insensitive for the 2nd/3rd arg positions)
EXECUTE=false
DEBUG=false
shift_ct=0
for arg in "${@:2}"; do
case "$arg" in
--execute) EXECUTE=true ;;
--debug) DEBUG=true ;;
*) ;; # ignore unknowns beyond position 1 to stay permissive
esac
shift_ct=$((shift_ct+1))
done
# (we don't shift positionals further; LOCAL_ROOT already captured)
# Debug / logging
if $DEBUG; then
set -x
DEBUG_LOG="${HOME}/fix-remotes-debug.log"
# tee preserves console output while capturing to file (stdout & stderr)
exec > >(tee -a "$DEBUG_LOG") 2> >(tee -a "$DEBUG_LOG" >&2)
fi
MAPPING_FILE="${HOME}/.fork_transfer_map.tsv"
log() { printf '[%s] %s\n' "$(date -u +'%Y-%m-%dT%H:%M:%SZ')" "$*"; }
if [ ! -f "$MAPPING_FILE" ]; then
log "Error: mapping file not found: $MAPPING_FILE"
exit 1
fi
UPDATED=0
ADDED=0
SKIPPED_ALREADY=0
SKIPPED_NOTGIT=0
SKIPPED_MALFORMED=0
TOTAL=0
# Helper: compute a new URL preserving scheme where possible.
# Args: current_url (may be empty), newowner, reponame -> echoes newurl
compute_new_url() {
cur="$1"; owner="$2"; repo="$3"
if printf '%s' "$cur" | grep -q '^git@github.com:'; then
printf 'git@github.com:%s/%s.git' "$owner" "$repo"
else
printf 'https://github.com/%s/%s.git' "$owner" "$repo"
fi
}
# Process each mapping line: old_full<TAB>new_full
# Allow comments and blank lines.
while IFS= read -r line; do
# Normalize and skip comments/blank
line_trim="$(printf '%s' "$line" | sed 's/^[[:space:]]*//; s/[[:space:]]*$//')"
[ -z "$line_trim" ] && continue
case "$line_trim" in \#*) continue ;; esac
old_full="$(printf '%s' "$line_trim" | awk -F'\t' 'NF>=1{print $1}')"
new_full="$(printf '%s' "$line_trim" | awk -F'\t' 'NF>=2{print $2}')"
if [ -z "${old_full:-}" ] || [ -z "${new_full:-}" ]; then
SKIPPED_MALFORMED=$((SKIPPED_MALFORMED+1))
continue
fi
TOTAL=$((TOTAL+1))
reponame="${old_full##*/}"
newowner="${new_full%%/*}"
localdir="${LOCAL_ROOT%/}/${reponame}"
if [ ! -d "$localdir/.git" ]; then
log "SKIP: not a git repo: $localdir"
SKIPPED_NOTGIT=$((SKIPPED_NOTGIT+1))
continue
fi
(
cd "$localdir"
# Current origin (may be empty if origin not defined)
cururl="$(git remote get-url origin 2>/dev/null || true)"
log "Repo: $localdir"
log " current origin: ${cururl:-<none>}"
# If already correct, skip
case "$cururl" in
*"/${newowner}/${reponame}.git"|*"/${newowner}/${reponame}")
log " SKIP: already correct → ${new_full}"
SKIPPED_ALREADY=$((SKIPPED_ALREADY+1))
exit 0
;;
esac
# Build new URL (preserve SSH vs HTTPS when possible)
newurl="$(compute_new_url "$cururl" "$newowner" "$reponame")"
if $EXECUTE; then
if git remote | grep -Fxq origin; then
if git remote set-url origin "$newurl"; then
UPDATED=$((UPDATED+1))
log " updated origin → $newurl"
else
log " ERROR: set-url failed: $newurl"
fi
else
if git remote add origin "$newurl"; then
ADDED=$((ADDED+1))
log " added origin → $newurl"
else
log " ERROR: add origin failed: $newurl"
fi
fi
else
log " [dry-run] would set origin → $newurl"
fi
)
done < "$MAPPING_FILE"
log "Done (execute=$EXECUTE). Summary:"
log " Total mappings processed: $TOTAL"
log " Updated origins: $UPDATED"
log " Added origins: $ADDED"
log " Skipped already-correct: $SKIPPED_ALREADY"
log " Skipped not-a-git-repo: $SKIPPED_NOTGIT"
log " Skipped malformed lines: $SKIPPED_MALFORMED"