From b4d4c3263e148826e941d86365936c9bb5ff794d Mon Sep 17 00:00:00 2001 From: Michael Gattozzi Date: Sun, 23 Jul 2023 22:02:31 +0000 Subject: [PATCH] Implement basic configuration w/Freight.toml file This commit adds the beginning of a configuration file for Freight. Eventually we'll make it more robust with parsing when we can add serde and the like as a dependency but we're a long ways off from that. With this we can offload configuration from being hardcoded inside of Freight to a config file that users can use to tailor to their project. It also lets us get rid of the janky check for ".git" in root_dir and instead look for a manifest to work with, in this case Freight. Later on we'll need better toml support so that we can build Cargo projects --- Freight.toml | 2 ++ src/config.rs | 42 ++++++++++++++++++++++++++++++++++++++++++ src/lib.rs | 21 +++++++++++---------- 3 files changed, 55 insertions(+), 10 deletions(-) create mode 100644 Freight.toml create mode 100644 src/config.rs diff --git a/Freight.toml b/Freight.toml new file mode 100644 index 0000000..1b62a7a --- /dev/null +++ b/Freight.toml @@ -0,0 +1,2 @@ +name = "freight" +edition = "2021" diff --git a/src/config.rs b/src/config.rs new file mode 100644 index 0000000..cc261bf --- /dev/null +++ b/src/config.rs @@ -0,0 +1,42 @@ +use super::Edition; +use super::Result; +use std::error::Error; +use std::fs; +use std::path::Path; + +pub struct Manifest { + pub crate_name: String, + pub edition: Edition, +} + +impl Manifest { + pub fn parse_from_file(path: impl AsRef) -> Result { + let path = path.as_ref(); + let mut crate_name = None; + let mut edition = None; + + for line in fs::read_to_string(path)?.lines() { + let mut split = line.split('='); + let field = split.next().unwrap().trim(); + let value = split.next().unwrap().trim(); + + match field { + "name" => crate_name = Some(value.replace('"', "")), + "edition" => { + edition = Some(match value.replace('"', "").parse()? { + 2015 => Edition::E2015, + 2018 => Edition::E2018, + 2021 => Edition::E2021, + edition => return Err(format!("Edition {edition} is unsupported").into()), + }) + } + field => return Err(format!("Field {field} is unsupported").into()), + } + } + + Ok(Self { + crate_name: crate_name.ok_or::>("name is a required field".into())?, + edition: edition.ok_or::>("edition is a required field".into())?, + }) + } +} diff --git a/src/lib.rs b/src/lib.rs index 031fc3a..a983c54 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,3 +1,6 @@ +mod config; + +use config::Manifest; use std::env; use std::error::Error; use std::fmt; @@ -10,10 +13,7 @@ pub type Result = std::result::Result>; pub fn build() -> Result<()> { let root_dir = root_dir()?; - // TODO: Get this from a config file - let crate_name = root_dir - .file_name() - .ok_or::>("Freight run in directory without a name".into())?; + let manifest = Manifest::parse_from_file(root_dir.join("Freight.toml"))?; let lib_rs = root_dir.join("src").join("lib.rs"); let main_rs = root_dir.join("src").join("main.rs"); @@ -24,9 +24,9 @@ pub fn build() -> Result<()> { let lib_compile = || -> Result<()> { println!("Compiling lib.rs"); Rustc::builder() - .edition(Edition::E2021) + .edition(manifest.edition) .crate_type(CrateType::Lib) - .crate_name(crate_name.to_str().unwrap()) + .crate_name(&manifest.crate_name) .out_dir(target_debug.clone()) .lib_dir(target_debug.clone()) .done() @@ -38,9 +38,9 @@ pub fn build() -> Result<()> { let bin_compile = |externs: Vec<&str>| -> Result<()> { println!("Compiling main.rs"); let mut builder = Rustc::builder() - .edition(Edition::E2021) + .edition(manifest.edition) .crate_type(CrateType::Bin) - .crate_name(crate_name.to_str().unwrap()) + .crate_name(&manifest.crate_name) .out_dir(target_debug.clone()) .lib_dir(target_debug.clone()); @@ -56,7 +56,7 @@ pub fn build() -> Result<()> { match (lib_rs.exists(), main_rs.exists()) { (true, true) => { lib_compile()?; - bin_compile(vec![crate_name.to_str().unwrap()])?; + bin_compile(vec![&manifest.crate_name])?; } (true, false) => { lib_compile()?; @@ -73,7 +73,7 @@ pub fn build() -> Result<()> { fn root_dir() -> Result { let current_dir = env::current_dir()?; for ancestor in current_dir.ancestors() { - if ancestor.join(".git").exists() { + if ancestor.join("Freight.toml").exists() { return Ok(ancestor.into()); } } @@ -183,6 +183,7 @@ impl RustcBuilder { } } +#[derive(Clone, Copy)] pub enum Edition { E2015, E2018,