diff --git a/.gitignore b/.gitignore old mode 100644 new mode 100755 diff --git a/Cargo.toml b/Cargo.toml old mode 100644 new mode 100755 index 8980836..55b2bd2 --- a/Cargo.toml +++ b/Cargo.toml @@ -12,3 +12,6 @@ path = "src/main.rs" [dependencies] clap = { version = "2.34.0", default-features = false } +toml = "0.5.8" +serde = "1.0.134" +serde_derive = "1.0.134" \ No newline at end of file diff --git a/src/internal/mod.rs b/src/internal/mod.rs new file mode 100755 index 0000000..3a4ebb9 --- /dev/null +++ b/src/internal/mod.rs @@ -0,0 +1,2 @@ +pub mod strings; +pub mod structs; diff --git a/src/internal/strings.rs b/src/internal/strings.rs new file mode 100755 index 0000000..8b13789 --- /dev/null +++ b/src/internal/strings.rs @@ -0,0 +1 @@ + diff --git a/src/internal/structs.rs b/src/internal/structs.rs new file mode 100755 index 0000000..ff46046 --- /dev/null +++ b/src/internal/structs.rs @@ -0,0 +1,8 @@ +use serde_derive::Deserialize; + +#[derive(Debug, Deserialize)] +pub struct Config { + pub mode: String, + pub name: Option, + pub repo: Vec, +} diff --git a/src/main.rs b/src/main.rs old mode 100644 new mode 100755 index 6c9600e..692a98b --- a/src/main.rs +++ b/src/main.rs @@ -1,5 +1,14 @@ +use std::env; +use std::process::Command; + use clap::{App, AppSettings, Arg, ArgSettings, SubCommand}; +use crate::workspace::read_cfg; + +mod internal; +mod repository; +mod workspace; + fn main() { fn build_app() -> App<'static, 'static> { let app = App::new("Malachite") @@ -11,7 +20,7 @@ fn main() { .long("verbose") .multiple(true) .set(ArgSettings::Global) - .help("Sets the level of verbosity") + .help("Sets the level of verbosity"), ) .arg( Arg::with_name("exclude") @@ -19,13 +28,13 @@ fn main() { .long("exclude") .multiple(true) .set(ArgSettings::Global) - .help("Excludes packages from given operation") + .help("Excludes packages from given operation"), ) .arg( Arg::with_name("all") .long("all") .set(ArgSettings::Global) - .help("Operates on every possible package") + .help("Operates on every possible package"), ) .subcommand( SubCommand::with_name("build") @@ -36,7 +45,11 @@ fn main() { .required(true) .multiple(true) .index(1), - ) + ), + ) + .subcommand( + SubCommand::with_name("repo-gen") + .about("Generates repository from build packages") ) .subcommand( SubCommand::with_name("prune") @@ -45,18 +58,133 @@ fn main() { Arg::with_name("days") .help("How old a duplicate package needs to be (in days) to be pruned") .required(true) - .index(1) - ) + .index(1), + ), + ) + .subcommand(SubCommand::with_name("init").about( + "Clones all git repositories from mlc.toml branching from current directory", + )) + .subcommand( + SubCommand::with_name("pull").alias("update").about( + "Pulls all git repositories from mlc.toml branching from current directory", + ), ) .settings(&[ AppSettings::GlobalVersion, AppSettings::VersionlessSubcommands, AppSettings::ArgRequiredElseHelp, - AppSettings::InferSubcommands + AppSettings::InferSubcommands, ]); app } let matches = build_app().get_matches(); -} + if let true = matches.is_present("init") { + let config = workspace::read_cfg(); + if config.mode == "workspace" { + for r in config.repo { + println!("Cloning (workspace mode): {}", r); + Command::new("git") + .args(&["clone", &r]) + .spawn() + .unwrap() + .wait() + .unwrap(); + } + } else if config.mode == "repository" { + for r in config.repo { + println!("Cloning (repository mode): {}", r); + Command::new("git") + .args(&["clone", "--no-checkout", &r]) + .spawn() + .unwrap() + .wait() + .unwrap(); + + println!("Entering working directory: {}", r); + let dir = format!( + "{}/{}", + env::current_dir().unwrap().display(), + r.split('/').collect::>().last().unwrap() + ); + env::set_current_dir(dir).unwrap(); + + println!("Resetting unstaged files: {}", r); + Command::new("git") + .arg("reset") + .spawn() + .unwrap() + .wait() + .unwrap(); + + println!("Checking out PKGBUILD: {}", r); + Command::new("git") + .args(&["checkout", "HEAD", "PKGBUILD"]) + .spawn() + .unwrap() + .wait() + .unwrap(); + } + } else { + panic!("Invalid mode in mlc.toml"); + } + } + + if let true = matches.is_present("build") { + let config = workspace::read_cfg(); + if config.mode != "repository" { + panic!("Cannot build packages in workspace mode") + } + let packages: Vec = matches + .subcommand() + .1 + .unwrap() + .values_of("package(s)") + .unwrap() + .into_iter() + .map(|s| s.to_string()) + .collect(); + let mut repos: Vec = vec![]; + for r in config.repo { + let split = r.split('/').collect::>(); + let a = split.last().unwrap(); + repos.push(a.parse().unwrap()); + } + + for pkg in packages { + if !repos.contains(&pkg) { + panic!("Package {} not found in repos in mlc.toml", pkg); + } else { + repository::build(pkg); + } + } + } + + if let true = matches.is_present("pull") { + let config = workspace::read_cfg(); + for r in config.repo { + println!("Entering working directory: {}", r); + let dir = format!( + "{}/{}", + env::current_dir().unwrap().display(), + r.split('/').collect::>().last().unwrap() + ); + env::set_current_dir(dir).unwrap(); + Command::new("git") + .args(&["pull", &r]) + .spawn() + .unwrap() + .wait() + .unwrap(); + } + } + + if let true = matches.is_present("repo-gen") { + let config = read_cfg(); + if config.mode != "repository" { + panic!("Cannot build packages in workspace mode") + } + repository::generate(); + } +} \ No newline at end of file diff --git a/src/repository/mod.rs b/src/repository/mod.rs new file mode 100755 index 0000000..ca6a11d --- /dev/null +++ b/src/repository/mod.rs @@ -0,0 +1,8 @@ +mod package; +mod repo; + +pub fn build(pkg: String) { + package::build(pkg); +} + +pub fn generate() { repo::generate(); } \ No newline at end of file diff --git a/src/repository/package.rs b/src/repository/package.rs new file mode 100755 index 0000000..46ac517 --- /dev/null +++ b/src/repository/package.rs @@ -0,0 +1,32 @@ +use std::{env, fs}; +use std::path::Path; +use std::process::Command; + +pub fn build(pkg: String) { + let dir = env::current_dir().unwrap(); + if !Path::exists("out".as_ref()) { + fs::create_dir_all("out").unwrap(); + } + if !Path::exists(pkg.as_ref()) { + panic!("Git directory for {} not found, aborting", pkg); + } + + env::set_current_dir(pkg).unwrap(); + Command::new("updpkgsums").spawn().unwrap().wait().unwrap(); + + Command::new("makepkg") + .args(&["-sf", "--skippgpcheck", "--sign", "--noconfirm"]) + .spawn() + .unwrap() + .wait() + .unwrap(); + + Command::new("bash") + .args(&["-c", "cp *.pkg.tar.zst* ../out/"]) + .spawn() + .unwrap() + .wait() + .unwrap(); + + env::set_current_dir(dir).unwrap(); +} \ No newline at end of file diff --git a/src/repository/repo.rs b/src/repository/repo.rs new file mode 100644 index 0000000..9ca83a7 --- /dev/null +++ b/src/repository/repo.rs @@ -0,0 +1,50 @@ +use std::{env, fs}; +use std::path::Path; +use std::process::Command; + +use crate::workspace::read_cfg; + +pub fn generate() { + let config = read_cfg(); + let name = config.name.unwrap(); + + if !Path::exists(name.as_ref()) { + fs::create_dir_all(&name).unwrap(); + } + + Command::new("bash") + .args(&["-c", &format!("cp -v out/* {}/", &name)]) + .spawn() + .unwrap() + .wait() + .unwrap(); + + env::set_current_dir(&name).unwrap(); + + let db = format!("{}.db", &name); + let files = format!("{}.files", &name); + + Command::new("bash") + .args(&["-c", &format!("repo-add {}.tar.gz *.pkg.tar.zst", db)]) + .spawn() + .unwrap() + .wait() + .unwrap(); + + Command::new("bash") + .args(&["-c", &format!("rm {}.{{db,files}}", &name)]) + .spawn() + .unwrap() + .wait() + .unwrap(); + + Command::new("bash") + .args(&[ + "-c", + &format!("mv {}.tar.gz {}; mv {}.tar.gz {}", db, db, files, files), + ]) + .spawn() + .unwrap() + .wait() + .unwrap(); +} \ No newline at end of file diff --git a/src/workspace/mod.rs b/src/workspace/mod.rs new file mode 100755 index 0000000..1b19d47 --- /dev/null +++ b/src/workspace/mod.rs @@ -0,0 +1,7 @@ +use crate::internal::structs::Config; + +mod read; + +pub fn read_cfg() -> Config { + read::read_cfg() +} diff --git a/src/workspace/read.rs b/src/workspace/read.rs new file mode 100755 index 0000000..886a6e9 --- /dev/null +++ b/src/workspace/read.rs @@ -0,0 +1,15 @@ +use std::fs; +use std::path::Path; + +use crate::internal::structs::Config; + +pub fn read_cfg() -> Config { + if !Path::exists("mlc.toml".as_ref()) { + panic!("mlc.toml file not found") + } + + let file = fs::read_to_string("mlc.toml").unwrap(); + let config: Config = toml::from_str(&file).unwrap(); + + config +} \ No newline at end of file