You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
193 lines
5.4 KiB
Rust
193 lines
5.4 KiB
Rust
use std::borrow::Cow;
|
|
use std::collections::HashMap;
|
|
use std::env;
|
|
use std::ops::Not;
|
|
use std::path::PathBuf;
|
|
|
|
use serde::{Deserialize, Serialize};
|
|
|
|
use crate::build::BUILDFILE;
|
|
use crate::builders::{GitAddBuilder, GitInitBuilder};
|
|
use crate::errors::ConfigError;
|
|
use crate::generate::GENERATEFILE;
|
|
use crate::lock::LOCKFILE_VERSION;
|
|
use crate::AppError;
|
|
|
|
#[derive(Clone, Debug, Deserialize, Serialize)]
|
|
pub struct Config {
|
|
pub base: BaseConfig,
|
|
pub repo: RepoConfig,
|
|
pub repositories: Repositories,
|
|
}
|
|
|
|
#[derive(Clone, Debug, Deserialize, Serialize)]
|
|
pub struct BaseConfig {
|
|
pub src: PathBuf,
|
|
pub podman: bool,
|
|
pub image: String,
|
|
}
|
|
|
|
#[derive(Clone, Debug, Deserialize, Serialize)]
|
|
pub struct RepoConfig {
|
|
pub name: String,
|
|
pub out: PathBuf,
|
|
pub repo: PathBuf,
|
|
pub security: SecurityConfig,
|
|
}
|
|
|
|
#[derive(Clone, Debug, Deserialize, Serialize)]
|
|
pub struct SecurityConfig {
|
|
pub sign: bool,
|
|
pub sign_key: Option<String>,
|
|
}
|
|
|
|
#[derive(Clone, Debug, Deserialize, Serialize)]
|
|
pub struct Repositories {
|
|
pub names: Vec<GitRepo>,
|
|
pub keys: HashMap<String, String>,
|
|
}
|
|
|
|
#[derive(Clone, Debug, Deserialize, Serialize)]
|
|
#[serde(into = "String", try_from = "String")]
|
|
pub struct GitRepo {
|
|
pub key: String,
|
|
pub name: String,
|
|
pub rev: Option<String>,
|
|
}
|
|
|
|
impl From<String> for GitRepo {
|
|
fn from(s: String) -> Self {
|
|
let (key, repo) = s.split_once(':').unwrap();
|
|
let (name, rev) = repo.split_once('@').unwrap_or((repo, ""));
|
|
|
|
Self {
|
|
key: key.to_string(),
|
|
name: name.to_string(),
|
|
rev: rev.is_empty().not().then_some(rev.to_string()),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl From<GitRepo> for String {
|
|
fn from(repo: GitRepo) -> Self {
|
|
if let Some(rev) = repo.rev {
|
|
format!("{}:{}@{}", repo.key, repo.name, rev)
|
|
} else {
|
|
format!("{}:{}", repo.key, repo.name)
|
|
}
|
|
}
|
|
}
|
|
|
|
impl GitRepo {
|
|
pub fn expand(&self, config: &Config) -> Result<String, ConfigError> {
|
|
let url = config
|
|
.repositories
|
|
.keys
|
|
.get(&self.key)
|
|
.ok_or_else(|| ConfigError::Expand(format!("Unknown key: {}", self.key)))?;
|
|
|
|
Ok(url.replace("{}", &self.name))
|
|
}
|
|
}
|
|
|
|
impl Default for Config {
|
|
fn default() -> Self {
|
|
let pwd = env::current_dir().unwrap_or_else(|_| PathBuf::from("."));
|
|
let name = pwd
|
|
.file_name()
|
|
.map(|s| s.to_string_lossy())
|
|
.unwrap_or_else(|| Cow::from("mlc".to_string()));
|
|
Self {
|
|
base: BaseConfig {
|
|
src: pwd.clone(),
|
|
podman: false,
|
|
image: "archlinux:latest".to_string(),
|
|
},
|
|
repo: RepoConfig {
|
|
name: name.to_string(),
|
|
out: pwd.join("out"),
|
|
repo: pwd.join("repo"),
|
|
security: SecurityConfig {
|
|
sign: false,
|
|
sign_key: None,
|
|
},
|
|
},
|
|
repositories: Repositories {
|
|
names: vec![
|
|
GitRepo {
|
|
key: "crs".to_string(),
|
|
name: "malachite".to_string(),
|
|
rev: Some("mlc3-rewrite".to_string()),
|
|
},
|
|
GitRepo {
|
|
key: "aur".to_string(),
|
|
name: "ame".to_string(),
|
|
rev: None,
|
|
},
|
|
],
|
|
keys: HashMap::from([
|
|
(
|
|
"crs".to_string(),
|
|
"https://git.getcryst.al/crystal/software/{}.git".to_string(),
|
|
),
|
|
(
|
|
"aur".to_string(),
|
|
"https://aur.archlinux.org/{}.git".to_string(),
|
|
),
|
|
]),
|
|
},
|
|
}
|
|
}
|
|
}
|
|
|
|
impl Config {
|
|
pub fn init() -> Result<(), AppError> {
|
|
let pwd = env::current_dir().unwrap_or_else(|_| PathBuf::from("."));
|
|
let config = Config::default();
|
|
|
|
if pwd.read_dir()?.count() > 0 {
|
|
return Err(AppError::Config(ConfigError::Init(
|
|
"Directory is not empty".to_string(),
|
|
)));
|
|
}
|
|
|
|
std::fs::create_dir(".mlc")?;
|
|
std::fs::write(
|
|
".mlc/config.toml",
|
|
toml::to_string_pretty(&config)
|
|
.map_err(|e| AppError::Config(ConfigError::Serialize(e)))?,
|
|
)?;
|
|
std::fs::write(".mlc/Buildfile", BUILDFILE)?;
|
|
std::fs::write(".mlc/Generatefile", GENERATEFILE)?;
|
|
|
|
std::fs::create_dir(".mlc/conf.d")?;
|
|
std::fs::create_dir(".mlc/store")?;
|
|
std::fs::create_dir(".mlc/logs")?;
|
|
|
|
std::fs::write(
|
|
".mlc/mlc.lock",
|
|
format!("[lockfile]\nversion = '{LOCKFILE_VERSION}'\n\n[remote]\n"),
|
|
)?;
|
|
std::fs::write(".mlc/conf.d/.gitkeep", "\n")?;
|
|
std::fs::write(".mlc/store/.gitkeep", "\n")?;
|
|
std::fs::write(".mlc/logs/.gitkeep", "\n")?;
|
|
std::fs::write(".gitignore", "/*/\n!/.mlc")?;
|
|
|
|
GitInitBuilder::new(pwd.clone()).init()?.silent()?;
|
|
|
|
GitAddBuilder::new(pwd)
|
|
.refspecs([".gitignore", ".mlc/**"])
|
|
.add()?
|
|
.silent()?;
|
|
|
|
Ok(())
|
|
}
|
|
|
|
pub fn load() -> Result<Config, AppError> {
|
|
let pwd = env::current_dir().unwrap_or_else(|_| PathBuf::from("."));
|
|
let config = toml::from_str(&std::fs::read_to_string(pwd.join(".mlc/config.toml"))?)?;
|
|
|
|
Ok(config)
|
|
}
|
|
}
|