caio.co/de/caca

Enable config file support

With a "hidden" `--me` flag so I can still have my yolo single binary
WAN deploy
Id
022ef64b774b8e4bb8d9940f2961ab03e93a9a8a
Author
Caio
Commit time
2024-03-02T14:58:58+01:00

Modified README.md

@@ -15,10 +15,11

# usage

-Configure it by changing the `GlobalConfig` instance within
-[caca/src/main.rs](caca/src/main.rs#L120) then:
+ caca [-c /path/to/config] /path/to/gitroot

- cargo run -- path/to/gitroot
+The (optional) configuration maps a gitconfig/ini file to [a GlobalConfig
+instance](caca/src/config.rs#L13). See [here](caca/src/config.rs#L448) how
+one could look like

You can use the `RUST_LOG` environment variable to configure logging.
The cmdline I tend to use when hacking is something like:

Modified caca/src/config.rs

@@ -355,10 +355,6
}

impl ListenMode {
- pub fn external() -> Self {
- Self::External
- }
-
pub fn addr(addr: &str) -> std::result::Result<Self, AddrParseError> {
let addr = addr.parse()?;
Ok(Self::Bind(BindOptions {

Modified caca/src/main.rs

@@ -73,7 +73,6
)]

use std::{
- num::NonZeroUsize,
path::{Path, PathBuf},
sync::Arc,
};
@@ -103,7 +102,7
mod repo;
mod view;

-use crate::{client::Client, config::GlobalConfig, repo::RepoState, view::Theme};
+use crate::{client::Client, config::GlobalConfig, repo::RepoState};

type Result<T> = std::result::Result<T, Box<dyn std::error::Error>>; // yolo

@@ -117,36 +116,10
)
.init();

- let config = Arc::new(
- GlobalConfig {
- site: config::Site {
- listing_title: String::from("caio's code asylum"),
- listing_html_header: String::from("<h1>caca</h1>"),
- base_url: String::from("http://localhost:42080"),
- clone_base_url: None,
- // to allow mounting caca as a subdirectory
- // when set, a repo url is base_url + reverse_proxy_base + / + name
- reverse_proxy_base: None,
- },
- max_file_size_bytes: 2 * 1024 * 1024,
- rename_similarity_threshold: Some(0.7),
- repo_object_cache_size: 20 * 1024 * 1024,
- metadata_config: config::MetadataConfig::default(),
- global_mailmap: None,
- feed_size: NonZeroUsize::new(40),
- log_size: NonZeroUsize::new(30).unwrap(),
- allow_http_clone: true,
- cache_size: NonZeroUsize::new(1000).unwrap(),
- // theme: Theme::Static,
- theme: Theme::AutoReload("caca/theme".to_string()),
- num_threads: None,
- export_all: true, // false => require git-daemon-export-ok
- listen_mode: config::ListenMode::addr("[::]:42080")?,
- // listen_mode: config::ListenMode::with_admin("[::]:42080", "[::1]:42081")?,
- // listen_mode: config::ListenMode::external(),
- }
- .check()?,
- );
+ let (config, gitroot) = parse_args()?;
+ let config = Arc::new(config);
+
+ let basedir = PathBuf::from(gitroot).canonicalize()?;

// May fiddle with env. keep it early at boot
let (app_listener, admin_listener) = config.listen_mode.to_non_blocking_sockets()?;
@@ -161,9 +134,6
.num_threads(num_threads)
.build()?,
);
-
- let basedir =
- PathBuf::from(std::env::args().nth(1).expect("path as first arg")).canonicalize()?;

let repos = open_repos(basedir.clone(), &pool, Arc::clone(&config))?;
if repos.is_empty() {
@@ -367,4 +337,55

async fn handler(State(client): State<Client>, uri: Uri) -> Response {
client.handle(uri).await
+}
+
+fn parse_args() -> Result<(GlobalConfig, String)> {
+ let mut args = std::env::args().collect::<std::collections::VecDeque<_>>();
+
+ let Some(prog) = args.pop_front() else {
+ return Err("missing argv0".into());
+ };
+
+ macro_rules! usage {
+ () => {
+ format!("usage: {prog} [-c /path/to/config] /path/to/gitroot")
+ };
+ }
+
+ if args
+ .iter()
+ .next()
+ .map_or(true, |a| matches!(a.as_str(), "-h" | "--help"))
+ {
+ return Err(usage!().into());
+ }
+
+ let arg = args.pop_front().expect("checked above: has at least one");
+
+ match arg.as_str() {
+ "-c" | "--config" => {
+ let Some(path) = args.pop_front() else {
+ return Err(usage!().into());
+ };
+ let data = std::fs::read(path)?;
+ let config = GlobalConfig::from_bytes(&data)?;
+
+ let Some(gitroot) = args.pop_front() else {
+ tracing::error!("missing gitroot");
+ return Err(usage!().into());
+ };
+
+ Ok((config, gitroot))
+ }
+ "--me" => {
+ let Some(gitroot) = args.pop_front() else {
+ tracing::error!("missing gitroot");
+ return Err(usage!().into());
+ };
+
+ Ok((GlobalConfig::caiodotco(), gitroot))
+ }
+ _ if args.is_empty() => Ok((GlobalConfig::default(), arg)),
+ _ => Err(usage!().into()),
+ }
}