Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Move default soar dir, add local package install support #2

Merged
merged 2 commits into from
Nov 5, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions src/cli.rs
Original file line number Diff line number Diff line change
Expand Up @@ -175,4 +175,8 @@ pub enum Commands {
/// Health check
#[clap(name = "health")]
Health,

/// Generate config
#[clap(name = "defconfig")]
DefConfig,
}
70 changes: 40 additions & 30 deletions src/core/config.rs
Original file line number Diff line number Diff line change
@@ -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)]
Expand Down Expand Up @@ -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);
Expand All @@ -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),
}
}
}

Expand All @@ -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(())
}
11 changes: 6 additions & 5 deletions src/core/file.rs
Original file line number Diff line number Diff line change
@@ -1,18 +1,19 @@
use std::{
fs::File,
io::{BufReader, Read},
};
use std::io::{BufReader, Read};

use super::constant::{APPIMAGE_MAGIC_BYTES, ELF_MAGIC_BYTES, FLATIMAGE_MAGIC_BYTES};

#[derive(PartialEq, Eq)]
pub enum FileType {
AppImage,
FlatImage,
ELF,
Unknown,
}

pub fn get_file_type(file: &mut BufReader<File>) -> FileType {
pub fn get_file_type<T>(file: &mut BufReader<T>) -> FileType
where
T: Read,
{
let mut magic_bytes = [0u8; 12];
if file.read_exact(&mut magic_bytes).is_ok() {
if magic_bytes[8..] == APPIMAGE_MAGIC_BYTES {
Expand Down
59 changes: 53 additions & 6 deletions src/core/util.rs
Original file line number Diff line number Diff line change
@@ -1,26 +1,49 @@
use std::{
env, mem,
env,
ffi::CStr,
io::Write,
mem,
path::{Path, PathBuf},
};

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},
io::{AsyncReadExt, AsyncWriteExt},
};

use crate::warn;

use super::{
color::{Color, ColorExt},
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)
})
}

Expand Down Expand Up @@ -88,9 +111,12 @@ pub fn parse_size(size_str: &str) -> Option<u64> {
let size_str = size_str.trim();
let units = [
("B", 1u64),
("KB", 1024u64),
("MB", 1024u64 * 1024),
("GB", 1024u64 * 1024 * 1024),
("KB", 1000u64),
("MB", 1000u64 * 1000),
("GB", 1000u64 * 1000 * 1000),
("KiB", 1024u64),
("MiB", 1024u64 * 1024),
("GiB", 1024u64 * 1024 * 1024),
];

for (unit, multiplier) in &units {
Expand Down Expand Up @@ -348,3 +374,24 @@ pub fn download_progress_style(with_msg: bool) -> ProgressStyle {
)
.progress_chars("━━")
}

#[derive(PartialEq, Eq)]
pub enum AskType {
Warn,
Normal,
}

pub fn interactive_ask(ques: &str, ask_type: AskType) -> Result<String> {
if ask_type == AskType::Warn {
warn!("{ques}");
} else {
println!("{ques}");
}

std::io::stdout().flush()?;

let mut response = String::new();
std::io::stdin().read_line(&mut response)?;

Ok(response.trim().to_owned())
}
8 changes: 6 additions & 2 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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},
Expand All @@ -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) {
Expand All @@ -35,6 +34,8 @@ pub async fn init() -> Result<()> {
);
}

let registry = PackageRegistry::new().await?;

let _ = cleanup().await;

match args.command {
Expand Down Expand Up @@ -109,6 +110,9 @@ pub async fn init() -> Result<()> {
Commands::Health => {
check_health().await;
}
Commands::DefConfig => {
generate_default_config()?;
}
};

Ok(())
Expand Down
14 changes: 7 additions & 7 deletions src/package/appimage.rs
Original file line number Diff line number Diff line change
Expand Up @@ -161,9 +161,9 @@ pub async fn integrate_appimage(
match resolve_and_extract(&squashfs, node, &output_path, &mut HashSet::new()) {
Ok(()) => {
if extension == "png" {
process_icon(&output_path, &package.bin_name, data_path).await?;
process_icon(&output_path, &package.pkg_name, data_path).await?;
} else {
process_desktop(&output_path, &package.bin_name, &package.name, data_path)
process_desktop(&output_path, &package.pkg_name, &package.pkg, data_path)
.await?;
}
}
Expand Down Expand Up @@ -315,20 +315,20 @@ pub async fn integrate_using_remote_files(package: &Package, file_path: &Path) -
let desktop_content = match desktop_content {
Some(content) => content,
None => create_default_desktop_entry(
&package.bin_name,
&package.name,
&package.pkg_name,
&package.pkg,
&package.category.replace(',', ";"),
),
};

fs::write(&desktop_output_path, &desktop_content).await?;

try_join!(
process_icon(&icon_output_path, &package.bin_name, data_path),
process_icon(&icon_output_path, &package.pkg_name, data_path),
process_desktop(
&desktop_output_path,
&package.bin_name,
&package.name,
&package.pkg_name,
&package.pkg,
data_path
)
)?;
Expand Down
Loading