@echo "Listing certificates..."
sudo certbot certificates
endif
+
+.PHONY: gitweb/set-owner
+gitweb/set-owner: ##H @Local Set gitweb.owner for all repos (usage: make gitweb/set-owner OWNER="Shane")
+ifndef OWNER
+ $(error OWNER is undefined. Usage: make gitweb/set-owner OWNER="Shane")
+endif
+ifdef SUDO_USER
+ @echo "Setting owner as $(SUDO_USER)..."
+ su -P $(SUDO_USER) -c "bash scripts/set_gitweb_owner.sh '$(OWNER)'"
+else
+ @echo "Setting owner..."
+ bash scripts/set_gitweb_owner.sh "$(OWNER)"
+endif
+
+.PHONY: gitweb/update-metadata
+gitweb/update-metadata: ##H @Local Bulk update repo metadata from CSV (usage: make gitweb/update-metadata CSV=repo_metadata.csv)
+ @echo "Updating repository metadata..."
+ifdef SUDO_USER
+ @# Run as SUDO_USER (usually gg) to have permission to write to git repos
+ su -P $(SUDO_USER) -c "python3 scripts/update_repo_metadata.py $(or $(CSV),repo_metadata.csv)"
+else
+ python3 scripts/update_repo_metadata.py $(or $(CSV),repo_metadata.csv)
+endif
--- /dev/null
+#!/bin/bash
+set -e
+
+OWNER="$1"
+PROJECT_ROOT="/srv/git/projects"
+
+if [ -z "$OWNER" ]; then
+ echo "Usage: $0 \"Owner Name\""
+ exit 1
+fi
+
+if [ ! -d "$PROJECT_ROOT" ]; then
+ echo "Error: Directory $PROJECT_ROOT not found."
+ exit 1
+fi
+
+echo "Setting 'gitweb.owner' to '$OWNER' for all repos in $PROJECT_ROOT..."
+
+# Iterate over directories ending in .git
+find "$PROJECT_ROOT" -name "*.git" -type d | while read -r repo; do
+ if [ -f "$repo/config" ]; then
+ echo "Updating $repo..."
+ git config --file "$repo/config" gitweb.owner "$OWNER"
+ else
+ echo "Skipping $repo (no config file found)"
+ fi
+done
+
+echo "Done."
--- /dev/null
+#!/usr/bin/env python3
+import csv
+import os
+import subprocess
+import sys
+
+# Default to repo_metadata.csv in the current directory if not provided
+CSV_FILE = sys.argv[1] if len(sys.argv) > 1 else "repo_metadata.csv"
+GIT_ROOT = "/srv/git"
+
+
+def main():
+ if not os.path.exists(CSV_FILE):
+ print(f"Error: CSV file '{CSV_FILE}' not found.")
+ sys.exit(1)
+
+ print(f"Reading metadata from {CSV_FILE}...")
+
+ with open(CSV_FILE, mode="r", newline="", encoding="utf-8") as f:
+ reader = csv.DictReader(f)
+
+ # Normalize column names (strip whitespace)
+ reader.fieldnames = [name.strip() for name in reader.fieldnames]
+
+ if "repo_path" not in reader.fieldnames:
+ print("Error: CSV must have a 'repo_path' column.")
+ sys.exit(1)
+
+ for row in reader:
+ repo_rel_path = row["repo_path"].strip()
+ owner = row.get("owner", "").strip()
+ description = row.get("description", "").strip()
+
+ if not repo_rel_path:
+ continue
+
+ full_repo_path = os.path.join(GIT_ROOT, repo_rel_path)
+
+ if not os.path.isdir(full_repo_path):
+ print(
+ f"Skipping {repo_rel_path}: Not found directly at {full_repo_path}"
+ )
+ # Try prepending projects/ if not present, just in case user omitted it
+ if not repo_rel_path.startswith("projects/"):
+ alt_path = os.path.join(GIT_ROOT, "projects", repo_rel_path)
+ if os.path.isdir(alt_path):
+ full_repo_path = alt_path
+ print(f"Found at {full_repo_path}")
+ else:
+ continue
+ else:
+ continue
+
+ print(f"Updating {repo_rel_path}...")
+
+ # 1. Set Owner (git config gitweb.owner)
+ if owner:
+ config_file = os.path.join(full_repo_path, "config")
+ if os.path.exists(config_file):
+ try:
+ subprocess.run(
+ [
+ "git",
+ "config",
+ "--file",
+ config_file,
+ "gitweb.owner",
+ owner,
+ ],
+ check=True,
+ )
+ print(f" - Owner set to: {owner}")
+ except subprocess.CalledProcessError as e:
+ print(f" - Failed to set owner: {e}")
+ else:
+ print(f" - Warning: No config file found at {config_file}")
+
+ # 2. Set Description (write to description file)
+ if description:
+ desc_file = os.path.join(full_repo_path, "description")
+ try:
+ with open(desc_file, "w", encoding="utf-8") as df:
+ df.write(description + "\n")
+ print(f" - Description updated.")
+ except Exception as e:
+ print(f" - Failed to write description: {e}")
+
+ print("Done.")
+
+
+if __name__ == "__main__":
+ main()