From ca7437b9f970677af8fb3d90d08082ea998faa7f Mon Sep 17 00:00:00 2001
From: Rabindra Dhakal <contact@qaidvoid.dev>
Date: Tue, 5 Nov 2024 20:45:21 +0545
Subject: [PATCH] refactor(config): move default soar dir, use without config
 file

---
 src/cli.rs             |  4 +++
 src/core/config.rs     | 70 ++++++++++++++++++++++++------------------
 src/core/file.rs       |  2 +-
 src/core/util.rs       | 23 ++++++++++++--
 src/lib.rs             |  8 +++--
 src/package/install.rs |  2 +-
 src/package/mod.rs     |  2 +-
 src/registry/mod.rs    |  2 +-
 8 files changed, 75 insertions(+), 38 deletions(-)

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<u8> {
+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<Config> = 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<T>(file: &mut BufReader<T>) -> 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<String> {
+    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<String>,
     pub pkg_id: Option<String>,
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),
                 ),
             ];