diff --git a/example/mlc.toml b/example/mlc.toml index f1cc194..b1e407f 100644 --- a/example/mlc.toml +++ b/example/mlc.toml @@ -1,15 +1,21 @@ +[base] mode = "repository" +smart_pull = true + +[mode.repository] name = "test" sign = false -smart_pull = true +build_on_update = true -repo = [ +[mode.workspace] + +[repositories] +name = [ "1::amethyst", "1::jade!", "2::notop-git", "3::slippy-rb" ] - urls = [ "https://github.com/crystal-linux/%repo%", "https://aur.archlinux.org/%repo%", diff --git a/src/internal/exit_codes.rs b/src/internal/exit_codes.rs index 4d28575..a464d08 100644 --- a/src/internal/exit_codes.rs +++ b/src/internal/exit_codes.rs @@ -7,4 +7,5 @@ pub enum AppExitCode { RepoNotFound = 6, ConfigNotFound = 7, NoPkgs = 8, + ConfigParseError = 9, } diff --git a/src/internal/structs.rs b/src/internal/structs.rs index ff8b575..978eda0 100755 --- a/src/internal/structs.rs +++ b/src/internal/structs.rs @@ -1,37 +1,66 @@ use serde_derive::Deserialize; +//// Config structs #[derive(Debug, Deserialize)] pub struct Config { pub mode: String, - pub name: Option, + pub name: String, pub sign: bool, pub smart_pull: bool, + pub build_on_update: bool, pub repo: Vec, } #[derive(Debug, Deserialize)] -pub struct Repo { - pub name: String, - pub url: String, - pub priority: usize, +pub struct UnexpandedConfig { + pub base: ConfigBase, + pub mode: ConfigMode, + pub repositories: ConfigRepositories, } #[derive(Debug, Deserialize)] -pub struct UnexpandedConfig { +pub struct ConfigBase { pub mode: String, - pub name: Option, - pub sign: bool, pub smart_pull: bool, - pub repo: Vec, +} + +#[derive(Debug, Deserialize)] +pub struct ConfigMode { + pub repository: ConfigModeRepository, + pub workspace: ConfigModeWorkspace, +} + +#[derive(Debug, Deserialize)] +pub struct ConfigModeRepository { + pub name: String, + pub sign: bool, + pub build_on_update: bool, +} + +#[derive(Debug, Deserialize)] +pub struct ConfigModeWorkspace {} + +#[derive(Debug, Deserialize)] +pub struct ConfigRepositories { + pub name: Vec, pub urls: Vec, } +//// Repository structs +#[derive(Debug, Deserialize)] +pub struct Repo { + pub name: String, + pub url: String, + pub priority: usize, +} + #[derive(Debug)] pub struct SplitRepo { pub indx: usize, pub name: String, } +//// Build operation structs #[derive(Debug)] pub struct ErroredPackage { pub name: String, diff --git a/src/main.rs b/src/main.rs index 26aa8fc..5117a23 100755 --- a/src/main.rs +++ b/src/main.rs @@ -24,32 +24,48 @@ fn main() { let args: Args = Args::parse(); - if Path::exists("mlc.toml".as_ref()) && Path::exists(".git".as_ref()) { - info!( - "In a git repository, pulling latest mlc.toml. It is advised you run mlc pull/update" - ); - Command::new("git") - .arg("pull") - .spawn() - .unwrap() - .wait() - .unwrap(); - } - let exclude = &args.exclude; let verbose = args.verbose; if Path::exists("../.git".as_ref()) { info!("Parent directory is a git directory, pulling latest mlc.toml. It is advised you run mlc pull/update in all malachite directories"); + let dir = env::current_dir().unwrap(); env::set_current_dir("../").unwrap(); - Command::new("git") - .arg("pull") - .spawn() - .unwrap() - .wait() - .unwrap(); - env::set_current_dir(dir).unwrap(); + log!(verbose, "Current dir: {:?}", env::current_dir().unwrap()); + + if read_cfg(args.verbose).smart_pull { + log!(verbose, "Smart pull"); + Command::new("git") + .args(&["remote", "update"]) + .spawn() + .unwrap() + .wait() + .unwrap(); + let output = Command::new("git").arg("status").output().unwrap(); + if String::from_utf8(output.stdout) + .unwrap() + .contains("Your branch is behind") + { + Command::new("git") + .arg("pull") + .spawn() + .unwrap() + .wait() + .unwrap(); + } else { + info!("No changes to pull"); + } + } else { + log!(verbose, "Normal pull"); + Command::new("git") + .arg("pull") + .spawn() + .unwrap() + .wait() + .unwrap(); + env::set_current_dir(dir).unwrap(); + } } match args.subcommand.unwrap_or(Operation::Clone) { @@ -66,7 +82,7 @@ fn main() { "Cannot build packages in workspace mode" ) } - info!("Generating repository: {}", config.name.unwrap()); + info!("Generating repository: {}", config.name); repository::generate(verbose); } Operation::Config => operations::config(verbose), diff --git a/src/operations/pull.rs b/src/operations/pull.rs index 849a80d..d704b94 100644 --- a/src/operations/pull.rs +++ b/src/operations/pull.rs @@ -4,7 +4,7 @@ use std::process::Command; use crate::info; use crate::{crash, internal::AppExitCode, log, workspace::read_cfg}; -fn do_the_pulling(repos: Vec, verbose: bool, smart_pull: bool) { +fn do_the_pulling(repos: Vec, verbose: bool, smart_pull: bool, build_on_update: bool) { for repo in repos { // Set root dir to return after each git pull let root_dir = env::current_dir().unwrap(); @@ -42,6 +42,11 @@ fn do_the_pulling(repos: Vec, verbose: bool, smart_pull: bool) { .unwrap() .wait() .unwrap(); + + // If build_on_update is set, rebuild package + if build_on_update { + unimplemented!() + } } else { // If there are no changes, alert the user info!("No changes to pull"); @@ -76,6 +81,9 @@ pub fn pull(packages: Vec, exclude: Vec, verbose: bool) { // Read smart_pull from config let smart_pull = config.smart_pull; log!(verbose, "Smart pull: {}", smart_pull); + // Read build_on_update from config + let build_on_update = config.build_on_update; + log!(verbose, "Build on update: {}", build_on_update); // Read repos from config let repos = config @@ -105,5 +113,5 @@ pub fn pull(packages: Vec, exclude: Vec, verbose: bool) { // Pull! log!(verbose, "Pulling {:?}", repos_applicable); - do_the_pulling(repos_applicable, verbose, smart_pull); + do_the_pulling(repos_applicable, verbose, smart_pull, build_on_update); } diff --git a/src/repository/repo.rs b/src/repository/repo.rs index 9dab54a..2896a13 100644 --- a/src/repository/repo.rs +++ b/src/repository/repo.rs @@ -10,7 +10,7 @@ pub fn generate(verbose: bool) { log!(verbose, "Config: {:?}", config); // Get repository name from config - let name = config.name.unwrap(); + let name = config.name; log!(verbose, "Name: {}", name); // If repository exists, delete it diff --git a/src/workspace/read.rs b/src/workspace/read.rs index 9ae9e35..7df1cb0 100755 --- a/src/workspace/read.rs +++ b/src/workspace/read.rs @@ -16,11 +16,20 @@ pub fn read_cfg(verbose: bool) -> Config { // Reading the config file to an UnexpandedConfig struct let file = fs::read_to_string("mlc.toml").unwrap(); - let config: UnexpandedConfig = toml::from_str(&file).unwrap(); + let config: UnexpandedConfig = toml::from_str(&file).unwrap_or_else(|e| { + crash!( + AppExitCode::ConfigParseError, + "Error parsing config file: {}", + e + ); + // This is unreachable, but rustc complains about it otherwise + std::process::exit(1); + }); + log!(verbose, "Config file read: {:?}", config); // Crash if incorrect mode is set - if config.mode != "workspace" && config.mode != "repository" { + if config.base.mode != "workspace" && config.base.mode != "repository" { crash!( AppExitCode::InvalidMode, "Invalid mode in mlc.toml, must be either \"repository\" or \"workspace\"" @@ -30,7 +39,7 @@ pub fn read_cfg(verbose: bool) -> Config { let mut expanded_repos: Vec = vec![]; // Parsing repos from the config file - for x in config.repo { + for x in config.repositories.name { log!(verbose, "Parsing repo: {:?}", x); // Splits the repo name and index inta a SplitRepo struct let split: Vec<&str> = x.split("::").collect(); @@ -43,7 +52,7 @@ pub fn read_cfg(verbose: bool) -> Config { // Parses all necessary values for expanding the repo to a Repo struct let index = split_struct.indx; let name = split_struct.name.replace('!', ""); - let url = config.urls[index - 1].replace("%repo%", &name); + let url = config.repositories.urls[index - 1].replace("%repo%", &name); let priority = &split_struct.name.matches('!').count(); // Creates and pushes Repo struct to expanded_repos @@ -58,10 +67,11 @@ pub fn read_cfg(verbose: bool) -> Config { // Returns parsed config file let conf = Config { - mode: config.mode, - sign: config.sign, - name: config.name, - smart_pull: config.smart_pull, + mode: config.base.mode, + smart_pull: config.base.smart_pull, + sign: config.mode.repository.sign, + name: config.mode.repository.name, + build_on_update: config.mode.repository.build_on_update, repo: expanded_repos, }; log!(verbose, "Config: {:?}", conf);