diff --git a/src/cli.rs b/src/cli.rs index ac1b70b..4223c15 100644 --- a/src/cli.rs +++ b/src/cli.rs @@ -175,4 +175,8 @@ pub enum Commands { /// Health check #[clap(name = "health")] Health, + + /// Generate config + #[clap(name = "defconfig")] + DefConfig, } diff --git a/src/core/config.rs b/src/core/config.rs index a9dcd9a..cf758ab 100644 --- a/src/core/config.rs +++ b/src/core/config.rs @@ -1,10 +1,12 @@ use std::{collections::HashMap, env::consts::ARCH, fs, path::PathBuf, sync::LazyLock}; +use anyhow::Result; use serde::{Deserialize, Serialize}; -use crate::core::color::{Color, ColorExt}; - -use super::{constant::REGISTRY_PATH, util::home_config_path}; +use super::{ + constant::REGISTRY_PATH, + util::{home_config_path, home_data_path}, +}; /// Application's configuration #[derive(Deserialize, Serialize)] @@ -50,18 +52,13 @@ impl Config { /// If the configuration file is not found, it generates a new default configuration. pub fn new() -> Self { let home_config = home_config_path(); - let pkg_config = PathBuf::from(home_config).join(env!("CARGO_PKG_NAME")); + let pkg_config = PathBuf::from(home_config).join("soar"); let config_path = pkg_config.join("config.json"); let content = match fs::read(&config_path) { Ok(content) => content, Err(e) if e.kind() == std::io::ErrorKind::NotFound => { - fs::create_dir_all(&pkg_config).unwrap(); - eprintln!( - "{}\nGenerating default config at {}", - "Config not found".color(Color::BrightRed), - config_path.to_string_lossy().color(Color::Green) - ); - Config::generate(config_path) + let def_config = Self::default(); + serde_json::to_vec(&def_config).unwrap() } Err(e) => { panic!("Error reading config file: {:?}", e); @@ -70,37 +67,30 @@ impl Config { serde_json::from_slice(&content) .unwrap_or_else(|e| panic!("Failed to parse config file: {:?}", e)) } +} - fn generate(config_path: PathBuf) -> Vec { +impl Default for Config { + fn default() -> Self { let sources = HashMap::from([ - ("bin".to_owned(), format!("https://bin.ajam.dev/{ARCH}")), + ("bin".to_owned(), format!("https://bin.pkgforge.dev/{ARCH}")), ( "base".to_owned(), - format!("https://bin.ajam.dev/{ARCH}/Baseutils"), + format!("https://bin.pkgforge.dev/{ARCH}/Baseutils"), ), - ("pkg".to_owned(), format!("https://pkg.ajam.dev/{ARCH}")), + ("pkg".to_owned(), format!("https://pkg.pkgforge.dev/{ARCH}")), ]); - let def_config = Self { - soar_path: "$HOME/.soar".to_owned(), + Self { + soar_path: format!("{}/soar", home_data_path()), repositories: vec![Repository { - name: "ajam".to_owned(), - url: format!("https://bin.ajam.dev/{ARCH}"), + name: "pkgforge".to_owned(), + url: format!("https://bin.pkgforge.dev/{ARCH}"), metadata: Some("METADATA.AIO.json".to_owned()), sources, }], parallel: Some(true), - parallel_limit: Some(2), - }; - let serialized = serde_json::to_vec_pretty(&def_config).unwrap(); - fs::write(config_path, &serialized).unwrap(); - serialized - } -} - -impl Default for Config { - fn default() -> Self { - Self::new() + parallel_limit: Some(4), + } } } @@ -110,3 +100,23 @@ pub fn init() { } pub static CONFIG: LazyLock = LazyLock::new(Config::default); + +pub fn generate_default_config() -> Result<()> { + let home_config = home_config_path(); + let config_path = PathBuf::from(home_config).join("soar").join("config.json"); + + if config_path.exists() { + eprintln!("Default config already exists. Not overriding it."); + std::process::exit(1); + } + + fs::create_dir_all(config_path.parent().unwrap())?; + + let def_config = Config::default(); + let serialized = serde_json::to_vec_pretty(&def_config)?; + fs::write(&config_path, &serialized)?; + + println!("Default config is saved at: {}", config_path.display()); + + Ok(()) +} diff --git a/src/core/file.rs b/src/core/file.rs index 7ef918c..d36850a 100644 --- a/src/core/file.rs +++ b/src/core/file.rs @@ -12,7 +12,7 @@ pub enum FileType { pub fn get_file_type(file: &mut BufReader) -> FileType where - T: std::io::Read, + T: Read, { let mut magic_bytes = [0u8; 12]; if file.read_exact(&mut magic_bytes).is_ok() { diff --git a/src/core/util.rs b/src/core/util.rs index 5ead3b5..4662b95 100644 --- a/src/core/util.rs +++ b/src/core/util.rs @@ -1,5 +1,6 @@ use std::{ env, + ffi::CStr, io::Write, mem, path::{Path, PathBuf}, @@ -8,7 +9,7 @@ use std::{ use anyhow::{Context, Result}; use futures::StreamExt; use indicatif::{ProgressState, ProgressStyle}; -use libc::{ioctl, winsize, STDOUT_FILENO, TIOCGWINSZ}; +use libc::{geteuid, getpwuid, ioctl, winsize, STDOUT_FILENO, TIOCGWINSZ}; use termion::cursor; use tokio::{ fs::{self, File}, @@ -22,9 +23,27 @@ use super::{ constant::{BIN_PATH, CACHE_PATH, INSTALL_TRACK_PATH, PACKAGES_PATH, REGISTRY_PATH}, }; +fn get_username() -> Result { + unsafe { + let uid = geteuid(); + let pwd = getpwuid(uid); + if pwd.is_null() { + anyhow::bail!("Failed to get user"); + } + let username = CStr::from_ptr((*pwd).pw_name) + .to_string_lossy() + .into_owned(); + Ok(username) + } +} + pub fn home_path() -> String { env::var("HOME").unwrap_or_else(|_| { - panic!("Unable to find home directory."); + let username = env::var("USER") + .or_else(|_| env::var("LOGNAME")) + .or_else(|_| get_username().map_err(|_| ())) + .unwrap_or_else(|_| panic!("Couldn't determine username. Please fix the system.")); + format!("home/{}", username) }) } diff --git a/src/lib.rs b/src/lib.rs index 3ff9a53..8f6937d 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -6,7 +6,7 @@ use registry::PackageRegistry; use core::{ color::{Color, ColorExt}, - config, + config::{self, generate_default_config}, constant::BIN_PATH, health::check_health, util::{cleanup, setup_required_paths}, @@ -24,7 +24,6 @@ pub async fn init() -> Result<()> { config::init(); setup_required_paths().await?; - let registry = PackageRegistry::new().await?; let path_env = env::var("PATH")?; if !path_env.split(':').any(|p| Path::new(p) == *BIN_PATH) { @@ -35,6 +34,8 @@ pub async fn init() -> Result<()> { ); } + let registry = PackageRegistry::new().await?; + let _ = cleanup().await; match args.command { @@ -109,6 +110,9 @@ pub async fn init() -> Result<()> { Commands::Health => { check_health().await; } + Commands::DefConfig => { + generate_default_config()?; + } }; Ok(()) diff --git a/src/package/install.rs b/src/package/install.rs index 56639a4..c6e64a1 100644 --- a/src/package/install.rs +++ b/src/package/install.rs @@ -1,6 +1,6 @@ use std::{ fs::{File, Permissions}, - io::{BufReader, Write}, + io::BufReader, os::unix::fs::PermissionsExt, path::{Path, PathBuf}, sync::Arc, diff --git a/src/package/mod.rs b/src/package/mod.rs index 916c826..44aab25 100644 --- a/src/package/mod.rs +++ b/src/package/mod.rs @@ -40,7 +40,7 @@ pub struct Package { pub build_script: String, pub build_log: String, pub category: String, - pub extra_bins: String, + pub provides: String, pub icon: String, pub desktop: Option, pub pkg_id: Option, diff --git a/src/registry/mod.rs b/src/registry/mod.rs index 08a88ad..d703b6a 100644 --- a/src/registry/mod.rs +++ b/src/registry/mod.rs @@ -195,7 +195,7 @@ impl PackageRegistry { ), ( "Extra Bins", - package.extra_bins.clone().color(Color::BrightBlack), + package.provides.clone().color(Color::BrightBlack), ), ];