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.
malachite/src/main.rs

245 lines
8.2 KiB
Rust

2 years ago
use std::env;
use std::path::Path;
2 years ago
use std::process::Command;
use crate::internal::{crash, info};
use clap::{App, AppSettings, Arg, ArgSettings, SubCommand};
use crate::repository::create_config;
2 years ago
2 years ago
use crate::workspace::read_cfg;
#[global_allocator]
static GLOBAL: mimalloc::MiMalloc = mimalloc::MiMalloc;
2 years ago
mod internal;
mod repository;
mod workspace;
2 years ago
fn main() {
extern "C" {
fn geteuid() -> u32;
}
if unsafe { geteuid() } == 0 {
crash("Running malachite as root is disallowed as it can lead to system breakage. Instead, malachite will prompt you when it needs superuser permissions".to_string(), 1);
}
2 years ago
fn build_app() -> App<'static, 'static> {
let app = App::new("Malachite")
.version(env!("CARGO_PKG_VERSION"))
.about(env!("CARGO_PKG_DESCRIPTION"))
.arg(
Arg::with_name("verbose")
.short("v")
.long("verbose")
.multiple(true)
.set(ArgSettings::Global)
2 years ago
.help("Sets the level of verbosity"),
2 years ago
)
.subcommand(
SubCommand::with_name("build")
.about("Builds the given packages")
.arg(
Arg::with_name("package(s)")
.help("The packages to operate on")
.multiple(true)
.index(1),
)
.arg(
Arg::with_name("all")
.long("all")
.help("Builds all packages in mlc.toml (except if -x is specified)")
.conflicts_with("package(s)")
)
.arg(
Arg::with_name("exclude")
.short("x")
.long("exclude")
.multiple(true)
.takes_value(true)
.help("Excludes packages from given operation")
)
2 years ago
)
.subcommand(
SubCommand::with_name("repo-gen").about("Generates repository from built packages"),
2 years ago
)
.subcommand(
SubCommand::with_name("prune")
.about("Prunes duplicate packages older than X days from the repository")
.arg(
Arg::with_name("days")
.help("How old a duplicate package needs to be (in days) to be pruned")
.required(true)
2 years ago
.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",
),
2 years ago
)
.subcommand(
SubCommand::with_name("config").about("Create and/or open local config file"),
)
2 years ago
.settings(&[
AppSettings::GlobalVersion,
AppSettings::VersionlessSubcommands,
AppSettings::ArgRequiredElseHelp,
2 years ago
AppSettings::InferSubcommands,
2 years ago
]);
app
}
let matches = build_app().get_matches();
2 years ago
if let true = matches.is_present("init") {
let config = workspace::read_cfg();
if config.mode == "workspace" {
for r in config.repo {
info(format!("Cloning (workspace mode): {}", r));
2 years ago
Command::new("git")
.args(&["clone", &r])
.spawn()
.unwrap()
.wait()
.unwrap();
}
} else if config.mode == "repository" {
for r in config.repo {
info(format!("Cloning (repository mode): {}", r));
2 years ago
Command::new("git")
.args(&["clone", "--no-checkout", &r])
.spawn()
.unwrap()
.wait()
.unwrap();
info(format!("Entering working directory: {}", r));
let cdir = env::current_dir().unwrap();
2 years ago
let dir = format!(
"{}/{}",
env::current_dir().unwrap().display(),
r.split('/').collect::<Vec<&str>>().last().unwrap()
);
env::set_current_dir(dir).unwrap();
info(format!("Resetting unstaged files: {}", r));
2 years ago
Command::new("git")
.arg("reset")
.spawn()
.unwrap()
.wait()
.unwrap();
info(format!("Checking out PKGBUILD: {}", r));
2 years ago
Command::new("git")
.args(&["checkout", "HEAD", "PKGBUILD"])
.spawn()
.unwrap()
.wait()
.unwrap();
info(format!("Exiting work directory: {}", r));
env::set_current_dir(cdir).unwrap();
2 years ago
}
} else {
crash("Invalid mode in mlc.toml".to_string(), 1);
2 years ago
}
}
if let true = matches.is_present("build") {
let config = workspace::read_cfg();
let mut packages: Vec<String> = matches
.subcommand_matches("build")
.unwrap()
.values_of_lossy("package(s)")
.unwrap_or(vec![]);
let exclude: Vec<String> = matches
.subcommand_matches("build")
.unwrap()
.values_of_lossy("exclude")
.unwrap_or(vec![]);
for pkg in &exclude {
packages.retain(|x| &*x != pkg);
}
2 years ago
if config.mode != "repository" {
crash("Cannot build packages in workspace mode".to_string(), 2);
2 years ago
}
2 years ago
let mut repos: Vec<String> = vec![];
for r in config.repo {
let split = r.split('/').collect::<Vec<&str>>();
let a = split.last().unwrap();
repos.push(a.parse().unwrap());
}
if matches.subcommand_matches("build").unwrap().is_present("exclude") {
for ex in exclude {
repos.retain(|x| *x != ex);
}
}
2 years ago
for pkg in packages {
if !repos.contains(&pkg) {
crash(format!("Package {} not found in repos in mlc.toml", pkg), 3);
2 years ago
} else {
repository::build(pkg);
}
}
if matches.subcommand_matches("build").unwrap().is_present("all") {
for pkg in repos {
repository::build(pkg);
}
}
2 years ago
}
if let true = matches.is_present("pull") {
let config = workspace::read_cfg();
let cdir = env::current_dir().unwrap();
2 years ago
for r in config.repo {
info(format!("Entering working directory: {}", r));
2 years ago
let dir = format!(
"{}/{}",
env::current_dir().unwrap().display(),
r.split('/').collect::<Vec<&str>>().last().unwrap()
);
env::set_current_dir(dir).unwrap();
Command::new("git")
.args(&["pull", &r])
.spawn()
.unwrap()
.wait()
.unwrap();
env::set_current_dir(&cdir).unwrap();
2 years ago
}
}
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();
}
if let true = matches.is_present("config") {
if !Path::exists("mlc.toml".as_ref()) {
create_config();
}
let editor = env::var("EDITOR").unwrap_or_else(|_| "nano".to_string());
Command::new(editor)
.arg("mlc.toml")
.spawn()
.unwrap()
.wait()
.unwrap();
}
}