diff options
| author | Leitwolf | 2026-11-13 05:06:08 +0300 |
|---|---|---|
| committer | GitHub | 2026-11-13 05:06:08 +0300 |
| commit | d82258f9f3bb23a0f59d79b984ff527942efc0f0 (patch) | |
| tree | da8b19d9dbe959d85ab60b044295b3c1afb8cc3a /ops/git/git-mirror.sh | |
| parent | 189b15ca0909033a40626bc8f600686e561b9cbb (diff) | |
| parent | f980fee24c5302173fa00ab758b7c54213d2bb7a (diff) | |
| download | progmaweb-content/catalog-without-tala.tar.gz | |
Merge branch 'main' into content/catalog-without-talacontent/catalog-without-tala
Diffstat (limited to 'ops/git/git-mirror.sh')
| -rw-r--r-- | ops/git/git-mirror.sh | 74 |
1 files changed, 74 insertions, 0 deletions
diff --git a/ops/git/git-mirror.sh b/ops/git/git-mirror.sh new file mode 100644 index 0000000..a36f978 --- /dev/null +++ b/ops/git/git-mirror.sh @@ -0,0 +1,74 @@ +#!/bin/sh +# SPDX-FileCopyrightText: 2026 Progmasoft <support@progmasoft.com> +# SPDX-License-Identifier: AGPL-3.0-or-later WITH AdditionRef-Progmasoft-Patent-Grant-1.1 + +# Mirrors the repositories of /etc/git-mirror/repositories from https://github.com/Progmasoft into +# /srv/git/mirrors/<name>.git: branches and tags only, never the pull-request refs of GitHub, with +# what GitHub removed removed here too. Runs as gitmirror from git-mirror.service; installed as +# /usr/local/libexec/git-mirror. +set -eu + +list=${GIT_MIRROR_LIST:-/etc/git-mirror/repositories} +root=${GIT_MIRROR_ROOT:-/srv/git/mirrors} +status=0 + +# A for loop, not a pipe: a pipe would run the loop in a subshell and lose the status. +names=$(grep -Ev '^[[:space:]]*(#|$)' "$list") +for name in $names; do + case "$name" in + *[!A-Za-z0-9._-]* | .* ) echo "git-mirror: skipping the name '$name'" >&2; status=1; continue ;; + esac + repository="$root/$name.git" + if [ ! -d "$repository" ]; then + git init --quiet --bare "$repository.new" + git -C "$repository.new" config remote.origin.url "https://github.com/Progmasoft/$name.git" + git -C "$repository.new" config remote.origin.fetch '+refs/heads/*:refs/heads/*' + git -C "$repository.new" config --add remote.origin.fetch '+refs/tags/*:refs/tags/*' + git -C "$repository.new" config remote.origin.tagOpt --no-tags + git -C "$repository.new" config http.receivepack false + mv "$repository.new" "$repository" + fi + # A clone is served from one pack with a bitmap, so it starts sending at once. + git -C "$repository" config repack.writeBitmaps true + git -C "$repository" config pack.writeBitmapHashCache true + git -C "$repository" config gc.auto 0 + mkdir -p "$repository/info/web" + before=$(git -C "$repository" for-each-ref --format="%(objectname) %(refname)" | sha256sum) + if git -C "$repository" fetch --quiet --prune origin; then + after=$(git -C "$repository" for-each-ref --format="%(objectname) %(refname)" | sha256sum) + if [ "$before" != "$after" ] || [ ! -f "$repository/info/web/repacked" ]; then + git -C "$repository" repack -a -d -b -q + touch "$repository/info/web/repacked" + fi + # HEAD follows the default branch of GitHub; a failed lookup fails the run. + if advertised=$(git -C "$repository" ls-remote --symref origin HEAD); then + head=$(printf '%s\n' "$advertised" | sed -n 's|^ref: refs/heads/\([^[:space:]]*\)[[:space:]]*HEAD$|\1|p') + [ -n "$head" ] && git -C "$repository" symbolic-ref HEAD "refs/heads/$head" + else + echo "git-mirror: the default branch of $name could not be read" >&2 + status=1 + fi + # git-http-backend serves only repositories with this file. + touch "$repository/git-daemon-export-ok" + # cgit shows the age of the last change of a repository from this file. + git -C "$repository" for-each-ref --sort=-committerdate --count=1 \ + --format='%(committerdate:iso8601)' refs/heads > "$repository/info/web/last-modified" + else + echo "git-mirror: fetching $name failed" >&2 + status=1 + fi +done +# A repository no longer listed stops being served at once and is removed. +for repository in "$root"/*.git; do + [ -d "$repository" ] || continue + name=$(basename "$repository" .git) + case " $(printf '%s ' $names)" in + *" $name "*) ;; + *) + rm -f "$repository/git-daemon-export-ok" + rm -rf -- "$repository" + echo "git-mirror: removed $name, which is no longer listed" >&2 + ;; + esac +done +exit "$status" |