commit ec1ef7f88973b9c5d8b7be202c12ddc7675224c2
parent 5dbc5170b3ac9d06f53d4326b1c3f646c9cf8fdc
Author: gracefu <81774659+gracefuu@users.noreply.github.com>
Date: Sat, 19 Apr 2025 23:05:02 +0800
Use stagit as git repo frontend
Diffstat:
4 files changed, 108 insertions(+), 29 deletions(-)
diff --git a/.gitignore b/.gitignore
@@ -1,3 +1,4 @@
+git/
public/
__pycache__/
.makedb
diff --git a/.gitmodules b/.gitmodules
@@ -0,0 +1,3 @@
+[submodule "stagit"]
+ path = stagit
+ url = git://git.codemadness.org/stagit
diff --git a/make.py b/make.py
@@ -51,9 +51,11 @@ import collections
import functools
import hashlib
import inspect
+import os
import pickle
import subprocess
import sys
+import threading
import traceback
from typing import (
@@ -610,26 +612,92 @@ import json
async def main():
- sem = asyncio.Semaphore(50)
-
@rule_no_cache
- def rebuild(fetch: Fetch):
+ def build_git_repo(
+ fetch: Fetch,
+ stagit_path: str,
+ source_git_path: str,
+ output_git_path: str,
+ output_url: str,
+ description: str,
+ ):
return shell(
- """
- find public -mindepth 1 -maxdepth 1 -path 'public/git' -prune -o -exec rm -r {} +
- zine release
- [ -d public/git/blog.grace.moe ] || git init --bare public/git/blog.grace.moe
- git push --mirror --force public/git/blog.grace.moe
- git -C public/git/blog.grace.moe gc --no-detach --aggressive
- git -C public/git/blog.grace.moe update-server-info
- [ -d public/git/pymake ] || git init --bare public/git/pymake
- git -C ~/Documents/src/pymake push --mirror --force $(realpath public/git/pymake)
- git -C public/git/pymake gc --no-detach --aggressive
- git -C public/git/pymake update-server-info
+ f"""
+ SRC_PATH="$(realpath {source_git_path})"
+
+ [ -d {output_git_path} ] || git init --bare {output_git_path}
+ GIT_PATH="$(realpath {output_git_path})"
+
+ mkdir -p public/{output_url}
+ PUBLIC_PATH="$(realpath public/{output_url})"
+
+ STAGIT_PATH="$(realpath {stagit_path})"
+
+ rm -rf "$GIT_PATH"/hooks
+
+ git -C "$SRC_PATH" push --no-recurse-submodules --mirror --force "$GIT_PATH"
+ # HEAD is not updated by --mirror, because HEAD is not a ref.
+ # Update it by hand
+ cp "$(git -C "$SRC_PATH" rev-parse --path-format=absolute --git-path HEAD)" "$GIT_PATH"/HEAD
+
+ git -C "$GIT_PATH" gc --no-detach --aggressive
+ git -C "$GIT_PATH" update-server-info
+
+ echo '{description}' > "$GIT_PATH"/description
+ echo 'https://blog.grace.moe/{output_url}' > "$GIT_PATH"/url
+
+ cp -a "$GIT_PATH" -T "$PUBLIC_PATH"
+
+ ( cd "$PUBLIC_PATH" &&
+ "$STAGIT_PATH" \
+ -u https://blog.grace.moe/{output_url} \
+ "$GIT_PATH" &&
+ echo '<meta http-equiv="refresh" content="0; url=log.html" />' > index.html
+ )
""",
echo=EchoAll,
)
+ @rule_no_cache
+ async def rebuild(fetch: Fetch):
+ await shell(
+ """
+ rm -rf public
+ """
+ )
+ await shell("zine release", echo=EchoAll)
+ await fetch(
+ build_git_repo(
+ "stagit/stagit",
+ ".",
+ "git/blog.grace.moe",
+ "git/blog.grace.moe",
+ "Source for the blog blog.grace.moe",
+ )
+ )
+ await fetch(
+ build_git_repo(
+ "stagit/stagit",
+ "~/Documents/src/pymake",
+ "git/pymake",
+ "git/pymake",
+ "A build system based on Build Systems à la Carte",
+ )
+ )
+ await fetch(
+ build_git_repo(
+ "stagit/stagit",
+ ".git/modules/stagit",
+ "git/stagit",
+ "git/stagit",
+ "My personal fork of stagit https://codemadness.org/stagit.html",
+ )
+ )
+ await shell(
+ "cd public/git && ../../stagit/stagit-index blog.grace.moe pymake stagit > index.html",
+ echo=EchoAll,
+ )
+
STORAGENAME = "blog-grace-moe"
STORAGEPASSWORD = (
await shell("secret-tool lookup owner blog-grace-moe.b-cdn.net")
@@ -644,9 +712,20 @@ async def main():
PURGEURL = f"https://api.bunny.net/pullzone/{PULLZONEID}/purgeCache"
APICMD = f"curl -H 'AccessKey: {APIPASSWORD}' -s"
+ def hash_file(path):
+ with open(path, "rb") as f:
+ # print("+ hashing", path)
+ h = hashlib.sha256()
+ for chunk in f:
+ h.update(chunk)
+ # print("- hashing", path)
+ return h.hexdigest().upper()
+
+ bunny_sem = asyncio.Semaphore(50)
+
@rule_no_cache
async def contents(fetch: Fetch, path: str):
- async with sem:
+ async with bunny_sem:
print("+++ download", path)
path_json = await shell(f"{STORAGECMD} '{STORAGEURL}/{path}/'")
print("--- download", path)
@@ -654,16 +733,16 @@ async def main():
@rule_no_cache
async def cleanfile(fetch: Fetch, path: str):
- if 0 != (await shell(f"[ -f '{LOCALPATH}/{path}' ]")).returncode:
- async with sem:
+ if not os.path.isfile(f"{LOCALPATH}/{path}"):
+ async with bunny_sem:
print("+++ cleanfile", path)
await shell(f"{STORAGECMD} -XDELETE '{STORAGEURL}/{path}'")
print("--- cleanfile", path)
@rule_no_cache
async def cleandir(fetch: Fetch, path: str):
- if 0 != (await shell(f"[ -d '{LOCALPATH}/{path}' ]")).returncode:
- async with sem:
+ if not os.path.isdir(f"{LOCALPATH}/{path}"):
+ async with bunny_sem:
print("+++ cleandir", path)
await shell(f"{STORAGECMD} -XDELETE '{STORAGEURL}/{path}/'")
print("--- cleandir", path)
@@ -679,17 +758,11 @@ async def main():
else fetch(cleanfile(path + "/" + ent["ObjectName"]))
)
for ent in path_contents
+ if isinstance(ent, dict)
)
)
print("- clean", path)
- def hash_file(path):
- with open(path, "rb") as f:
- h = hashlib.sha256()
- for chunk in f:
- h.update(chunk)
- return h.hexdigest().upper()
-
@rule_no_cache
async def upload(fetch: Fetch, path: str):
path_contents = await fetch(contents(path[: path.rfind("/")]))
@@ -710,7 +783,7 @@ async def main():
our_checksum = await run_in_executor(hash_file, f"{LOCALPATH}/{path}")
if bunny_checksum != our_checksum:
- async with sem:
+ async with bunny_sem:
print("+++ uploading", path)
await shell(
f"{STORAGECMD} -T'{LOCALPATH}/{path}' '{STORAGEURL}/{path}'"
@@ -720,8 +793,9 @@ async def main():
@rule_no_cache
async def purge(fetch: Fetch):
- await shell(f"{APICMD} -XPOST '{PURGEURL}'")
- print("Purged.")
+ async with bunny_sem:
+ await shell(f"{APICMD} -XPOST '{PURGEURL}'")
+ print("Purged.")
with Build(".makedb") as build:
await build(rebuild())
diff --git a/stagit b/stagit
@@ -0,0 +1 @@
+Subproject commit 24aaa757627f678f20fa1dd6ca676d5598f1d841