Skip to main content

packset_daemon/
lib.rs

1//! The loopback pack writer.
2//!
3//! One process owns `memory.lmdb` and every client speaks HTTP to it, so an
4//! isolated harness home does not get a private store. Cards stay files
5//! because a person edits them; atoms are a database because a program does.
6
7pub mod cards;
8pub mod context;
9pub mod embed;
10pub mod glob;
11pub mod home;
12pub mod http;
13pub mod milli;
14pub mod proposals;
15pub mod service;
16pub mod store;
17pub mod workspace;
18
19pub use home::Home;
20pub use service::Service;
21pub use store::Store;
22
23/// The `packsetd` binary. Also the `packset` crate's packsetd bin.
24///
25/// # Errors
26///
27/// Fails when flags are unknown, the store cannot open, or the listener
28/// cannot bind.
29pub fn run() -> anyhow::Result<()> {
30    use std::sync::Arc;
31
32    let mut host = http::LOOPBACK.to_string();
33    let mut port = std::env::var("PACKSET_PORT")
34        .or_else(|_| std::env::var("GROK_MEM_PORT"))
35        .ok()
36        .and_then(|raw| raw.parse().ok())
37        .unwrap_or(http::DEFAULT_PORT);
38    let mut root = std::env::var_os("PACKSET_HOME")
39        .or_else(|| std::env::var_os("GROKINSIDE_HOME"))
40        .or_else(|| std::env::var_os("GROK_INSIDE_MEMORY_HOME"))
41        .map_or_else(Home::default_root, Into::into);
42    let mut fuse = None;
43    let mut diversify = None;
44    let mut decay = None;
45
46    let mut args = std::env::args().skip(1);
47    while let Some(arg) = args.next() {
48        let mut next = |flag: &str| -> anyhow::Result<String> {
49            args.next()
50                .ok_or_else(|| anyhow::anyhow!("{flag} needs a value"))
51        };
52        match arg.as_str() {
53            "--host" => host = next("--host")?,
54            "--port" => port = next("--port")?.parse()?,
55            "--home" => root = next("--home")?.into(),
56            "--fuse" => fuse = Some(next("--fuse")?),
57            "--diversify" => diversify = Some(next("--diversify")?),
58            "--decay" => decay = Some(next("--decay")?),
59            "-h" | "--help" => {
60                println!("{}", packsetd_usage());
61                return Ok(());
62            }
63            "-V" | "--version" => {
64                println!(
65                    "packsetd {} ({})",
66                    env!("CARGO_PKG_VERSION"),
67                    env!("PACKSET_COMMIT")
68                );
69                return Ok(());
70            }
71            other => anyhow::bail!("unknown argument: {other}\n\n{}", packsetd_usage()),
72        }
73    }
74
75    let fuse = fuse.or_else(|| std::env::var("PACKSET_FUSE").ok());
76    let diversify = diversify.or_else(|| std::env::var("PACKSET_DIVERSIFY").ok());
77    let decay = decay.or_else(|| std::env::var("PACKSET_DECAY").ok());
78    let panel = packset_core::Panel::from_env_vars(
79        fuse.as_deref(),
80        diversify.as_deref(),
81        decay.as_deref(),
82    )?;
83    eprintln!(
84        "packsetd: panel {} / {} / {}",
85        panel.fuse.as_str(),
86        panel.diversify.as_str(),
87        panel.decay.as_str()
88    );
89
90    let service = Arc::new(Service::open(Home::new(root))?);
91    http::serve(service, panel, &host, port)
92}
93
94fn packsetd_usage() -> String {
95    format!(
96        "packsetd: the loopback pack writer\n\
97         \n\
98             -V, --version       the build this is\n\
99             --host <addr>       {} only, which is the contract\n\
100             --port <n>          default {}, or PACKSET_PORT\n\
101             --home <dir>        the pack home, or PACKSET_HOME\n\
102             --fuse <name>       host fuse voter, or PACKSET_FUSE\n\
103             --diversify <name>  host diversify voter, or PACKSET_DIVERSIFY\n\
104             --decay <name>      host decay voter, or PACKSET_DECAY",
105        http::LOOPBACK,
106        http::DEFAULT_PORT
107    )
108}