upleb.uk

Public git repos — served from a NIP-34 GRASP relay at git.upleb.uk

summaryrefslogtreecommitdiff
path: root/src/main.rs
diff options
context:
space:
mode:
authorDanConwayDev <DanConwayDev@protonmail.com>2026-04-10 19:26:23 +0000
committerDanConwayDev <DanConwayDev@protonmail.com>2026-04-10 19:26:23 +0000
commit8aef478c6b1e9e3f6ebbad6d57f59f1a84a261ea (patch)
tree2aa56188b13fc4b8e6a2fdf302dea19afb65a5a7 /src/main.rs
parent2161e3c0a8169a85111cd6dc01ffe2b0fed1493f (diff)
feat: add cleanup-empty-repos subcommand to remove stale events for empty git repos
Adds a maintenance subcommand that scans the LMDB database for kind 30617 (repository announcement) events whose bare git repo on disk is empty or missing, then removes both the 30617 and any matching 30618 (state) events. A relay should not serve announcement or state events for a repository with no git data. This was needed to clean up repos leaked by the bug fixed in 2161e3c, and is useful as an ongoing maintenance tool. Usage (dry-run by default, stop relay before --execute): ngit-grasp cleanup-empty-repos [--relay-data-path <path>] [--git-data-path <path>] [--execute] The relay itself is now invoked as an implicit 'serve' subcommand, preserving full backward compatibility with existing deployments and env-var configuration.
Diffstat (limited to 'src/main.rs')
-rw-r--r--src/main.rs57
1 files changed, 55 insertions, 2 deletions
diff --git a/src/main.rs b/src/main.rs
index 12a875c..bc77fcb 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -2,12 +2,14 @@ use std::time::Duration;
2use std::{path::PathBuf, sync::Arc}; 2use std::{path::PathBuf, sync::Arc};
3 3
4use anyhow::Result; 4use anyhow::Result;
5use clap::Parser;
5use tokio::signal; 6use tokio::signal;
6use tracing::{error, info, warn}; 7use tracing::{error, info, warn};
7use tracing_subscriber::{EnvFilter, FmtSubscriber}; 8use tracing_subscriber::{EnvFilter, FmtSubscriber};
8 9
9use ngit_grasp::{ 10use ngit_grasp::{
10 audit_cleanup, 11 audit_cleanup,
12 cleanup_empty_repos,
11 config::{Config, DatabaseBackend}, 13 config::{Config, DatabaseBackend},
12 git, http, 14 git, http,
13 metrics::Metrics, 15 metrics::Metrics,
@@ -16,10 +18,61 @@ use ngit_grasp::{
16 sync::{naughty_list::NaughtyListTracker, SyncManager}, 18 sync::{naughty_list::NaughtyListTracker, SyncManager},
17}; 19};
18 20
21/// Top-level CLI dispatcher.
22///
23/// With no subcommand the binary runs the relay (all relay flags apply).
24/// With a subcommand it runs the requested maintenance tool instead.
25#[derive(Debug, Parser)]
26#[command(author, version, about = "ngit-grasp GRASP relay", long_about = None)]
27#[command(propagate_version = true)]
28enum Cli {
29 /// Run the GRASP relay server (default when no subcommand is given).
30 #[command(name = "serve")]
31 Serve(Config),
32
33 /// Remove kind 30617/30618 events whose bare git repository is empty or missing.
34 ///
35 /// Runs in dry-run mode by default. Pass --execute to make changes.
36 /// Stop the relay service before running with --execute.
37 CleanupEmptyRepos(cleanup_empty_repos::CleanupArgs),
38}
39
19#[tokio::main] 40#[tokio::main]
20async fn main() -> Result<()> { 41async fn main() -> Result<()> {
21 // Load configuration first (priority: CLI flags > env vars > .env file > defaults) 42 // Load .env file before clap parses, so env vars are available.
22 let config = Config::load()?; 43 dotenvy::dotenv().ok();
44
45 // Peek at argv[1] to decide whether a subcommand was explicitly provided.
46 // If not, prepend the implicit "serve" subcommand so that clap routes to Cli::Serve
47 // and all relay flags are parsed normally (preserving backward compatibility).
48 let mut args: Vec<String> = std::env::args().collect();
49 let known_subcommands = ["serve", "cleanup-empty-repos", "help"];
50 let has_subcommand = args.get(1).map_or(false, |a| {
51 known_subcommands.contains(&a.as_str())
52 || matches!(a.as_str(), "-h" | "--help" | "-V" | "--version")
53 });
54 if !has_subcommand {
55 args.insert(1, "serve".to_string());
56 }
57
58 match Cli::parse_from(args) {
59 Cli::CleanupEmptyRepos(cleanup_args) => {
60 cleanup_empty_repos::run(&cleanup_args).await
61 }
62 Cli::Serve(mut config) => {
63 // Finish initialising the Config (load relay owner key if not provided).
64 if config.relay_owner_nsec.is_none() {
65 config.relay_owner_nsec = Some(Config::load_or_generate_relay_owner_key()?);
66 } else {
67 config.relay_owner_nsec =
68 config.relay_owner_nsec.take().map(|s| s.trim().to_string());
69 }
70 run_relay(config).await
71 }
72 }
73}
74
75async fn run_relay(config: Config) -> Result<()> {
23 76
24 // Initialize tracing with configured log level 77 // Initialize tracing with configured log level
25 let subscriber = FmtSubscriber::builder() 78 let subscriber = FmtSubscriber::builder()