refractr/src/main.rs

150 lines
3.7 KiB
Rust
Raw Normal View History

/*
* Copyright 2025 Bryson Steck <me@brysonsteck.xyz>
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
mod common;
2025-02-15 22:11:08 -07:00
mod config;
mod refractr;
2025-02-15 22:11:08 -07:00
use crate::refractr::Refractr;
2025-02-15 22:11:08 -07:00
use clap::Parser;
use std::path::PathBuf;
2025-03-02 14:39:12 -07:00
use std::process;
2025-03-15 17:37:54 -06:00
#[cfg(target_family = "windows")]
2025-03-15 17:20:33 -06:00
use username;
#[cfg(target_family = "unix")]
use users;
2025-02-15 22:11:08 -07:00
#[derive(Parser)]
2025-03-09 12:16:51 -06:00
#[command(name = "refractr")]
2025-03-09 12:26:48 -06:00
#[command(version = option_env!("CARGO_PKG_VERSION"))]
2025-03-09 12:16:51 -06:00
#[command(about = "An automated pull/push utility for mirroring Git repositories")]
2025-02-15 22:11:08 -07:00
#[command(long_about = None)]
struct Args {
#[arg(short, long, help = "Specify a config file", default_value = get_config_default())]
config: Vec<PathBuf>,
2025-02-15 22:11:08 -07:00
#[arg(short, long, help = "Specify the level of verbosity", action = clap::ArgAction::Count)]
verbose: u8,
#[arg(
short = 'e',
long,
help = "Output a full, commented config file and exit"
)]
2025-02-15 22:11:08 -07:00
create: bool,
2025-03-23 21:39:45 -06:00
#[arg(
short = 's',
long,
help = "Exit on push and unknown host errors instead of ignoring them"
)]
strict: bool,
2025-02-15 22:11:08 -07:00
}
2025-02-11 23:32:28 -07:00
fn get_config_default() -> &'static str {
2025-03-15 17:43:22 -06:00
#[cfg(target_os = "windows")]
return "C:\\ProgramData\\refractr\\config.toml";
#[cfg(target_os = "linux")]
return "/etc/refractr/config.toml";
#[cfg(any(
target_os = "freebsd",
2025-03-15 18:18:32 -06:00
target_os = "openbsd",
target_os = "netbsd",
target_os = "macos"
))]
2025-03-15 17:43:22 -06:00
return "/usr/local/etc/refractr/config.toml";
}
2025-03-16 14:48:31 -06:00
#[quit::main]
2025-03-09 12:16:51 -06:00
fn main() -> Result<(), String> {
2025-02-15 22:11:08 -07:00
let args = Args::parse();
2025-03-05 20:45:35 -07:00
let refractr = Refractr {
docker: match option_env!("REFRACTR_DOCKER") {
Some(v) => match v {
"true" => true,
_ => false,
},
None => false,
},
2025-03-02 14:39:12 -07:00
pid: process::id(),
strict: args.strict,
unix: cfg!(unix),
verbose: args.verbose,
2025-03-02 11:47:29 -07:00
};
2025-03-15 17:37:54 -06:00
// warn to avoid root/admin
// unix-like
#[cfg(target_family = "unix")]
if users::get_current_uid() == 0 {
common::warning(format!("this program should not ran as root"));
}
// windows
#[cfg(target_family = "windows")]
match username::get_user_name() {
Ok(user) => {
if user.contains("Administrator") || user.contains("SYSTEM") {
common::warning(format!("this program should not ran as {}", user));
}
},
Err(_) => common::warning(format!("failed to get process username")),
}
common::verbose(
refractr.verbose,
1,
format!(
"refractr started with level {} verbosity enabled",
refractr.verbose.to_string()
),
);
2025-03-09 12:16:51 -06:00
common::verbose(refractr.verbose, 3, format!("Process ID: {}", refractr.pid));
common::verbose(
refractr.verbose,
3,
format!("Running in Docker: {}", refractr.docker),
);
common::verbose(
refractr.verbose,
3,
format!("System is UNIX(-like): {}", refractr.unix),
);
2025-03-02 11:47:29 -07:00
common::verbose(refractr.verbose, 2, format!("Checking for create flag"));
if args.create {
2025-03-02 14:39:12 -07:00
common::verbose(refractr.verbose, 3, format!("Printing sample config"));
let example = include_str!("example/config.toml");
println!("{}", example);
return Ok(());
2025-03-16 14:48:31 -06:00
}
2025-03-02 11:47:29 -07:00
2025-03-16 16:01:20 -06:00
let mut cfgs = vec![];
match config::read_config(args.config, &refractr) {
Ok(c) => cfgs = c,
Err(e) => common::error(format!("{}", e), common::ExitCode::ConfigError),
2025-03-16 14:48:31 -06:00
};
2025-03-16 16:01:20 -06:00
2025-03-16 14:48:31 -06:00
if refractr.verbose >= 2 {
// no need to loop over configs if verbose is not at the correct level
for i in &cfgs {
common::verbose(refractr.verbose, 2, format!("{}", i));
}
}
common::verbose(
refractr.verbose,
1,
format!("Config file(s) read successfully"),
);
2025-03-16 14:48:31 -06:00
match refractr.run(cfgs) {
Ok(_) => (),
Err(e) => common::error(format!("{}", e.msg), e.code),
2025-03-16 14:48:31 -06:00
};
Ok(())
2025-02-11 23:32:28 -07:00
}