splux-site · log · files · refs · tags · releases · people · languages · GitHub · commit
8e8042c
Ship a static git browser and drop the Forgejo backend.
Parents
Stat
README.md | 26 +- forgejo/README.md | 38 -- forgejo/app.ini.example | 80 ---- forgejo/import-repos.sh | 62 --- forgejo/install.sh | 153 ------- forgejo/templates/custom/extra_links.tmpl | 4 - forgejo/templates/custom/extra_links_footer.tmpl | 3 - forgejo/theme-splux.css | 306 ------------- site/assets/git.js | 99 +--- site/assets/live.js | 14 +- site/assets/style.css | 85 ++-- site/docs/first-boot/index.html | 1 + site/docs/images/index.html | 2 +- site/docs/index.html | 12 +- site/docs/sps/index.html | 12 +- site/download/index.html | 2 +- site/git/index.html | 21 +- site/index.html | 20 +- site/install/index.html | 10 +- site/packages/index.html | 2 +- site/source/index.html | 18 +- tools/build-git.sh | 559 +++++++++++++++++++++++ tools/build-site.sh | 65 ++- tools/collect-news.sh | 14 +- tools/git.awk | 132 ++++++ tools/packages.awk | 8 +- tools/subst.awk | 2 +- 27 files changed, 890 insertions(+), 860 deletions(-)
Diff
diff --git a/README.md b/README.md
index c9a0a6b..2d42303 100644
--- a/README.md
+++ b/README.md
@@ -77,18 +77,22 @@ repository there. `SITE_PREFIX` stays empty so links are rooted at `/`.
## Git
-`/git/` is the public forge page. Canonical clone, accounts, and pull
-requests belong on Splux Git (`https://git.splux.robertflexx.dev`).
-GitHub stays a mirror of git history. Live ISO files stay on GitHub
-Releases. The Forgejo theme and installer live in `forgejo/`.
-
-Point a DNS A or AAAA record for `git.splux` at the host that runs
-Forgejo, then put TLS in front of port 3000 (or a tunnel) and set
-`ROOT_URL` to `https://git.splux.robertflexx.dev/`. Until that name
-answers, the handbook page still lists GitHub clone URLs.
+`/git/` is a static browse of SPS, sps-core, sps-extra, and this
+repository. The Pages workflow clones those trees and writes commit,
+file, and language pages. There is no git server, no accounts, and no
+pull requests. Clone from GitHub:
```sh
-sh forgejo/install.sh
-sh forgejo/import-repos.sh
+git clone https://github.com/RobertFlexx/SPS.git
+git clone https://github.com/RobertFlexx/sps-core.git
+git clone https://github.com/RobertFlexx/sps-extra.git
+git clone https://github.com/RobertFlexx/splux-site.git
```
+News commit links point at `/git/<repo>/commit/<sha>/`. Recipe pages
+link into `/git/sps-core/` and `/git/sps-extra/`. Live ISO files stay
+on GitHub Releases.
+
+`git.splux.robertflexx.dev` is not a separate service. GitHub Pages
+allows one custom domain on this repository (`splux.robertflexx.dev`).
+The git UI is `https://splux.robertflexx.dev/git/`.
diff --git a/forgejo/README.md b/forgejo/README.md
deleted file mode 100644
index 7ad5031..0000000
--- a/forgejo/README.md
+++ /dev/null
@@ -1,38 +0,0 @@
-# Splux Git
-
-Forgejo themed to match the Splux handbook. The live process lives in
-`/home/robert/splux-forge`. This directory is the theme, example config,
-and installer that the static site ships so the forge and the handbook
-stay in the same style.
-
-```sh
-sh forgejo/install.sh
-```
-
-That copies the theme, writes `app.ini`, and starts port 3000. Create
-the admin account yourself (the installer does not set a password):
-
-```sh
-/home/robert/splux-forge/bin/forgejo -w /home/robert/splux-forge/data \
- admin user create --username RobertFlexx --email ohf9ck@gmail.com \
- --admin --password 'your-password'
-```
-
-Then import SPS, sps-core, sps-extra, and splux-site from GitHub:
-
-```sh
-sh forgejo/import-repos.sh
-```
-
-The public handbook page is `/git/`. That page is official on the
-site. Clone URLs on the internet still use GitHub until
-`git.splux.robertflexx.dev` has DNS and TLS in front of this process.
-LAN:
-
-```sh
-git clone http://10.0.0.139:3000/RobertFlexx/SPS.git
-git clone ssh://robert@10.0.0.139:2222/RobertFlexx/SPS.git
-```
-
-Push mirrors to GitHub are a per-repo setting in the forge UI. They
-need a GitHub PAT. Issues and pull requests stay on Splux Git.
diff --git a/forgejo/app.ini.example b/forgejo/app.ini.example
deleted file mode 100644
index 1b1e694..0000000
--- a/forgejo/app.ini.example
+++ /dev/null
@@ -1,80 +0,0 @@
-; Splux Git. Copy to $FORGEJO_WORK_DIR/custom/conf/app.ini
-; forgejo/install.sh writes the live file with secrets filled in.
-
-APP_NAME = Splux Git
-APP_SLOGAN = official repositories for Splux and SPS
-RUN_USER = robert
-WORK_PATH = /home/robert/splux-forge/data
-
-[server]
-APP_DATA_PATH = /home/robert/splux-forge/data
-PROTOCOL = http
-DOMAIN = 10.0.0.139
-HTTP_ADDR = 0.0.0.0
-HTTP_PORT = 3000
-; Change ROOT_URL to https://git.splux.robertflexx.dev/ after DNS and TLS exist.
-ROOT_URL = http://10.0.0.139:3000/
-DISABLE_SSH = false
-START_SSH_SERVER = true
-SSH_DOMAIN = 10.0.0.139
-SSH_PORT = 2222
-SSH_LISTEN_PORT = 2222
-LANDING_PAGE = explore
-OFFLINE_MODE = false
-
-[database]
-DB_TYPE = sqlite3
-PATH = /home/robert/splux-forge/data/forgejo.db
-
-[security]
-INSTALL_LOCK = true
-; SECRET_KEY and INTERNAL_TOKEN are generated by install.sh
-
-[oauth2]
-; JWT_SECRET is generated by install.sh
-
-[service]
-DISABLE_REGISTRATION = true
-REQUIRE_SIGNIN_VIEW = false
-ENABLE_NOTIFY_MAIL = false
-DEFAULT_KEEP_EMAIL_PRIVATE = true
-NO_REPLY_ADDRESS = noreply.splux.robertflexx.dev
-
-[ui]
-DEFAULT_THEME = splux
-THEMES = splux,forgejo-dark,forgejo-auto,forgejo-light
-SHOW_USER_EMAIL = false
-DEFAULT_SHOW_FULL_NAME = false
-
-[repository]
-DEFAULT_BRANCH = main
-DEFAULT_PRIVATE = last
-ENABLE_PUSH_CREATE_USER = false
-ENABLE_PUSH_CREATE_ORG = false
-
-[picture]
-DISABLE_GRAVATAR = true
-ENABLE_FEDERATED_AVATAR = false
-
-[cors]
-ENABLED = true
-SCHEME = https
-ALLOW_DOMAIN = splux.robertflexx.dev
-ALLOW_SUBDOMAIN = false
-METHODS = GET,HEAD,OPTIONS
-HEADERS = Content-Type,Authorization
-MAX_AGE = 10m
-ALLOW_CREDENTIALS = false
-
-[other]
-SHOW_FOOTER_VERSION = false
-SHOW_FOOTER_TEMPLATE_LOAD_TIME = false
-SHOW_FOOTER_POWERED_BY = false
-
-[session]
-PROVIDER = file
-
-[log]
-MODE = file
-LEVEL = info
-ROOT_PATH = /home/robert/splux-forge/log
diff --git a/forgejo/import-repos.sh b/forgejo/import-repos.sh
deleted file mode 100755
index 70cb588..0000000
--- a/forgejo/import-repos.sh
+++ /dev/null
@@ -1,62 +0,0 @@
-#!/bin/sh
-# Import official GitHub trees into Splux Git. No tokens.
-# Usage: sh forgejo/import-repos.sh
-set -eu
-
-FORGE=${FORGE:-/home/robert/splux-forge}
-BIN=$FORGE/bin/forgejo
-DATA=$FORGE/data
-DUMP=${DUMP:-/tmp/fj-dump}
-FJ() {
- "$BIN" -w "$DATA" "$@"
-}
-
-already() {
- curl -sf -o /dev/null "http://127.0.0.1:3000/api/v1/repos/RobertFlexx/$1"
-}
-
-import_one() {
- name=$1
- url=$2
- if already "$name"
- then
- printf '%s\n' "already in forge: $name" >&2
- return 0
- fi
- unitdir=$DUMP/RobertFlexx/$name
- if [ ! -f "$unitdir/repo.yml" ]; then
- workdir=$(mktemp -d "$DUMP/work.XXXXXX")
- printf '%s\n' "dumping $name" >&2
- FJ dump-repo \
- --git_service github \
- --clone_addr "$url" \
- --owner_name RobertFlexx \
- --repo_name "$name" \
- --repo_dir "$workdir" \
- --units labels,releases,milestones
- mkdir -p "$DUMP/RobertFlexx"
- if [ -d "$workdir/RobertFlexx/$name" ]; then
- rm -rf "$unitdir"
- mv "$workdir/RobertFlexx/$name" "$unitdir"
- fi
- rm -rf "$workdir"
- fi
- [ -f "$unitdir/repo.yml" ] || {
- printf '%s\n' "dump missing $unitdir/repo.yml" >&2
- return 1
- }
- printf '%s\n' "restoring $name" >&2
- FJ restore-repo \
- --owner_name RobertFlexx \
- --repo_name "$name" \
- --repo_dir "$unitdir" \
- --units labels,releases,milestones
- printf '%s\n' "imported $name" >&2
-}
-
-mkdir -p "$DUMP"
-import_one SPS https://github.com/RobertFlexx/SPS.git
-import_one sps-core https://github.com/RobertFlexx/sps-core.git
-import_one sps-extra https://github.com/RobertFlexx/sps-extra.git
-import_one splux-site https://github.com/RobertFlexx/splux-site.git
-printf '%s\n' "import done" >&2
diff --git a/forgejo/install.sh b/forgejo/install.sh
deleted file mode 100755
index 0dae969..0000000
--- a/forgejo/install.sh
+++ /dev/null
@@ -1,153 +0,0 @@
-#!/bin/sh
-# Install Splux Git (Forgejo) on this host and copy the Splux theme.
-# Does not create an admin user or access token.
-# Usage: sh forgejo/install.sh
-set -eu
-
-SITE=$(CDPATH= cd -P "$(dirname "$0")/.." && pwd) || exit 1
-FORGE=${FORGE:-/home/robert/splux-forge}
-THEME=$SITE/forgejo
-DATA=$FORGE/data
-CONF=$DATA/custom/conf/app.ini
-BIN=$FORGE/bin/forgejo
-FJ() {
- "$BIN" -w "$DATA" -c "$CONF" "$@"
-}
-
-[ -x "$BIN" ] || {
- printf '%s\n' "missing $BIN" >&2
- exit 1
-}
-
-mkdir -p "$DATA/custom/conf" "$DATA/custom/public/assets/css" \
- "$DATA/custom/public/assets/img" "$DATA/custom/templates/custom" \
- "$FORGE/log"
-
-install_theme() {
- cp "$THEME/theme-splux.css" "$DATA/custom/public/assets/css/theme-splux.css"
- cp "$THEME/templates/custom/extra_links.tmpl" \
- "$DATA/custom/templates/custom/extra_links.tmpl"
- cp "$THEME/templates/custom/extra_links_footer.tmpl" \
- "$DATA/custom/templates/custom/extra_links_footer.tmpl"
- if [ -f "$SITE/site/assets/sps.png" ]; then
- cp "$SITE/site/assets/sps.png" "$DATA/custom/public/assets/img/logo.png"
- cp "$SITE/site/assets/sps.png" \
- "$DATA/custom/public/assets/img/apple-touch-icon.png"
- fi
- if [ -f "$SITE/site/assets/favicon.png" ]; then
- cp "$SITE/site/assets/favicon.png" "$DATA/custom/public/assets/img/favicon.png"
- fi
-}
-
-write_app_ini() {
- sk=$("$BIN" generate secret SECRET_KEY)
- it=$("$BIN" generate secret INTERNAL_TOKEN)
- jw=$("$BIN" generate secret JWT_SECRET)
- umask 077
- cat >"$CONF" <<EOF
-APP_NAME = Splux Git
-APP_SLOGAN = official repositories for Splux and SPS
-RUN_USER = robert
-WORK_PATH = $DATA
-
-[server]
-APP_DATA_PATH = $DATA
-PROTOCOL = http
-DOMAIN = 10.0.0.139
-HTTP_ADDR = 0.0.0.0
-HTTP_PORT = 3000
-ROOT_URL = http://10.0.0.139:3000/
-DISABLE_SSH = false
-START_SSH_SERVER = true
-SSH_DOMAIN = 10.0.0.139
-SSH_PORT = 2222
-SSH_LISTEN_PORT = 2222
-LANDING_PAGE = explore
-OFFLINE_MODE = false
-
-[database]
-DB_TYPE = sqlite3
-PATH = $DATA/forgejo.db
-
-[security]
-INSTALL_LOCK = true
-SECRET_KEY = $sk
-INTERNAL_TOKEN = $it
-
-[oauth2]
-JWT_SECRET = $jw
-
-[service]
-DISABLE_REGISTRATION = true
-REQUIRE_SIGNIN_VIEW = false
-ENABLE_NOTIFY_MAIL = false
-DEFAULT_KEEP_EMAIL_PRIVATE = true
-NO_REPLY_ADDRESS = noreply.splux.robertflexx.dev
-
-[ui]
-DEFAULT_THEME = splux
-THEMES = splux,forgejo-dark,forgejo-auto,forgejo-light
-SHOW_USER_EMAIL = false
-
-[repository]
-DEFAULT_BRANCH = main
-DEFAULT_PRIVATE = last
-ENABLE_PUSH_CREATE_USER = false
-ENABLE_PUSH_CREATE_ORG = false
-
-[picture]
-DISABLE_GRAVATAR = true
-ENABLE_FEDERATED_AVATAR = false
-
-[cors]
-ENABLED = true
-SCHEME = https
-ALLOW_DOMAIN = splux.robertflexx.dev
-METHODS = GET,HEAD,OPTIONS
-HEADERS = Content-Type,Authorization
-MAX_AGE = 10m
-ALLOW_CREDENTIALS = false
-
-[other]
-SHOW_FOOTER_VERSION = false
-SHOW_FOOTER_TEMPLATE_LOAD_TIME = false
-SHOW_FOOTER_POWERED_BY = false
-
-[session]
-PROVIDER = file
-
-[log]
-MODE = file
-LEVEL = info
-ROOT_PATH = $FORGE/log
-EOF
-}
-
-install_theme
-
-if [ ! -f "$CONF" ] || ! grep -q '^INSTALL_LOCK = true' "$CONF" 2>/dev/null
-then
- write_app_ini
-fi
-
-FJ migrate
-sh "$FORGE/start.sh"
-
-i=0
-while [ "$i" -lt 40 ]
-do
- if curl -fsS http://127.0.0.1:3000/api/v1/version >/dev/null 2>&1
- then
- break
- fi
- i=$((i + 1))
- sleep 1
-done
-curl -fsS http://127.0.0.1:3000/api/v1/version >/dev/null || {
- printf '%s\n' "forgejo did not start on :3000" >&2
- exit 1
-}
-
-printf '%s\n' "Splux Git: http://10.0.0.139:3000/" >&2
-printf '%s\n' "Create the admin account yourself, then migrate the four GitHub trees from the web UI:" >&2
-printf '%s\n' " $BIN -w $DATA -c $CONF admin user create --username RobertFlexx --email ohf9ck@gmail.com --admin --password 'your-password'" >&2
diff --git a/forgejo/templates/custom/extra_links.tmpl b/forgejo/templates/custom/extra_links.tmpl
deleted file mode 100644
index 37ed272..0000000
--- a/forgejo/templates/custom/extra_links.tmpl
+++ /dev/null
@@ -1,4 +0,0 @@
-<a class="item" href="https://splux.robertflexx.dev/">Handbook</a>
-<a class="item" href="https://splux.robertflexx.dev/git/">Git</a>
-<a class="item" href="https://splux.robertflexx.dev/packages/">Packages</a>
-<a class="item" href="https://splux.robertflexx.dev/download/">Download</a>
diff --git a/forgejo/templates/custom/extra_links_footer.tmpl b/forgejo/templates/custom/extra_links_footer.tmpl
deleted file mode 100644
index 004d307..0000000
--- a/forgejo/templates/custom/extra_links_footer.tmpl
+++ /dev/null
@@ -1,3 +0,0 @@
-<a href="https://splux.robertflexx.dev/">splux.robertflexx.dev</a>
-·
-<a href="https://github.com/RobertFlexx">GitHub mirror</a>
diff --git a/forgejo/theme-splux.css b/forgejo/theme-splux.css
deleted file mode 100644
index 12e6bc0..0000000
--- a/forgejo/theme-splux.css
+++ /dev/null
@@ -1,306 +0,0 @@
-/*
- * Splux Git. Same black, gray, yellow, monospace as splux.robertflexx.dev.
- * Drop at $FORGEJO_CUSTOM/public/assets/css/theme-splux.css
- */
-
-@import url("./theme-forgejo-dark.css");
-
-:root {
- color-scheme: dark;
-
- --fonts-proportional: ui-monospace, "SFMono-Regular", "Cascadia Mono",
- "Liberation Mono", "DejaVu Sans Mono", "Adwaita Mono", monospace !important;
- --fonts-monospace: ui-monospace, "SFMono-Regular", "Cascadia Mono",
- "Liberation Mono", "DejaVu Sans Mono", "Adwaita Mono", monospace !important;
-
- --color-primary: #ffff00 !important;
- --color-primary-hover: #ffff66 !important;
- --color-primary-active: #cccc00 !important;
- --color-primary-light-1: #ffff33 !important;
- --color-primary-light-2: #ffff66 !important;
- --color-primary-light-3: #ffff99 !important;
- --color-primary-dark-1: #cccc00 !important;
- --color-primary-dark-2: #999900 !important;
- --color-primary-alpha-10: rgba(255, 255, 0, 0.10) !important;
- --color-primary-alpha-20: rgba(255, 255, 0, 0.20) !important;
- --color-primary-alpha-40: rgba(255, 255, 0, 0.40) !important;
- --color-accent: #ffff00 !important;
- --color-secondary-button: #8a8a8a !important;
- --color-secondary-button-hover: #d6d6d6 !important;
-
- --color-body: #0a0a0a !important;
- --color-box-body: #111111 !important;
- --color-box-body-highlight: #1a1a1a !important;
- --color-secondary: #2a2a2a !important;
- --color-secondary-dark-1: #1a1a1a !important;
- --color-secondary-dark-2: #111111 !important;
- --color-secondary-dark-3: #0a0a0a !important;
- --color-secondary-dark-4: #000000 !important;
- --color-secondary-dark-5: #000000 !important;
- --color-secondary-dark-6: #000000 !important;
- --color-secondary-dark-7: #000000 !important;
- --color-secondary-dark-8: #000000 !important;
- --color-secondary-dark-9: #000000 !important;
- --color-secondary-dark-10: #000000 !important;
- --color-secondary-dark-11: #000000 !important;
- --color-secondary-dark-12: #000000 !important;
- --color-secondary-dark-13: #000000 !important;
- --color-secondary-light-1: #333333 !important;
- --color-secondary-alpha-20: rgba(255, 255, 255, 0.04) !important;
- --color-secondary-alpha-40: rgba(255, 255, 255, 0.07) !important;
- --color-secondary-alpha-60: rgba(255, 255, 255, 0.10) !important;
- --color-secondary-alpha-80: rgba(255, 255, 255, 0.14) !important;
-
- --color-border: #2a2a2a !important;
- --color-light-border: #2a2a2a !important;
-
- --color-text: #d6d6d6 !important;
- --color-text-dark: #d6d6d6 !important;
- --color-text-light: #8a8a8a !important;
- --color-text-light-1: #8a8a8a !important;
- --color-text-light-2: #6e6e6e !important;
- --color-text-light-3: #555555 !important;
- --color-text-light-4: #444444 !important;
- --color-text-light-5: #333333 !important;
- --color-text-light-6: #2a2a2a !important;
-
- --color-nav-bg: #0a0a0a !important;
- --color-nav-hover-bg: #1a1a1a !important;
- --color-nav-text: #d6d6d6 !important;
- --color-header-wrapper: #0a0a0a !important;
- --color-header-bar: #0a0a0a !important;
- --color-footer: #0a0a0a !important;
- --color-menu: #111111 !important;
-
- --color-markup-code-block: #111111 !important;
- --color-code-bg: #111111 !important;
- --color-code-sidebar-bg: #0a0a0a !important;
- --color-input-background: #111111 !important;
- --color-input-border: #2a2a2a !important;
- --color-input-text: #d6d6d6 !important;
- --color-hover: #1a1a1a !important;
- --color-active: #1a1a1a !important;
- --color-active-line: rgba(255, 255, 0, 0.08) !important;
-
- --color-button: #111111 !important;
- --color-button-hover: #1a1a1a !important;
-
- --color-label-text: #d6d6d6 !important;
- --color-label-hover-bg: #1a1a1a !important;
- --color-label-active-bg: rgba(255, 255, 0, 0.12) !important;
- --color-label-active-text: #ffff00 !important;
-
- --color-red: #ff6666 !important;
- --color-orange: #ffcc00 !important;
- --color-yellow: #ffff00 !important;
- --color-olive: #cccc00 !important;
- --color-green: #88cc44 !important;
- --color-teal: #88aaaa !important;
- --color-blue: #88aacc !important;
- --color-violet: #aaaaee !important;
- --color-purple: #cc88cc !important;
- --color-pink: #eeaaaa !important;
- --color-brown: #aa8866 !important;
- --color-grey: #8a8a8a !important;
- --color-black: #0a0a0a !important;
- --color-gold: #ffff00 !important;
- --color-white: #d6d6d6 !important;
-
- --color-diff-removed-word-bg: rgba(255, 102, 102, 0.28) !important;
- --color-diff-added-word-bg: rgba(255, 255, 0, 0.22) !important;
- --color-diff-removed-row-bg: rgba(255, 102, 102, 0.08) !important;
- --color-diff-added-row-bg: rgba(255, 255, 0, 0.07) !important;
- --color-diff-removed-row-border: rgba(255, 102, 102, 0.25) !important;
- --color-diff-added-row-border: rgba(255, 255, 0, 0.25) !important;
- --color-diff-inactive: #111111 !important;
-
- --color-console-fg: #d6d6d6 !important;
- --color-console-bg: #0a0a0a !important;
- --color-console-border: #2a2a2a !important;
-
- --shadow-xs: none !important;
- --shadow-sm: none !important;
- --shadow-md: none !important;
- --shadow-lg: none !important;
- --shadow-xl: none !important;
-
- --border-radius: 0 !important;
- --border-radius-circle: 0 !important;
-}
-
-html,
-body {
- background: #0a0a0a !important;
- color: #d6d6d6 !important;
- font-family: ui-monospace, "SFMono-Regular", "Cascadia Mono",
- "Liberation Mono", "DejaVu Sans Mono", monospace !important;
- font-size: 15px !important;
- line-height: 1.5 !important;
-}
-
-*,
-.ui.segment,
-.ui.card,
-.ui.menu,
-.ui.dropdown .menu,
-.ui.modal,
-.ui.popup {
- box-shadow: none !important;
- border-radius: 0 !important;
-}
-
-.ui.segment,
-.ui.attached.segment,
-.repository .header-wrapper,
-.page-content {
- border-color: #2a2a2a !important;
- background: #0a0a0a !important;
-}
-
-.ui.card,
-.ui.cards > .card {
- border: 1px solid #2a2a2a !important;
- background: #111111 !important;
-}
-
-.flex-item {
- border-bottom: 1px solid #1a1a1a !important;
-}
-
-a:not(.button):not(.ui.label) {
- color: #ffff00 !important;
- text-decoration: none !important;
-}
-
-a:not(.button):hover {
- text-decoration: underline !important;
- color: #ffff66 !important;
-}
-
-.ui.button,
-.ui.basic.button {
- border-radius: 0 !important;
- font-family: inherit !important;
- text-transform: none !important;
- font-weight: 400 !important;
-}
-
-.ui.primary.button,
-a.button.primary {
- background: #ffff00 !important;
- color: #0a0a0a !important;
- border: 1px solid #ffff00 !important;
- font-weight: 700 !important;
-}
-
-.ui.primary.button:hover,
-a.button.primary:hover {
- background: #0a0a0a !important;
- color: #ffff00 !important;
- border: 1px solid #ffff00 !important;
-}
-
-.ui.basic.button {
- background: transparent !important;
- color: #8a8a8a !important;
- border: 1px solid #2a2a2a !important;
-}
-
-.ui.basic.button:hover {
- color: #ffff00 !important;
- border-color: #ffff00 !important;
- background: transparent !important;
-}
-
-.ui.tabular.menu {
- border-bottom: 1px solid #2a2a2a !important;
-}
-
-.ui.tabular.menu .item {
- border-radius: 0 !important;
- color: #8a8a8a !important;
-}
-
-.ui.tabular.menu .active.item {
- background: #111111 !important;
- color: #ffff00 !important;
- border-color: #2a2a2a !important;
- border-bottom-color: #0a0a0a !important;
-}
-
-.ui.secondary.menu .active.item {
- color: #ffff00 !important;
-}
-
-#navbar,
-.ui.secondary.menu {
- background: #0a0a0a !important;
- border-bottom: 1px solid #2a2a2a !important;
-}
-
-.page-header,
-.repo-header {
- border-bottom: 1px solid #2a2a2a !important;
-}
-
-.ui.dropdown .menu {
- background: #111111 !important;
- border: 1px solid #2a2a2a !important;
-}
-
-.ui.dropdown .menu > .item {
- color: #d6d6d6 !important;
-}
-
-.ui.dropdown .menu > .item:hover {
- background: #1a1a1a !important;
- color: #ffff00 !important;
-}
-
-input,
-textarea,
-.ui.form input,
-.ui.input input,
-.ui.selection.dropdown {
- background: #111111 !important;
- color: #d6d6d6 !important;
- border: 1px solid #2a2a2a !important;
- border-radius: 0 !important;
- font-family: inherit !important;
-}
-
-footer {
- background: #0a0a0a !important;
- border-top: 1px solid #2a2a2a !important;
- color: #8a8a8a !important;
-}
-
-.code-view .lines-code,
-.code-view .lines-num,
-.chroma,
-pre,
-code {
- font-family: inherit !important;
-}
-
-::-webkit-scrollbar {
- width: 8px;
- height: 8px;
-}
-
-::-webkit-scrollbar-track {
- background: #0a0a0a;
-}
-
-::-webkit-scrollbar-thumb {
- background: #2a2a2a;
-}
-
-::-webkit-scrollbar-thumb:hover {
- background: #ffff00;
-}
-
-::selection {
- background: rgba(255, 255, 0, 0.28);
- color: #0a0a0a;
-}
diff --git a/site/assets/git.js b/site/assets/git.js
index bee9d2c..10b43b5 100644
--- a/site/assets/git.js
+++ b/site/assets/git.js
@@ -1,81 +1,32 @@
-// Fill /git/ with GitHub metadata and whether Splux Git answers.
+// Filter the static git index. Pages are built with the handbook;
+// GitHub is only a clone mirror, not a runtime backend.
(function () {
- var API = "https://api.github.com/repos/RobertFlexx/";
- var ACCEPT = { Accept: "application/vnd.github+json" };
- var thisScript = document.currentScript ||
- document.querySelector("script[src*=\"git.js\"]");
- var gitHost = (thisScript && thisScript.getAttribute("data-git")) ||
- "https://git.splux.robertflexx.dev";
- gitHost = String(gitHost).replace(/\/+$/, "");
-
- function esc(s) {
- return String(s)
- .replace(/&/g, "&")
- .replace(/</g, "<")
- .replace(/>/g, ">")
- .replace(/"/g, """);
- }
-
- function json(url) {
- return fetch(url, { headers: ACCEPT }).then(function (r) {
- if (!r.ok)
- throw new Error(String(r.status));
- return r.json();
- });
- }
-
- function when(iso) {
- if (!iso)
- return "";
- var d = new Date(iso);
- if (isNaN(d.getTime()))
- return iso;
- try {
- return d.toLocaleString(undefined, {
- year: "numeric",
- month: "short",
- day: "numeric"
- });
- } catch (e) {
- return iso.slice(0, 10);
- }
+ function ready() {
+ var input = document.getElementById("git-filter");
+ var table = document.getElementById("git-repos");
+ if (input && table)
+ bindFilter(input, table);
+ var tree = document.querySelector("table.git-tree");
+ if (input && tree)
+ bindFilter(input, tree);
}
- var status = document.getElementById("git-status");
- if (status) {
- fetch(gitHost + "/api/v1/version", { mode: "cors" }).then(function (r) {
- if (!r.ok)
- throw new Error(String(r.status));
- return r.json();
- }).then(function (v) {
- var ver = (v && (v.version || v.forgejo)) || "up";
- status.innerHTML = "reachable (" + esc(String(ver)) + ")";
- }).catch(function () {
- status.textContent =
- "not reachable from this browser yet; clone GitHub until DNS and TLS exist";
- var rows = document.querySelectorAll("#git-repos tr[data-repo]");
- for (var j = 0; j < rows.length; j++) {
- var name = rows[j].getAttribute("data-repo");
- var a = rows[j].querySelector("a.name");
- if (a && name)
- a.setAttribute("href",
- "https://github.com/RobertFlexx/" + name);
+ function bindFilter(input, table) {
+ function apply() {
+ var q = (input.value || "").toLowerCase();
+ var rows = table.querySelectorAll("tbody tr");
+ for (var i = 0; i < rows.length; i++) {
+ var hay = rows[i].getAttribute("data-search") ||
+ rows[i].textContent || "";
+ rows[i].hidden = q !== "" &&
+ hay.toLowerCase().indexOf(q) === -1;
}
- });
+ }
+ input.addEventListener("input", apply);
}
- var rows = document.querySelectorAll("#git-repos tr[data-repo]");
- for (var i = 0; i < rows.length; i++) {
- (function (row) {
- var name = row.getAttribute("data-repo");
- json(API + encodeURIComponent(name)).then(function (repo) {
- var lang = row.querySelector(".lang");
- var pushed = row.querySelector(".pushed");
- if (lang && repo.language)
- lang.textContent = repo.language;
- if (pushed && repo.pushed_at)
- pushed.textContent = when(repo.pushed_at);
- }).catch(function () {});
- })(rows[i]);
- }
+ if (document.readyState === "loading")
+ document.addEventListener("DOMContentLoaded", ready);
+ else
+ ready();
})();
diff --git a/site/assets/live.js b/site/assets/live.js
index ce633ae..a1af22b 100644
--- a/site/assets/live.js
+++ b/site/assets/live.js
@@ -21,7 +21,7 @@
document.querySelector("script[src*=\"live.js\"]");
var dataRoot = (thisScript && thisScript.getAttribute("data-root")) || "./";
var gitHost = (thisScript && thisScript.getAttribute("data-git")) ||
- "https://git.splux.robertflexx.dev";
+ "https://splux.robertflexx.dev/git";
gitHost = String(gitHost).replace(/\/+$/, "");
if (!feed && !brief && !isoEl && !tagEl)
return;
@@ -321,15 +321,19 @@
function commitHref(repoPath, sha, htmlUrl) {
if (gitHost && repoPath && sha)
- return gitHost + "/RobertFlexx/" + repoPath + "/commit/" + sha;
+ return gitHost + "/" + repoPath + "/commit/" + sha + "/";
return htmlUrl || "";
}
function forgeCommitHref(url) {
- var m = /^https:\/\/github\.com\/RobertFlexx\/([^/]+)\/commit\/([0-9a-fA-F]+)/.exec(String(url || ""));
+ var u = String(url || "");
+ var m = /^https:\/\/github\.com\/RobertFlexx\/([^/]+)\/commit\/([0-9a-fA-F]+)/.exec(u);
if (m && gitHost)
- return gitHost + "/RobertFlexx/" + m[1] + "/commit/" + m[2];
- return url;
+ return gitHost + "/" + m[1] + "/commit/" + m[2] + "/";
+ m = /^https:\/\/git\.splux\.robertflexx\.dev\/RobertFlexx\/([^/]+)\/commit\/([0-9a-fA-F]+)/.exec(u);
+ if (m && gitHost)
+ return gitHost + "/" + m[1] + "/commit/" + m[2] + "/";
+ return u;
}
function setSha(id, repoPath, sha) {
diff --git a/site/assets/style.css b/site/assets/style.css
index 6a68315..228449f 100644
--- a/site/assets/style.css
+++ b/site/assets/style.css
@@ -627,65 +627,56 @@ table.docs th {
}
}
-.wip {
- margin: 1.25rem 0 2rem;
- border: 1px solid var(--rule);
- background: #111;
-}
-
-.wip-tape {
- height: 12px;
- background: repeating-linear-gradient(
- -45deg,
- var(--accent),
- var(--accent) 10px,
- #111 10px,
- #111 20px
- );
+pre.block.git-blob {
+ max-height: 70vh;
+ font-size: 0.82rem;
+ line-height: 1.4;
+ white-space: pre;
}
-.wip-board {
- display: flex;
- flex-direction: column;
- align-items: center;
- justify-content: center;
- gap: 1.25rem;
- padding: 3rem 1.5rem 2.5rem;
- text-align: center;
+.git-nav {
color: var(--muted);
}
-.wip-board p {
- margin: 0;
- max-width: none;
+.lang-bar {
+ display: flex;
+ height: 10px;
+ border: 1px solid var(--rule);
+ margin: 0.5rem 0 0.75rem;
+ overflow: hidden;
+ background: #111;
}
-.wip-mark,
-.wip-prompt {
- color: var(--fg);
+.lang-seg {
+ display: block;
+ height: 100%;
+ background: var(--accent);
+ opacity: 0.95;
+ min-width: 1px;
}
-.wip-copy {
- white-space: pre-line;
- line-height: 1.65;
-}
+.lang-seg:nth-child(2) { opacity: 0.7; }
+.lang-seg:nth-child(3) { opacity: 0.5; }
+.lang-seg:nth-child(n+4) { opacity: 0.35; background: #888; }
-.wip-cursor {
- display: inline-block;
- width: 0.7em;
- height: 1.05em;
- margin-left: 0.2em;
- vertical-align: -0.12em;
- background: var(--accent);
- animation: wip-blink 1.05s steps(1, end) infinite;
+.lang-list {
+ list-style: none;
+ padding: 0;
+ margin: 0 0 1.25rem;
+ color: var(--muted);
+ font-size: 0.92rem;
}
-@keyframes wip-blink {
- 50% { opacity: 0; }
+.lang-list li {
+ display: inline;
+ margin-right: 1rem;
}
-@media (prefers-reduced-motion: reduce) {
- .wip-cursor {
- animation: none;
- }
+#git-filter {
+ background: #111;
+ color: var(--fg);
+ border: 1px solid var(--rule);
+ font: inherit;
+ padding: 0.25rem 0.5rem;
+ min-width: 12rem;
}
diff --git a/site/docs/first-boot/index.html b/site/docs/first-boot/index.html
index 0ba11a0..1662947 100644
--- a/site/docs/first-boot/index.html
+++ b/site/docs/first-boot/index.html
@@ -56,6 +56,7 @@ dhcpcd eth0</pre>
<tr><td>runit</td><td>symlink under <code>/etc/runit/runsvdir/default</code></td></tr>
<tr><td>dinit</td><td>symlink under <code>/etc/dinit.d/boot.d</code></td></tr>
<tr><td>Shepherd</td><td>Scheme files under <code>/etc/shepherd.d</code></td></tr>
+<tr><td>SysV</td><td>scripts in <code>/etc/rc.d/init.d</code>; enable with <code>S*</code> links in <code>rc2.d</code> through <code>rc5.d</code></td></tr>
</tbody>
</table>
diff --git a/site/docs/images/index.html b/site/docs/images/index.html
index 2048e52..24e98a4 100644
--- a/site/docs/images/index.html
+++ b/site/docs/images/index.html
@@ -17,7 +17,7 @@
<main id="main">
<h2>Live images</h2>
<hr class="rule">
-<p>Images are hybrid ISOs from <a href="https://splux.robertflexx.dev/git/RobertFlexx/SPS">RobertFlexx/SPS</a>. Filenames stay the same; the current tag is <a href="https://github.com/RobertFlexx/SPS/releases/latest">live-2026-09-06-1</a> (2026-09-06). Verify against <a href="https://github.com/RobertFlexx/SPS/releases/latest/download/SHA256SUMS">SHA256SUMS</a>.</p>
+<p>Images are hybrid ISOs from <a href="../../../../git/SPS/">SPS</a>. Filenames stay the same; the current tag is <a href="https://github.com/RobertFlexx/SPS/releases/latest">live-2026-09-06-1</a> (2026-09-06). Verify against <a href="https://github.com/RobertFlexx/SPS/releases/latest/download/SHA256SUMS">SHA256SUMS</a>.</p>
<p>Every image includes SPS (<code>src</code>, <code>sget</code>, <code>mkpkg</code>, <code>pkin</code>, <code>setup</code>, <code>mkiso</code>, and the rest), <code>dialog</code>, disk tools, <code>dhcpcd</code>, <code>grub-install</code>, and <code>grub-mkconfig</code>. Live PID 1 is busybox init on published snapshots. <code>/bin/sh</code> is busybox. Login is <code>root</code> with an empty password.</p>
<table class="docs">
diff --git a/site/docs/index.html b/site/docs/index.html
index d37ac0e..5d0da81 100644
--- a/site/docs/index.html
+++ b/site/docs/index.html
@@ -55,12 +55,12 @@
<h3>Reference trees</h3>
<ul class="plain">
<li><a href="../../../../packages/">Package browser</a> (1474 packages)</li>
-<li><a href="https://splux.robertflexx.dev/git/RobertFlexx/SPS/src/branch/main/README.md">SPS README</a></li>
-<li><a href="https://splux.robertflexx.dev/git/RobertFlexx/SPS/src/branch/main/DESIGN.md">SPS 1.0 formats and behavior</a></li>
-<li><a href="https://splux.robertflexx.dev/git/RobertFlexx/SPS/src/branch/main/man/setup.1">setup(1)</a></li>
-<li><a href="https://splux.robertflexx.dev/git/RobertFlexx/SPS/src/branch/main/PACKAGE-MAINTAINER.md">Package maintainer guide</a></li>
-<li><a href="https://splux.robertflexx.dev/git/RobertFlexx/sps-core/src/branch/main/README.md">core collection</a></li>
-<li><a href="https://splux.robertflexx.dev/git/RobertFlexx/sps-extra/src/branch/main/README.md">extra collection</a></li>
+<li><a href="../../../../git/SPS/blob/README.md/">SPS README</a></li>
+<li><a href="../../../../git/SPS/blob/DESIGN.md/">SPS 1.0 formats and behavior</a></li>
+<li><a href="../../../../git/SPS/blob/man/setup.1/">setup(1)</a></li>
+<li><a href="../../../../git/SPS/blob/PACKAGE-MAINTAINER.md/">Package maintainer guide</a></li>
+<li><a href="../../../../git/sps-core/">core collection</a></li>
+<li><a href="../../../../git/sps-extra/">extra collection</a></li>
<li><a href="../../../../git/">Splux Git</a></li>
<li><a href="../../../../source/">Source repositories</a></li>
</ul>
diff --git a/site/docs/sps/index.html b/site/docs/sps/index.html
index 674527a..3e2eea2 100644
--- a/site/docs/sps/index.html
+++ b/site/docs/sps/index.html
@@ -56,13 +56,10 @@ unset SPS_DB SPS_CACHE SPS_BUILD SPS_CONFIG SPS_REPOS_CONFIG SPS_REPO_ROOT</pre>
<p>Leaving those unset is required so they resolve under the target, not under the live root.</p>
<h3>Repositories</h3>
-<p><code>/etc/sps/repos.conf</code> lists trees. Higher priority wins. Splux Git is official. Until that name answers, use the GitHub mirrors, not both at once.</p>
+<p><code>/etc/sps/repos.conf</code> lists trees. Higher priority wins. Clone from GitHub. The handbook git pages are a static browse of the same trees, not a clone URL.</p>
<pre class="block">dir core /usr/src/sps/core 100
dir extra /usr/src/sps/extra 80
-git core https://splux.robertflexx.dev/git/RobertFlexx/sps-core.git 100
-git extra https://splux.robertflexx.dev/git/RobertFlexx/sps-extra.git 80
-
git core https://github.com/RobertFlexx/sps-core.git 100
git extra https://github.com/RobertFlexx/sps-extra.git 80</pre>
<p>On tty and Plasma images the live <code>repos.conf</code> uses <code>dir</code> entries pointing at the bundled trees. Slim images have no recipes, so they use the git lines. <code>src update</code> for a git repo needs <code>git</code>, which slim does not ship.</p>
@@ -86,6 +83,7 @@ sget install curl</pre>
<tr><td><code>runit</code></td><td><code>init-runit</code></td><td>runit, eudev, elogind</td></tr>
<tr><td><code>dinit</code></td><td><code>init-dinit</code></td><td>dinit, eudev, elogind</td></tr>
<tr><td><code>shepherd</code></td><td><code>init-shepherd</code></td><td>GNU Shepherd, eudev, elogind, Guile</td></tr>
+<tr><td><code>sysvinit</code></td><td><code>init-sysvinit</code></td><td>SysV init, eudev, elogind</td></tr>
<tr><td><code>none</code></td><td>(no init package)</td><td>the installed tree has no PID 1 from SPS</td></tr>
</tbody>
</table>
@@ -96,9 +94,9 @@ sget install curl</pre>
<h3>Further reading</h3>
<ul class="plain">
-<li><a href="https://splux.robertflexx.dev/git/RobertFlexx/SPS/src/branch/main/README.md">SPS README</a></li>
-<li><a href="https://splux.robertflexx.dev/git/RobertFlexx/SPS/src/branch/main/DESIGN.md">DESIGN.md</a></li>
-<li><a href="https://splux.robertflexx.dev/git/RobertFlexx/SPS/src/branch/main/PACKAGE-MAINTAINER.md">Recipe format</a></li>
+<li><a href="../../../../git/SPS/blob/README.md/">SPS README</a></li>
+<li><a href="../../../../git/SPS/blob/DESIGN.md/">DESIGN.md</a></li>
+<li><a href="../../../../git/SPS/blob/PACKAGE-MAINTAINER.md/">Recipe format</a></li>
<li><a href="../../../../packages/">Package browser</a></li>
</ul>
</main>
diff --git a/site/download/index.html b/site/download/index.html
index 94ae8c2..e4fbeeb 100644
--- a/site/download/index.html
+++ b/site/download/index.html
@@ -15,7 +15,7 @@
<main id="main">
<h2>Download</h2>
<hr class="rule">
-<p>Images are hybrid ISOs from <a href="https://splux.robertflexx.dev/git/RobertFlexx/SPS">RobertFlexx/SPS</a>. The filenames below are stable. This page names the current <code>live-*</code> ISO tag and links to that GitHub release.</p>
+<p>Images are hybrid ISOs from <a href="../../../../git/SPS/">SPS</a>. The filenames below are stable. This page names the current <code>live-*</code> ISO tag and links to that GitHub release.</p>
<div class="dl-row"><span class="muted">Latest tag</span><span id="live-tag">live-2026-09-06-1</span></div>
<div class="dl-row"><span class="muted">Released</span><span id="live-date">2026-09-06</span></div>
<div class="dl-row"><span class="muted">Architecture</span><span>x86_64</span></div>
diff --git a/site/git/index.html b/site/git/index.html
index bd11ee4..6fcfa3c 100644
--- a/site/git/index.html
+++ b/site/git/index.html
@@ -3,8 +3,8 @@
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
-<title>Git (WIP) - Splux Linux</title>
-<meta name="description" content="Splux Git. Under construction.">
+<title>Git - Splux Linux</title>
+<meta name="description" content="Static browse of the official Splux git trees.">
<link rel="icon" href="../../../../assets/favicon.png" type="image/png">
<link rel="stylesheet" href="../../../../assets/style.css">
</head>
@@ -13,22 +13,9 @@
<div class="wrap">
@@HEADER@@
<main id="main">
-<h2>Git <span class="num">(WIP)</span></h2>
+<h2>Git</h2>
<hr class="rule">
-<div class="wip" role="status">
-<div class="wip-tape" aria-hidden="true"></div>
-<div class="wip-board">
-<p class="wip-mark">[ under construction ]</p>
-<p class="wip-copy">the floor is open
-the roof is not
-
-no trees
-no clones
-no pull requests</p>
-<p class="wip-prompt">$ <span class="wip-cursor"></span></p>
-</div>
-<div class="wip-tape" aria-hidden="true"></div>
-</div>
+<p>This page is generated at site build from the official clones. If you are reading it in the source tree, run <code>tools/build-site.sh</code>.</p>
</main>
@@FOOTER@@
</div>
diff --git a/site/index.html b/site/index.html
index 10fd030..f2af9ae 100644
--- a/site/index.html
+++ b/site/index.html
@@ -69,9 +69,9 @@ pkin: installed curl 8.21.0-2</pre>
<h2 id="repos"><span class="num">[004]</span> Repositories</h2>
<hr class="rule">
-<p><a href="https://splux.robertflexx.dev/git/RobertFlexx/sps-core">sps-core</a><br>
+<p><a href="../../../../git/sps-core/">sps-core</a><br>
Base system, toolchain, libraries, boot, filesystems, and networking. 119 packages. GitHub mirror: <a href="https://github.com/RobertFlexx/sps-core">RobertFlexx/sps-core</a>.</p>
-<p><a href="https://splux.robertflexx.dev/git/RobertFlexx/sps-extra">sps-extra</a><br>
+<p><a href="../../../../git/sps-extra/">sps-extra</a><br>
Desktop software, graphics, multimedia, development tools, and other packages. 1355 packages. GitHub mirror: <a href="https://github.com/RobertFlexx/sps-extra">RobertFlexx/sps-extra</a>.</p>
<p>SPS also supports administrator-maintained local repositories in addition to the official trees. Browse recipes from <a href="../../../../git/">Splux Git</a>.</p>
@@ -80,24 +80,24 @@ Desktop software, graphics, multimedia, development tools, and other packages. @
<p><a href="../../../../docs/">Handbook</a><br>
<a href="../../../../install/">Install</a> (setup, manual tty, slim)<br>
<a href="../../../../docs/images/">Live images</a><br>
-<a href="https://splux.robertflexx.dev/git/RobertFlexx/SPS/src/branch/main/README.md">SPS README</a><br>
-<a href="https://splux.robertflexx.dev/git/RobertFlexx/SPS/src/branch/main/DESIGN.md">SPS 1.0 formats</a></p>
+<a href="../../../../git/SPS/blob/README.md/">SPS README</a><br>
+<a href="../../../../git/SPS/blob/DESIGN.md/">SPS 1.0 formats</a></p>
<h2 id="source"><span class="num">[006]</span> Source</h2>
<hr class="rule">
<p>
<a href="../../../../git/">Splux Git</a>
-canonical forge<br>
-<a href="https://splux.robertflexx.dev/git/RobertFlexx/SPS">SPS</a>
+static browse of the official trees<br>
+<a href="../../../../git/SPS/">SPS</a>
the package system<br>
-<a href="https://splux.robertflexx.dev/git/RobertFlexx/sps-core">sps-core</a>
+<a href="../../../../git/sps-core/">sps-core</a>
official base recipes<br>
-<a href="https://splux.robertflexx.dev/git/RobertFlexx/sps-extra">sps-extra</a>
+<a href="../../../../git/sps-extra/">sps-extra</a>
official extra recipes<br>
-<a href="https://splux.robertflexx.dev/git/RobertFlexx/splux-site">splux-site</a>
+<a href="../../../../git/splux-site/">splux-site</a>
this website
</p>
-<p class="note">GitHub holds a read-only mirror of the same history. Live ISO files still come from GitHub Releases.</p>
+<p class="note">GitHub holds the clone URLs and live ISO files. This site rebuilds HTML from those trees; it does not run a git server.</p>
<h2 id="status"><span class="num">[007]</span> Project status</h2>
<hr class="rule">
diff --git a/site/install/index.html b/site/install/index.html
index 300abba..0b060a9 100644
--- a/site/install/index.html
+++ b/site/install/index.html
@@ -54,7 +54,7 @@
<h4>4. Run setup</h4>
<pre class="block">setup</pre>
-<p>Profiles: <code>minimal</code>, <code>server</code>, <code>plasma-desktop</code>, <code>plasma-full</code>. Init: systemd, OpenRC, s6, runit, dinit, or Shepherd. Those packages conflict. Guided partitioning waits until the last confirmation. Kernel <code>none</code> is the interactive default for a console profile; a disk that must boot itself needs <code>linux-desktop</code> or <code>linux</code>.</p>
+<p>Profiles: <code>minimal</code>, <code>server</code>, <code>plasma-desktop</code>, <code>plasma-full</code>. Init: systemd, OpenRC, s6, runit, dinit, Shepherd, or SysV. Those packages conflict. Guided partitioning waits until the last confirmation. Kernel <code>none</code> is the interactive default for a console profile; a disk that must boot itself needs <code>linux-desktop</code> or <code>linux</code>.</p>
<p>Non-interactive examples:</p>
<pre class="block">setup --plan --profile plasma-desktop --target /mnt --user alex
@@ -106,7 +106,7 @@ setup --non-interactive \
<h4>What setup does</h4>
<p>It writes hostname, timezone, keymap, locale, and <code>/etc/sps/init</code>, copies bundled recipe trees when they exist, writes <code>sps.conf</code>, runs <code>src update</code>, then <code>sget install</code>. Users land after packages so <code>filesystem</code>'s passwd file is already there. If you passed <code>--install-bootloader</code>, it runs live <code>grub-install</code> (EFI removable <code>EFI/BOOT/BOOTX64.EFI</code>, then NVRAM via <code>efibootmgr</code> when that binary exists; BIOS uses <code>i386-pc</code>). It does not run <code>grub-mkconfig</code>. See <code>/root/sps-bootloader.txt</code> on the target.</p>
-<p>A Plasma install compiles Qt and KDE and takes a long time. See <a href="https://splux.robertflexx.dev/git/RobertFlexx/SPS/src/branch/main/man/setup.1">setup(1)</a> for every flag.</p>
+<p>A Plasma install compiles Qt and KDE and takes a long time. See <a href="../../../../git/SPS/blob/man/setup.1/">setup(1)</a> for every flag.</p>
</section>
<section class="tabpanel" role="tabpanel" id="panel-manual" aria-labelledby="tab-manual">
@@ -222,6 +222,7 @@ unset SPS_DB SPS_CACHE SPS_BUILD SPS_CONFIG SPS_REPOS_CONFIG SPS_REPO_ROOT</pre>
<button type="button" role="tab" id="tab-runit" aria-controls="panel-init-runit" aria-selected="false" tabindex="-1" data-hash="runit">runit</button>
<button type="button" role="tab" id="tab-dinit" aria-controls="panel-init-dinit" aria-selected="false" tabindex="-1" data-hash="dinit">dinit</button>
<button type="button" role="tab" id="tab-shepherd" aria-controls="panel-init-shepherd" aria-selected="false" tabindex="-1" data-hash="shepherd">Shepherd</button>
+<button type="button" role="tab" id="tab-sysvinit" aria-controls="panel-init-sysvinit" aria-selected="false" tabindex="-1" data-hash="sysvinit">SysV</button>
</div>
<section class="tabpanel" role="tabpanel" id="panel-init-systemd" aria-labelledby="tab-systemd">
<pre class="block">printf '%s\n' systemd > /mnt/etc/sps/init
@@ -253,6 +254,11 @@ unset SPS_DB SPS_CACHE SPS_BUILD SPS_CONFIG SPS_REPOS_CONFIG SPS_REPO_ROOT</pre>
# later: sget install init-shepherd</pre>
<p>GNU Shepherd plus eudev, elogind, and Guile. Services are Scheme files under <code>/etc/shepherd.d</code>.</p>
</section>
+<section class="tabpanel" role="tabpanel" id="panel-init-sysvinit" aria-labelledby="tab-sysvinit">
+<pre class="block">printf '%s\n' sysvinit > /mnt/etc/sps/init
+# later: sget install init-sysvinit</pre>
+<p>SysV init plus eudev and elogind. Service scripts land in <code>/etc/rc.d/init.d</code>. Enable with <code>S*</code> links in <code>rc2.d</code> through <code>rc5.d</code>.</p>
+</section>
</div>
</li>
<li>
diff --git a/site/packages/index.html b/site/packages/index.html
index 20f7989..e48f0cf 100644
--- a/site/packages/index.html
+++ b/site/packages/index.html
@@ -15,7 +15,7 @@
<main id="main">
<h2>Packages</h2>
<hr class="rule">
-<p>Generated from the official <a href="https://splux.robertflexx.dev/git/RobertFlexx/sps-core">sps-core</a> and <a href="https://splux.robertflexx.dev/git/RobertFlexx/sps-extra">sps-extra</a> recipe trees. 1474 packages (119 core, 1355 extra). Updated 2026-10-19 13:01 UTC. Browse them from <a href="../../../../git/">Splux Git</a>.</p>
+<p>Generated from the official <a href="../../../../git/sps-core/">sps-core</a> and <a href="../../../../git/sps-extra/">sps-extra</a> recipe trees. 1474 packages (119 core, 1355 extra). Updated 2026-10-19 13:01 UTC. Browse them from <a href="../../../../git/">Splux Git</a>.</p>
<form id="pkg-search" role="search">
<label class="search" for="q">Search
<input id="q" name="q" type="search" autocomplete="off" spellcheck="false">
diff --git a/site/source/index.html b/site/source/index.html
index 6ecffd2..553c77a 100644
--- a/site/source/index.html
+++ b/site/source/index.html
@@ -15,15 +15,15 @@
<main id="main">
<h2>Source</h2>
<hr class="rule">
-<p>Canonical trees belong on <a href="../../../../git/">Splux Git</a>. GitHub is a read-only mirror of the same history. License for SPS and the package collections is ISC. See each repository.</p>
-<p><a href="https://splux.robertflexx.dev/git/RobertFlexx/SPS">SPS</a><br>
-Source Package System. POSIX shell and AWK. Installer and live ISO builder live here too. GitHub: <a href="https://github.com/RobertFlexx/SPS">RobertFlexx/SPS</a>.</p>
-<p><a href="https://splux.robertflexx.dev/git/RobertFlexx/sps-core">sps-core</a><br>
-Official base recipe collection. GitHub: <a href="https://github.com/RobertFlexx/sps-core">RobertFlexx/sps-core</a>.</p>
-<p><a href="https://splux.robertflexx.dev/git/RobertFlexx/sps-extra">sps-extra</a><br>
-Official extra recipe collection. GitHub: <a href="https://github.com/RobertFlexx/sps-extra">RobertFlexx/sps-extra</a>.</p>
-<p><a href="https://splux.robertflexx.dev/git/RobertFlexx/splux-site">splux-site</a><br>
-This website. Static HTML generated from the recipe trees. GitHub: <a href="https://github.com/RobertFlexx/splux-site">RobertFlexx/splux-site</a>.</p>
+<p>Canonical trees are browsed on <a href="../../../../git/">Splux Git</a>, a static HTML view rebuilt with this site. Clone from GitHub. License for SPS and the package collections is ISC. See each repository.</p>
+<p><a href="../../../../git/SPS/">SPS</a><br>
+Source Package System. POSIX shell and AWK. Installer and live ISO builder live here too. Clone: <a href="https://github.com/RobertFlexx/SPS.git">github.com/RobertFlexx/SPS.git</a>.</p>
+<p><a href="../../../../git/sps-core/">sps-core</a><br>
+Official base recipe collection. Clone: <a href="https://github.com/RobertFlexx/sps-core.git">github.com/RobertFlexx/sps-core.git</a>.</p>
+<p><a href="../../../../git/sps-extra/">sps-extra</a><br>
+Official extra recipe collection. Clone: <a href="https://github.com/RobertFlexx/sps-extra.git">github.com/RobertFlexx/sps-extra.git</a>.</p>
+<p><a href="../../../../git/splux-site/">splux-site</a><br>
+This website. Static HTML generated from the recipe trees. Clone: <a href="https://github.com/RobertFlexx/splux-site.git">github.com/RobertFlexx/splux-site.git</a>.</p>
</main>
@@FOOTER@@
</div>
diff --git a/tools/build-git.sh b/tools/build-git.sh
new file mode 100755
index 0000000..cd6a9d8
--- /dev/null
+++ b/tools/build-git.sh
@@ -0,0 +1,559 @@
+#!/bin/sh
+# Build a static git browser under $OUT/git from local clones.
+# No forge and no git-http-backend. Clone URLs are GitHub.
+# Env: OUT CORE EXTRA SPS SITE GIT_HOST SITE_URL
+
+set -eu
+
+cd "$(CDPATH= cd -P "$(dirname "$0")/.." && pwd)" || exit 1
+
+OUT=${OUT:-_site}
+CORE=${CORE:-vendor/core}
+EXTRA=${EXTRA:-vendor/extra}
+SPS=${SPS:-vendor/sps}
+SITE=${SITE:-.}
+SITE_URL=${SITE_URL:-https://splux.robertflexx.dev}
+GIT_HOST=${GIT_HOST:-$SITE_URL/git}
+GIT_HOST=${GIT_HOST%/}
+AWK=tools/git.awk
+MAXBLOB=262144
+
+esc() {
+ awk -f "$AWK" -v mode=one -v text="$1"
+}
+
+is_git() {
+ git -C "$1" rev-parse --is-inside-work-tree >/dev/null 2>&1
+}
+
+lang_of() {
+ path=$1
+ base=${path##*/}
+ case $path in
+ lib/setup/sv/*)
+ printf '%s\n' Shell
+ return
+ ;;
+ esac
+ case $base in
+ recipe) printf '%s\n' Recipe; return ;;
+ run) printf '%s\n' Shell; return ;;
+ Makefile|makefile|GNUmakefile) printf '%s\n' Make; return ;;
+ LICENSE|COPYING|COPYRIGHT) printf '%s\n' Text; return ;;
+ .gitignore|.gitattributes|.gitmodules) printf '%s\n' Git; return ;;
+ CNAME) printf '%s\n' Text; return ;;
+ esac
+ case $path in
+ *.sh) printf '%s\n' Shell ;;
+ *.awk) printf '%s\n' AWK ;;
+ *.c|*.h|*.in) printf '%s\n' C ;;
+ *.md) printf '%s\n' Markdown ;;
+ *.html) printf '%s\n' HTML ;;
+ *.css) printf '%s\n' CSS ;;
+ *.js) printf '%s\n' JavaScript ;;
+ *.json) printf '%s\n' JSON ;;
+ *.yml|*.yaml) printf '%s\n' YAML ;;
+ *.py) printf '%s\n' Python ;;
+ *.scm) printf '%s\n' Scheme ;;
+ *.service) printf '%s\n' systemd ;;
+ *.1|*.5|*.8) printf '%s\n' Manual ;;
+ *.svg) printf '%s\n' SVG ;;
+ *.xml) printf '%s\n' XML ;;
+ *.txt|*.conf|*.ini|*.cfg) printf '%s\n' Text ;;
+ *.png|*.jpg|*.jpeg|*.gif|*.webp|*.ico|*.woff|*.woff2|*.ttf)
+ printf '%s\n' Binary ;;
+ *.gz|*.xz|*.zst|*.bz2|*.zip|*.tar)
+ printf '%s\n' Binary ;;
+ *) printf '%s\n' Other ;;
+ esac
+}
+
+is_binary_name() {
+ case $1 in
+ *.png|*.jpg|*.jpeg|*.gif|*.webp|*.ico|*.woff|*.woff2|*.ttf| \
+ *.gz|*.xz|*.zst|*.bz2|*.zip|*.tar|*.bin)
+ return 0 ;;
+ esac
+ return 1
+}
+
+page_begin() {
+ _dest=$1
+ _title=$2
+ _desc=$3
+ mkdir -p "$(dirname "$_dest")"
+ {
+ printf '%s\n' '<!DOCTYPE html>'
+ printf '%s\n' '<html lang="en">'
+ printf '%s\n' '<head>'
+ printf '%s\n' '<meta charset="utf-8">'
+ printf '%s\n' '<meta name="viewport" content="width=device-width, initial-scale=1">'
+ printf '<title>%s</title>\n' "$(esc "$_title")"
+ printf '<meta name="description" content="%s">\n' "$(esc "$_desc")"
+ printf '%s\n' '<link rel="icon" href="../../../../assets/favicon.png" type="image/png">'
+ printf '%s\n' '<link rel="stylesheet" href="../../../../assets/style.css">'
+ printf '%s\n' '</head>'
+ printf '%s\n' '<body>'
+ printf '%s\n' '<a class="skip" href="#main">Skip to content</a>'
+ printf '%s\n' '<div class="wrap">'
+ printf '%s\n' '@@HEADER@@'
+ printf '%s\n' '<main id="main">'
+ } >"$_dest"
+}
+
+page_end() {
+ _dest=$1
+ {
+ printf '%s\n' '</main>'
+ printf '%s\n' '@@FOOTER@@'
+ printf '%s\n' '</div>'
+ if [ "${2-}" = "gitjs" ]; then
+ printf '%s\n' '<script src="../../../../assets/git.js?v=4c4f12c-20261019130111"></script>'
+ fi
+ printf '%s\n' '</body></html>'
+ } >>"$_dest"
+}
+
+write_redirect() {
+ dest=$1
+ target=$2
+ mkdir -p "$(dirname "$dest")"
+ {
+ printf '%s\n' '<!DOCTYPE html>'
+ printf '%s\n' '<html lang="en"><head>'
+ printf '%s\n' '<meta charset="utf-8">'
+ printf '<meta http-equiv="refresh" content="0;url=%s">\n' "$(esc "$target")"
+ printf '<link rel="canonical" href="%s">\n' "$(esc "$target")"
+ printf '<title>Redirect</title></head><body>\n'
+ printf '<p><a href="%s">Continue</a></p>\n' "$(esc "$target")"
+ printf '%s\n' '</body></html>'
+ } >"$dest"
+}
+
+github_of() {
+ case $1 in
+ SPS) printf '%s\n' https://github.com/RobertFlexx/SPS ;;
+ sps-core) printf '%s\n' https://github.com/RobertFlexx/sps-core ;;
+ sps-extra) printf '%s\n' https://github.com/RobertFlexx/sps-extra ;;
+ splux-site) printf '%s\n' https://github.com/RobertFlexx/splux-site ;;
+ *) printf '%s\n' "https://github.com/RobertFlexx/$1" ;;
+ esac
+}
+
+desc_of() {
+ case $1 in
+ SPS) printf '%s\n' 'Source Package System. Installer and live ISO builder.' ;;
+ sps-core) printf '%s\n' 'Official base recipe collection.' ;;
+ sps-extra) printf '%s\n' 'Official extra recipe collection.' ;;
+ splux-site) printf '%s\n' 'This website. Static HTML from the recipe trees.' ;;
+ *) printf '%s\n' "$1" ;;
+ esac
+}
+
+mkdir -p "$OUT/git" "$OUT/data"
+
+index_rows=$OUT/data/git-index.tsv
+: >"$index_rows"
+
+build_repo() {
+ name=$1
+ dir=$2
+ is_git "$dir" || return 0
+
+ gh=$(github_of "$name")
+ repo_desc=$(desc_of "$name")
+ head=$(git -C "$dir" rev-parse HEAD)
+ short=$(git -C "$dir" rev-parse --short HEAD)
+ branch=$(git -C "$dir" rev-parse --abbrev-ref HEAD 2>/dev/null || printf '%s\n' HEAD)
+ lastiso=$(git -C "$dir" log -1 --format='%cI')
+ ncommits=$(git -C "$dir" rev-list --count HEAD)
+ nfiles=$(git -C "$dir" ls-tree -r --name-only HEAD | wc -l)
+ nfiles=$(printf '%s' "$nfiles" | tr -d ' ')
+
+ base=$OUT/git/$name
+ mkdir -p "$base/log" "$base/refs" "$base/tree" "$base/commit" "$base/blob"
+
+ # Language counts by blob size at HEAD.
+ langtmp=$base/.langs.tsv
+ : >"$langtmp"
+ git -C "$dir" ls-tree -r -l HEAD | while IFS= read -r line
+ do
+ # 100644 blob HASH SIZE PATH
+ set -- $line
+ mode=$1
+ kind=$2
+ obj=$3
+ sz=$4
+ shift 4
+ path=$*
+ [ "$kind" = blob ] || continue
+ [ -n "$path" ] || continue
+ lang=$(lang_of "$path")
+ printf '%s\t%s\n' "$lang" "$sz"
+ done | awk -F '\t' '
+ { b[$1] += $2 + 0 }
+ END {
+ for (k in b)
+ print k "\t" b[k]
+ }
+ ' | LC_ALL=C sort -t "$(printf '\t')" -k2,2nr >"$langtmp"
+
+ # Commits
+ clog=$base/.commits.tsv
+ git -C "$dir" log --format='%H%x09%h%x09%ct%x09%cI%x09%an%x09%s' |
+ awk -F '\t' 'BEGIN { OFS="\t" } {
+ subj=$6
+ for (i = 7; i <= NF; i++) subj = subj " " $i
+ gsub(/\t/, " ", subj)
+ print $1, $2, $3, $4, subj, $5
+ }' >"$clog"
+
+ # Repo home
+ page_begin "$base/index.html" "$name - Splux Git" "$repo_desc"
+ {
+ printf '<h2>%s</h2>\n' "$(esc "$name")"
+ printf '%s\n' '<hr class="rule">'
+ printf '<p>%s</p>\n' "$(esc "$repo_desc")"
+ printf '%s\n' '<p class="git-nav">'
+ printf '<a href="log/">log</a> · <a href="tree/">files</a> · <a href="refs/">refs</a> · '
+ printf '<a href="%s">GitHub mirror</a>\n' "$(esc "$gh")"
+ printf '%s\n' '</p>'
+ printf '%s\n' '<div class="info">'
+ printf '<div class="dl-row"><span class="muted">HEAD</span><span><a href="commit/%s/"><code>%s</code></a> (%s)</span></div>\n' \
+ "$(esc "$head")" "$(esc "$short")" "$(esc "$branch")"
+ printf '<div class="dl-row"><span class="muted">Commits</span><span>%s</span></div>\n' \
+ "$(esc "$ncommits")"
+ printf '<div class="dl-row"><span class="muted">Files</span><span>%s</span></div>\n' \
+ "$(esc "$nfiles")"
+ printf '<div class="dl-row"><span class="muted">Clone</span><span><code>git clone %s.git</code></span></div>\n' \
+ "$(esc "$gh")"
+ printf '%s\n' '</div>'
+ if [ -s "$langtmp" ]; then
+ printf '%s\n' '<h3>Languages</h3>'
+ awk -f "$AWK" -v mode=langs "$langtmp"
+ fi
+ printf '%s\n' '<h3>Recent commits</h3>'
+ awk -f "$AWK" -v mode=commits -v commitpfx="commit/" -v limit=20 "$clog"
+ printf '%s\n' '<p><a href="log/">Full log</a></p>'
+ if git -C "$dir" cat-file -e HEAD:README.md 2>/dev/null; then
+ printf '%s\n' '<h3>README.md</h3>'
+ git -C "$dir" show HEAD:README.md | awk -f "$AWK" -v mode=pre
+ elif git -C "$dir" cat-file -e HEAD:README 2>/dev/null; then
+ printf '%s\n' '<h3>README</h3>'
+ git -C "$dir" show HEAD:README | awk -f "$AWK" -v mode=pre
+ fi
+ } >>"$base/index.html"
+ page_end "$base/index.html"
+
+ # Full log
+ page_begin "$base/log/index.html" "Log - $name - Splux Git" "Commit log for $name"
+ {
+ printf '<p class="git-nav"><a href="../">%s</a> · log</p>\n' "$(esc "$name")"
+ printf '<h2>Log</h2>\n'
+ printf '%s\n' '<hr class="rule">'
+ awk -f "$AWK" -v mode=commits -v commitpfx="../commit/" "$clog"
+ } >>"$base/log/index.html"
+ page_end "$base/log/index.html"
+
+ # Refs
+ page_begin "$base/refs/index.html" "Refs - $name - Splux Git" "Branches and tags for $name"
+ {
+ printf '<p class="git-nav"><a href="../">%s</a> · refs</p>\n' "$(esc "$name")"
+ printf '<h2>Refs</h2>\n'
+ printf '%s\n' '<hr class="rule">'
+ printf '%s\n' '<h3>Branches</h3>'
+ printf '%s\n' '<ul class="plain">'
+ git -C "$dir" for-each-ref --format='%(objectname) %(refname:short)' refs/heads |
+ while IFS= read -r line
+ do
+ [ -n "$line" ] || continue
+ h=${line%% *}
+ r=${line#* }
+ printf '<li><a href="../commit/%s/">%s</a> <code>%s</code></li>\n' \
+ "$(esc "$h")" "$(esc "$r")" "$(esc "${h%"${h#???????}"}")"
+ done
+ printf '%s\n' '</ul>'
+ printf '%s\n' '<h3>Tags</h3>'
+ printf '%s\n' '<ul class="plain">'
+ ntags=0
+ git -C "$dir" for-each-ref --format='%(objectname) %(refname:short)' refs/tags |
+ while IFS= read -r line
+ do
+ [ -n "$line" ] || continue
+ h=${line%% *}
+ r=${line#* }
+ # Peel annotated tags to the commit when possible.
+ c=$(git -C "$dir" rev-parse "$r^{commit}" 2>/dev/null || printf '%s\n' "$h")
+ printf '<li><a href="../commit/%s/">%s</a></li>\n' \
+ "$(esc "$c")" "$(esc "$r")"
+ ntags=1
+ done
+ if [ "$ntags" = 0 ]; then
+ :
+ fi
+ printf '%s\n' '</ul>'
+ } >>"$base/refs/index.html"
+ page_end "$base/refs/index.html"
+
+ # Commits
+ while IFS="$(printf '\t')" read -r hash shortc epoch iso subject author || [ -n "${hash-}" ]
+ do
+ [ -n "${hash-}" ] || continue
+ cdir=$base/commit/$hash
+ mkdir -p "$cdir"
+ page_begin "$cdir/index.html" "$shortc - $name - Splux Git" "$subject"
+ {
+ printf '<p class="git-nav"><a href="../../">%s</a> · <a href="../../log/">log</a> · commit</p>\n' \
+ "$(esc "$name")"
+ printf '<h2><code>%s</code></h2>\n' "$(esc "$shortc")"
+ printf '%s\n' '<hr class="rule">'
+ printf '<p>%s</p>\n' "$(esc "$subject")"
+ printf '%s\n' '<div class="info">'
+ printf '<div class="dl-row"><span class="muted">Author</span><span>%s</span></div>\n' \
+ "$(esc "$author")"
+ printf '<div class="dl-row"><span class="muted">Date</span><span><time datetime="%s">%s</time></span></div>\n' \
+ "$(esc "$iso")" "$(esc "$iso")"
+ printf '<div class="dl-row"><span class="muted">Commit</span><span><code>%s</code></span></div>\n' \
+ "$(esc "$hash")"
+ printf '<div class="dl-row"><span class="muted">GitHub</span><span><a href="%s/commit/%s">mirror</a></span></div>\n' \
+ "$(esc "$gh")" "$(esc "$hash")"
+ printf '%s\n' '</div>'
+ printf '%s\n' '<h3>Parents</h3>'
+ printf '%s\n' '<ul class="plain">'
+ git -C "$dir" rev-list --parents -n 1 "$hash" | {
+ read -r self rest || rest=
+ for p in $rest
+ do
+ ps=$(git -C "$dir" rev-parse --short "$p")
+ printf '<li><a href="../%s/"><code>%s</code></a></li>\n' \
+ "$(esc "$p")" "$(esc "$ps")"
+ done
+ }
+ printf '%s\n' '</ul>'
+ printf '%s\n' '<h3>Stat</h3>'
+ git -C "$dir" show --stat --format= "$hash" | awk -f "$AWK" -v mode=pre
+ printf '%s\n' '<h3>Diff</h3>'
+ # Truncate huge diffs so the Pages artifact stays small.
+ git -C "$dir" show --format= --color=never "$hash" |
+ dd bs=1024 count=300 2>/dev/null |
+ awk -f "$AWK" -v mode=pre
+ } >>"$cdir/index.html"
+ page_end "$cdir/index.html"
+ if [ -n "$shortc" ] && [ "$shortc" != "$hash" ]; then
+ write_redirect "$base/commit/$shortc/index.html" "../$hash/"
+ fi
+ done <"$clog"
+
+ # Trees and blobs at HEAD
+ write_tree() {
+ treepath=${1-}
+ if [ -n "$treepath" ]; then
+ tdest=$base/tree/$treepath/index.html
+ title="$treepath - $name - Splux Git"
+ else
+ tdest=$base/tree/index.html
+ title="Files - $name - Splux Git"
+ fi
+ if [ -z "$treepath" ]; then
+ up_repo="../"
+ blobpfx="../blob/"
+ treepfx="./"
+ else
+ depth=1
+ rest=$treepath
+ while [ "$rest" != "${rest#*/}" ]
+ do
+ depth=$((depth + 1))
+ rest=${rest#*/}
+ done
+ up=""
+ j=0
+ while [ "$j" -le "$depth" ]
+ do
+ up="../$up"
+ j=$((j + 1))
+ done
+ up_repo=$up
+ blobpfx=$up"blob/"
+ treepfx="./"
+ fi
+ page_begin "$tdest" "$title" "HEAD tree for $name"
+ {
+ printf '<p class="git-nav"><a href="%s">%s</a> · files</p>\n' \
+ "$(esc "$up_repo")" "$(esc "$name")"
+ if [ -n "$treepath" ]; then
+ printf '<h2>%s</h2>\n' "$(esc "$treepath")"
+ else
+ printf '%s\n' '<h2>Files</h2>'
+ fi
+ printf '%s\n' '<hr class="rule">'
+ if [ -n "$treepath" ]; then
+ printf '<p><a href="../">../</a></p>\n'
+ fi
+ printf '%s\n' '<p><label for="git-filter">Filter</label> <input id="git-filter" type="search" placeholder="file"></p>'
+ ent=$base/.entries.tsv
+ : >"$ent"
+ if [ -n "$treepath" ]; then
+ git -C "$dir" ls-tree -l "HEAD:$treepath"
+ else
+ git -C "$dir" ls-tree -l HEAD
+ fi | while IFS= read -r line
+ do
+ set -- $line
+ [ $# -ge 5 ] || continue
+ kind=$2
+ sz=$4
+ shift 4
+ path=$*
+ basepath=${path##*/}
+ [ -n "$basepath" ] || continue
+ if [ "$kind" = tree ]; then
+ printf 'dir\t\t%s\t%s\n' "$basepath/" "$treepfx$basepath/"
+ elif [ "$kind" = blob ]; then
+ if [ -n "$treepath" ]; then
+ fullpath=$treepath/$basepath
+ else
+ fullpath=$basepath
+ fi
+ printf 'file\t%s\t%s\t%s\n' "$sz" "$basepath" "$blobpfx$fullpath/"
+ fi
+ done >"$ent"
+ if [ -s "$ent" ]; then
+ awk -f "$AWK" -v mode=entries "$ent"
+ else
+ printf '%s\n' '<p class="muted">empty directory</p>'
+ fi
+ } >>"$tdest"
+ page_end "$tdest" gitjs
+ }
+
+ write_tree ""
+ # Every directory that contains a blob.
+ git -C "$dir" ls-tree -r -d --name-only HEAD | while IFS= read -r d
+ do
+ [ -n "$d" ] || continue
+ write_tree "$d"
+ done
+
+ git -C "$dir" ls-tree -r -l HEAD | while IFS= read -r line
+ do
+ set -- $line
+ [ "$2" = blob ] || continue
+ sz=$4
+ obj=$3
+ shift 4
+ path=$*
+ [ -n "$path" ] || continue
+ bdest=$base/blob/$path/index.html
+ page_begin "$bdest" "$path - $name - Splux Git" "$path at HEAD"
+ parent=${path%/*}
+ # depth of blob/path/...
+ depth=1
+ rest=$path
+ while [ "$rest" != "${rest#*/}" ]
+ do
+ depth=$((depth + 1))
+ rest=${rest#*/}
+ done
+ up=""
+ j=0
+ while [ "$j" -le "$depth" ]
+ do
+ up="../$up"
+ j=$((j + 1))
+ done
+ # blob/a/b -> up is ../../../ (blob + a + b) = depth+1, plus we started le depth so depth+1. Good.
+ {
+ if [ "$parent" = "$path" ]; then
+ dirhref="${up}tree/"
+ else
+ dirhref="${up}tree/${parent}/"
+ fi
+ printf '<p class="git-nav"><a href="%s">%s</a> · <a href="%s">directory</a></p>\n' \
+ "$(esc "$up")" "$(esc "$name")" "$(esc "$dirhref")"
+ printf '<h2>%s</h2>\n' "$(esc "$path")"
+ printf '%s\n' '<hr class="rule">'
+ printf '<p class="muted">%s bytes at <a href="%scommit/%s/">%s</a> · <a href="%s/blob/main/%s">GitHub</a></p>\n' \
+ "$(esc "$sz")" "$(esc "$up")" "$(esc "$head")" "$(esc "$short")" \
+ "$(esc "$gh")" "$(esc "$path")"
+ szn=$(printf '%s' "$sz" | tr -d ' ')
+ case $szn in
+ ''|*[!0-9]*) szn=0 ;;
+ esac
+ if is_binary_name "$path"; then
+ printf '%s\n' '<p>Binary file. Clone the repository or open the GitHub mirror.</p>'
+ elif [ "$szn" -gt "$MAXBLOB" ]; then
+ printf '%s\n' '<p>File is too large to embed here. Clone the repository or open the GitHub mirror.</p>'
+ else
+ git -C "$dir" cat-file blob "$obj" | awk -f "$AWK" -v mode=pre
+ fi
+ } >>"$bdest"
+ page_end "$bdest"
+ done
+
+ day=${lastiso%%T*}
+ printf '%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\n' \
+ "$name" "$repo_desc" "$short" "$head" "$ncommits" "$nfiles" "$day" "$gh" \
+ >>"$index_rows"
+
+ rm -f "$langtmp" "$clog" "$base/.entries.tsv"
+ printf '%s\n' "git: $name ($ncommits commits, $nfiles files)" >&2
+}
+
+build_repo SPS "$SPS"
+build_repo sps-core "$CORE"
+build_repo sps-extra "$EXTRA"
+build_repo splux-site "$SITE"
+
+# Index
+page_begin "$OUT/git/index.html" "Git - Splux Linux" "Static browse of the official Splux git trees."
+{
+ printf '%s\n' '<h2>Git</h2>'
+ printf '%s\n' '<hr class="rule">'
+ printf '%s\n' '<p>This is a static browse of the official trees, rebuilt with the handbook. There is no git server here: no accounts, no pull requests, and no <code>git clone</code> from this host. Clone the GitHub mirrors. The commits, files, and language counts on these pages are the same history.</p>'
+ printf '%s\n' '<p><label for="git-filter">Filter</label> <input id="git-filter" type="search" placeholder="repository"></p>'
+ printf '%s\n' '<table class="pkgs" id="git-repos">'
+ printf '%s\n' '<thead><tr><th>Repository</th><th>Description</th><th>HEAD</th><th>Commits</th><th>Updated</th></tr></thead>'
+ printf '%s\n' '<tbody>'
+ if [ -s "$index_rows" ]; then
+ while IFS="$(printf '\t')" read -r name desc short head ncommits nfiles day gh || [ -n "${name-}" ]
+ do
+ [ -n "${name-}" ] || continue
+ printf '<tr data-repo="%s" data-search="%s %s">' \
+ "$(esc "$name")" "$(esc "$name")" "$(esc "$desc")"
+ printf '<td><a class="name" href="%s/">%s</a></td>' "$(esc "$name")" "$(esc "$name")"
+ printf '<td>%s</td>' "$(esc "$desc")"
+ printf '<td><a href="%s/commit/%s/"><code>%s</code></a></td>' \
+ "$(esc "$name")" "$(esc "$head")" "$(esc "$short")"
+ printf '<td>%s</td>' "$(esc "$ncommits")"
+ printf '<td>%s</td>' "$(esc "$day")"
+ printf '</tr>\n'
+ done <"$index_rows"
+ fi
+ printf '%s\n' '</tbody></table>'
+ printf '%s\n' '<h3>Clone</h3>'
+ printf '%s\n' '<pre class="block">git clone https://github.com/RobertFlexx/SPS.git'
+ printf '%s\n' 'git clone https://github.com/RobertFlexx/sps-core.git'
+ printf '%s\n' 'git clone https://github.com/RobertFlexx/sps-extra.git'
+ printf '%s\n' 'git clone https://github.com/RobertFlexx/splux-site.git</pre>'
+ printf '%s\n' '<p class="note">Live ISO files stay on GitHub Releases. Recipe browse also lives under <a href="../../../../packages/">packages</a>.</p>'
+} >>"$OUT/git/index.html"
+page_end "$OUT/git/index.html" gitjs
+
+# JSON summary
+awk -F '\t' '
+function jesc(s) {
+ gsub(/\\/, "\\\\", s)
+ gsub(/"/, "\\\"", s)
+ return s
+}
+BEGIN { print "[" }
+{
+ if (NR > 1) print ","
+ printf "{\"name\":\"%s\",\"description\":\"%s\",\"head\":\"%s\",\"full\":\"%s\",\"commits\":%s,\"files\":%s,\"updated\":\"%s\",\"github\":\"%s\"}", \
+ jesc($1), jesc($2), jesc($3), jesc($4), $5 + 0, $6 + 0, jesc($7), jesc($8)
+}
+END { print "\n]" }
+' "$index_rows" >"$OUT/data/git.json"
+
+printf '%s\n' "git: wrote $OUT/git" >&2
diff --git a/tools/build-site.sh b/tools/build-site.sh
index 7f8c5cb..2cb7de2 100755
--- a/tools/build-site.sh
+++ b/tools/build-site.sh
@@ -17,7 +17,7 @@ CORE_GIT=${CORE_GIT:-https://github.com/RobertFlexx/sps-core}
EXTRA_GIT=${EXTRA_GIT:-https://github.com/RobertFlexx/sps-extra}
SPS_GIT=${SPS_GIT:-https://github.com/RobertFlexx/SPS}
SITE_URL=${SITE_URL:-https://splux.robertflexx.dev}
-GIT_HOST=${GIT_HOST:-https://git.splux.robertflexx.dev}
+GIT_HOST=${GIT_HOST:-https://splux.robertflexx.dev/git}
clone_tree() {
url=$1
@@ -69,7 +69,7 @@ write_header() {
<a href="${root}packages/">packages</a>
<a href="${root}install/">install</a>
<a href="${root}docs/">docs</a>
-<a href="${root}git/">git (WIP)</a>
+<a href="${root}git/">git</a>
<a href="${root}source/">source</a>
<a href="${root}news/">news</a>
</nav>
@@ -81,8 +81,8 @@ write_footer() {
cat <<EOF
<footer>
<p>Splux Linux</p>
-<p><a href="${root}">home</a> · <a href="${root}packages/">packages</a> · <a href="${root}git/">git (WIP)</a> · <a href="${root}docs/">documentation</a></p>
-<p>This site was fully handmade by <a href="${GIT_HOST}/RobertFlexx">RobertFlexx</a>.</p>
+<p><a href="${root}">home</a> · <a href="${root}packages/">packages</a> · <a href="${root}git/">git</a> · <a href="${root}docs/">documentation</a></p>
+<p>This site was fully handmade by <a href="https://github.com/RobertFlexx">RobertFlexx</a>.</p>
</footer>
EOF
}
@@ -99,7 +99,7 @@ write_docs_nav() {
install "${root}install/" "Install" \
sps "${root}docs/sps/" "SPS tools" \
firstboot "${root}docs/first-boot/" "After first boot" \
- git "${root}git/" "Git (WIP)"
+ git "${root}git/" "Git"
while [ "$#" -ge 3 ]
do
if [ "$cur" = "$1" ]; then
@@ -149,8 +149,8 @@ scan_tree() {
}
printf '%s\n' "reading recipes" >&2
-scan_tree core "$CORE" "$GIT_HOST/RobertFlexx/sps-core" "https://github.com/RobertFlexx/sps-core"
-scan_tree extra "$EXTRA" "$GIT_HOST/RobertFlexx/sps-extra" "https://github.com/RobertFlexx/sps-extra"
+scan_tree core "$CORE" "$GIT_HOST/sps-core" "https://github.com/RobertFlexx/sps-core"
+scan_tree extra "$EXTRA" "$GIT_HOST/sps-extra" "https://github.com/RobertFlexx/sps-extra"
LC_ALL=C sort -t "$(printf '\t')" -k1,1 -k5,5 "$tsv" >"$tmp/sorted.tsv"
mv "$tmp/sorted.tsv" "$tsv"
@@ -282,9 +282,9 @@ livesig=${site_sha}-$(date -u '+%Y%m%d%H%M%S' 2>/dev/null || date +%Y%m%d%H%M%S)
cat >"$tmp/news-info.html" <<EOF
<div class="info">
<div class="dl-row"><span class="muted">Latest ISO</span><span id="live-iso"><a href="$notes_url">$tag</a> ($date)</span></div>
-<div class="dl-row"><span class="muted">SPS</span><span id="live-sps"><a href="$GIT_HOST/RobertFlexx/SPS/commit/$sps_sha">$sps_sha</a></span></div>
-<div class="dl-row"><span class="muted">sps-core</span><span id="live-core"><a href="$GIT_HOST/RobertFlexx/sps-core/commit/$core_sha">$core_sha</a></span></div>
-<div class="dl-row"><span class="muted">sps-extra</span><span id="live-extra"><a href="$GIT_HOST/RobertFlexx/sps-extra/commit/$extra_sha">$extra_sha</a></span></div>
+<div class="dl-row"><span class="muted">SPS</span><span id="live-sps"><a href="$GIT_HOST/SPS/commit/$sps_sha/">$sps_sha</a></span></div>
+<div class="dl-row"><span class="muted">sps-core</span><span id="live-core"><a href="$GIT_HOST/sps-core/commit/$core_sha/">$core_sha</a></span></div>
+<div class="dl-row"><span class="muted">sps-extra</span><span id="live-extra"><a href="$GIT_HOST/sps-extra/commit/$extra_sha/">$extra_sha</a></span></div>
<div class="dl-row"><span class="muted">Packages</span><span>$npkgs ($ncore core, $nextra extra)</span></div>
<div class="dl-row"><span class="muted">Site build</span><span>$generated ($site_sha)</span></div>
</div>
@@ -332,7 +332,50 @@ subst site/docs/images/index.html "$OUT/docs/images/index.html" "../../" images
subst site/docs/sps/index.html "$OUT/docs/sps/index.html" "../../" sps
subst site/docs/first-boot/index.html "$OUT/docs/first-boot/index.html" "../../" firstboot
subst site/source/index.html "$OUT/source/index.html" "../"
-subst site/git/index.html "$OUT/git/index.html" "../"
+
+export OUT CORE EXTRA SPS SITE GIT_HOST SITE_URL
+sh tools/build-git.sh
+find "$OUT/git" -name index.html >"$tmp/gitpages"
+while IFS= read -r page
+do
+ [ -n "$page" ] || continue
+ rel=${page#"$OUT"/}
+ depth=0
+ rest=$rel
+ while [ "$rest" != "${rest#*/}" ]
+ do
+ depth=$((depth + 1))
+ rest=${rest#*/}
+ done
+ root=""
+ i=0
+ while [ "$i" -lt "$depth" ]
+ do
+ root="../$root"
+ i=$((i + 1))
+ done
+ write_header "$root" >"$tmp/hgit.html"
+ write_footer "$root" >"$tmp/fgit.html"
+ awk -f tools/subst.awk \
+ -v headerfile="$tmp/hgit.html" \
+ -v footerfile="$tmp/fgit.html" \
+ -v rowsfile="" \
+ -v newsfile="" \
+ -v brieffile="" \
+ -v infofile="" \
+ -v root="$root" \
+ -v tag="$tag" \
+ -v date="$date" \
+ -v npkgs="$npkgs" \
+ -v ncore="$ncore" \
+ -v nextra="$nextra" \
+ -v generated="$generated" \
+ -v livesig="$livesig" \
+ -v curlver="$curlver" \
+ -v githost="$GIT_HOST" \
+ "$page" >"$tmp/gpage.html"
+ mv "$tmp/gpage.html" "$page"
+done <"$tmp/gitpages"
awk -f tools/news.awk -v mode=html -v page=1 -v per="$news_per" \
"$tmp/news.tsv" >"$tmp/news.html"
diff --git a/tools/collect-news.sh b/tools/collect-news.sh
index a42c44f..0b6dfd7 100755
--- a/tools/collect-news.sh
+++ b/tools/collect-news.sh
@@ -13,7 +13,7 @@ CORE=${CORE:-vendor/core}
EXTRA=${EXTRA:-vendor/extra}
SPS=${SPS:-vendor/sps}
SITE=${SITE:-.}
-GIT_HOST=${GIT_HOST:-https://git.splux.robertflexx.dev}
+GIT_HOST=${GIT_HOST:-https://splux.robertflexx.dev/git}
GIT_HOST=${GIT_HOST%/}
tab=$(printf '\t')
@@ -84,7 +84,7 @@ git_commits() {
[ -n "${iso-}" ] || continue
[ -n "${hash-}" ] || continue
emit "$epoch" "$iso" commit "$repo" \
- "$baseurl/commit/$hash" "$subject" "" "$author" "" \
+ "$baseurl/commit/$hash/" "$subject" "" "$author" "" \
"$(github_avatar "$author")"
done
}
@@ -103,10 +103,10 @@ read_commit_tsv() {
done <"$file"
}
-git_commits "$SPS" SPS "$GIT_HOST/RobertFlexx/SPS"
-git_commits "$CORE" sps-core "$GIT_HOST/RobertFlexx/sps-core"
-git_commits "$EXTRA" sps-extra "$GIT_HOST/RobertFlexx/sps-extra"
-git_commits "$SITE" splux-site "$GIT_HOST/RobertFlexx/splux-site"
+git_commits "$SPS" SPS "$GIT_HOST/SPS"
+git_commits "$CORE" sps-core "$GIT_HOST/sps-core"
+git_commits "$EXTRA" sps-extra "$GIT_HOST/sps-extra"
+git_commits "$SITE" splux-site "$GIT_HOST/splux-site"
if command -v gh >/dev/null 2>&1; then
if gh api --paginate "repos/RobertFlexx/SPS/releases?per_page=100" --jq \
@@ -137,7 +137,7 @@ if command -v gh >/dev/null 2>&1; then
if gh api --paginate "repos/${path}/commits?per_page=100" --jq \
'.[] | [
.commit.committer.date,
- ("'"$GIT_HOST"'/'"$path"'/commit/" + .sha),
+ ("'"$GIT_HOST"'/'"$label"'/commit/" + .sha + "/"),
((.commit.message // "") | split("\n")[0] | gsub("[\r\t]"; " ")),
((.author.login // .commit.author.name // "") | gsub("[\r\t]"; " ")),
(if .commit.verification.verified == true then "yes" else "no" end),
diff --git a/tools/git.awk b/tools/git.awk
new file mode 100644
index 0000000..388597e
--- /dev/null
+++ b/tools/git.awk
@@ -0,0 +1,132 @@
+# HTML fragments for the static Splux Git browser.
+# mode=one escape $0 (or -v text=) as one HTML string
+# mode=pre escape stdin as a <pre class="block git-blob">
+# mode=langs TSV lang<TAB>bytes -> bar plus list
+# mode=commits TSV hash short epoch iso subject author
+# -v commitpfx= relative prefix ending in commit/
+# mode=entries TSV kind size name href (kind=dir|file)
+
+function esc(s) {
+ gsub(/&/, "\\&", s)
+ gsub(/</, "\\<", s)
+ gsub(/>/, "\\>", s)
+ gsub(/"/, "\\"", s)
+ return s
+}
+
+function pct(n, d) {
+ if (d <= 0)
+ return 0
+ return int((n * 1000) / d) / 10
+}
+
+BEGIN {
+ FS = "\t"
+ limit = limit + 0
+ if (mode == "one") {
+ if (text != "")
+ printf "%s", esc(text)
+ else {
+ while ((getline line) > 0)
+ printf "%s", esc(line)
+ }
+ exit
+ }
+}
+
+mode == "pre" {
+ if (!opened) {
+ print "<pre class=\"block git-blob\">"
+ opened = 1
+ }
+ print esc($0)
+}
+
+mode == "langs" {
+ n++
+ lang[n] = $1
+ bytes[n] = $2 + 0
+ total += bytes[n]
+}
+
+mode == "commits" {
+ if (limit > 0 && n >= limit)
+ next
+ n++
+ hash[n] = $1
+ short[n] = $2
+ iso[n] = $4
+ subject[n] = $5
+ author[n] = $6
+}
+
+mode == "entries" {
+ n++
+ kind[n] = $1
+ size[n] = $2
+ name[n] = $3
+ href[n] = $4
+}
+
+END {
+ if (mode == "pre") {
+ if (!opened)
+ print "<pre class=\"block git-blob\"></pre>"
+ else
+ print "</pre>"
+ exit
+ }
+ if (mode == "langs") {
+ if (n < 1)
+ exit
+ print "<div class=\"lang-bar\" role=\"img\" aria-label=\"Languages\">"
+ for (i = 1; i <= n; i++) {
+ w = pct(bytes[i], total)
+ if (w <= 0 && bytes[i] > 0)
+ w = 0.1
+ printf "<span class=\"lang-seg\" style=\"width:%s%%\" title=\"%s %s%%\"></span>\n", \
+ w, esc(lang[i]), w
+ }
+ print "</div>"
+ print "<ul class=\"lang-list\">"
+ for (i = 1; i <= n; i++)
+ printf "<li>%s <span class=\"muted\">%s%%</span></li>\n", \
+ esc(lang[i]), pct(bytes[i], total)
+ print "</ul>"
+ exit
+ }
+ if (mode == "commits") {
+ print "<table class=\"pkgs git-log\">"
+ print "<thead><tr><th>Commit</th><th>Subject</th><th>Author</th><th>When</th></tr></thead>"
+ print "<tbody>"
+ for (i = 1; i <= n; i++) {
+ href = commitpfx esc(hash[i]) "/"
+ day = iso[i]
+ sub(/T.*/, "", day)
+ printf "<tr>"
+ printf "<td><a href=\"%s\"><code>%s</code></a></td>", href, esc(short[i])
+ printf "<td><a href=\"%s\">%s</a></td>", href, esc(subject[i])
+ printf "<td>%s</td>", esc(author[i])
+ printf "<td><time datetime=\"%s\">%s</time></td>", esc(iso[i]), esc(day)
+ print "</tr>"
+ }
+ print "</tbody></table>"
+ exit
+ }
+ if (mode == "entries") {
+ print "<table class=\"pkgs git-tree\">"
+ print "<thead><tr><th></th><th>Name</th><th>Size</th></tr></thead>"
+ print "<tbody>"
+ for (i = 1; i <= n; i++) {
+ label = kind[i] == "dir" ? "dir" : "file"
+ sz = kind[i] == "dir" ? "" : size[i]
+ printf "<tr data-search=\"%s\">", esc(tolower(name[i]))
+ printf "<td class=\"muted\">%s</td>", label
+ printf "<td><a href=\"%s\">%s</a></td>", esc(href[i]), esc(name[i])
+ printf "<td class=\"muted\">%s</td>", esc(sz)
+ print "</tr>"
+ }
+ print "</tbody></table>"
+ exit
+ }
+}
diff --git a/tools/packages.awk b/tools/packages.awk
index 56d92df..84215e9 100644
--- a/tools/packages.awk
+++ b/tools/packages.awk
@@ -145,9 +145,9 @@ function write_page( dir, ncomp, i, prefix, parts, cat, page, gh_dir) {
print "<a href=\"" github "/tree/main/" gh_dir "\">repository directory</a><br>" > page
print "<a href=\"" github "/commits/main/" gh_dir "\">history</a>" > page
} else {
- print "<a href=\"" github "/src/branch/main/" gh_dir "/recipe\">view recipe</a><br>" > page
- print "<a href=\"" github "/src/branch/main/" gh_dir "\">repository directory</a><br>" > page
- print "<a href=\"" github "/commits/branch/main/" gh_dir "\">history</a>" > page
+ print "<a href=\"" github "/blob/" gh_dir "/recipe/\">view recipe</a><br>" > page
+ print "<a href=\"" github "/tree/" gh_dir "/\">repository directory</a><br>" > page
+ print "<a href=\"" github "/log/\">history</a>" > page
}
if (mirror != "") {
print "<br>" > page
@@ -162,7 +162,7 @@ function write_page( dir, ncomp, i, prefix, parts, cat, page, gh_dir) {
BEGIN {
if (repo == "") repo = "unknown"
- if (github == "") github = "https://git.splux.robertflexx.dev/RobertFlexx/sps-core"
+ if (github == "") github = "https://splux.robertflexx.dev/git/sps-core"
if (pkgpath == "") pkgpath = "unknown"
}
diff --git a/tools/subst.awk b/tools/subst.awk
index eb37dc2..03c2b0e 100644
--- a/tools/subst.awk
+++ b/tools/subst.awk
@@ -21,7 +21,7 @@ BEGIN {
close(footerfile)
}
if (githost == "")
- githost = "https://git.splux.robertflexx.dev"
+ githost = "https://splux.robertflexx.dev/git"
}
$0 == "@@HEADER@@" {