anvilsign in

collin/anvil

1//! Core domain model, persistence, and on-disk repository storage for anvil.
2//!
3//! This crate is transport-agnostic: it knows about users, repositories, the
4//! SQLite database, and bare git repositories on disk, but nothing about HTTP,
5//! SSH, or the git wire protocol. Higher layers (`anvil-web`, `anvil-ssh`,
6//! `anvil-git`) build on top of it.
7
8pub mod access;
9pub mod ci;
10pub mod config;
11pub mod db;
12pub mod error;
13pub mod models;
14pub mod repos;
15pub mod sessions;
16pub mod ssh_keys;
17pub mod storage;
18pub mod users;
19
20pub use config::Config;
21pub use error::{
22 Error,
23 Result,
24};
25pub use models::{
26 CiRun,
27 Repository,
28 Session,
29 SshKey,
30 User,
31};
32
33/// Current Unix time in seconds, for `created_at` columns.
34pub(crate) fn now() -> i64 {
35 std::time::SystemTime::now()
36 .duration_since(std::time::UNIX_EPOCH)
37 .map(|d| d.as_secs() as i64)
38 .unwrap_or(0)
39}
40
41/// Shared application state: configuration plus a database handle.
42///
43/// Cloneable and cheap to pass around — `toasty::Db` is internally reference
44/// counted and backed by a connection pool.
45#[derive(Clone)]
46pub struct App {
47 pub config: Config,
48 pub db: toasty::Db,
49}
50
51impl App {
52 /// Initialize application state from a config: ensure the data directories
53 /// exist, then open the database and create the schema.
54 pub async fn bootstrap(config: Config) -> Result<Self> {
55 std::fs::create_dir_all(&config.data_dir)?;
56 std::fs::create_dir_all(config.repositories_dir())?;
57
58 let db = db::connect(config.database_path()).await?;
59
60 Ok(Self { config, db })
61 }
62}