feat: list_installed_packages, update_package, update_all_packages for client

This commit is contained in:
Ahmet Kaan GÜMÜŞ 2024-11-24 20:46:16 +03:00
parent 0f0e05ef91
commit 4ba4e6fe30
3 changed files with 107 additions and 18 deletions

View file

@ -1,11 +1,12 @@
use tokio::{
fs::{read_dir, remove_file, DirBuilder, File, OpenOptions},
fs::{remove_file, DirBuilder, File, OpenOptions},
io::{AsyncReadExt, AsyncWriteExt},
};
use sha3::{Digest, Sha3_512};
const PACKAGE_PATH: &str = "./packages/";
const METADATA_FILE_NAME: &str = "metadata.txt";
pub async fn save_package(package_name: String, package_data: &[u8]) -> Result<(), std::io::Error> {
let file_location = format!("{}{}", PACKAGE_PATH, package_name);
@ -22,23 +23,25 @@ pub async fn delete_package(package_name: String) -> Result<(), std::io::Error>
delete_metadata(package_name).await
}
pub async fn list_packages() -> Option<Vec<String>> {
let mut folder_elements = read_dir(PACKAGE_PATH).await.ok()?;
let mut packages = vec![];
loop {
match folder_elements.next_entry().await.ok()? {
Some(file_entry) => packages.push(file_entry.file_name().into_string().ok()?),
None => break,
pub async fn list_installed_packages() -> Result<Vec<String>, std::io::Error> {
let metadata_file_location = format!("{}{}", PACKAGE_PATH, METADATA_FILE_NAME);
let mut metadata_file = match File::open(&metadata_file_location).await {
Ok(metadata_file) => metadata_file,
Err(_) => {
File::create_new(&metadata_file_location).await?;
return Ok(vec![]);
}
};
let mut metadata = String::default();
metadata_file.read_to_string(&mut metadata).await?;
let mut package_names = vec![];
for line in metadata.lines() {
package_names.push(line.trim_end().to_string());
}
Ok(package_names)
}
if packages.is_empty() {
return None;
}
Some(packages)
}
async fn calculate_hash(package_name: String) -> Result<Option<Vec<u8>>, std::io::Error> {
pub async fn calculate_hash(package_name: String) -> Result<Option<Vec<u8>>, std::io::Error> {
if let Some(_) = search_metadata(package_name.to_owned()).await? {
let file_location = format!("{}{}", PACKAGE_PATH, package_name);
let mut target_file = File::open(file_location).await?;
@ -53,7 +56,7 @@ async fn calculate_hash(package_name: String) -> Result<Option<Vec<u8>>, std::io
}
async fn search_metadata(package_name: String) -> Result<Option<usize>, std::io::Error> {
let file_location = format!("{}{}", PACKAGE_PATH, "metadata.txt");
let file_location = format!("{}{}", PACKAGE_PATH, METADATA_FILE_NAME);
let mut file = match File::open(file_location.clone()).await {
Ok(file) => file,
Err(_) => {
@ -75,7 +78,7 @@ async fn search_metadata(package_name: String) -> Result<Option<usize>, std::io:
async fn search_and_retrieve_metadata(
package_name: String,
) -> Result<(Option<usize>, Vec<String>), std::io::Error> {
let file_location = format!("{}{}", PACKAGE_PATH, "metadata.txt");
let file_location = format!("{}{}", PACKAGE_PATH, METADATA_FILE_NAME);
let mut file = match File::open(file_location.clone()).await {
Ok(file) => file,
Err(_) => {
@ -98,7 +101,7 @@ async fn search_and_retrieve_metadata(
async fn save_metadata(package_name: String) -> Result<(), std::io::Error> {
let searched = search_metadata(package_name.to_owned()).await?;
if searched.is_none() {
let file_location = format!("{}{}", PACKAGE_PATH, "metadata.txt");
let file_location = format!("{}{}", PACKAGE_PATH, METADATA_FILE_NAME);
let mut file = OpenOptions::new()
.append(true)
.create(true)
@ -118,7 +121,7 @@ async fn delete_metadata(package_name: String) -> Result<(), std::io::Error> {
None => return Err(std::io::ErrorKind::NotFound.into()),
};
let file_location = format!("{}{}", PACKAGE_PATH, "metadata.txt");
let file_location = format!("{}{}", PACKAGE_PATH, METADATA_FILE_NAME);
let mut file = OpenOptions::new()
.append(false)
.create(false)

View file

@ -18,6 +18,9 @@ impl Package {
pub fn get_name(&self) -> String {
self.name.clone()
}
pub fn get_hash(&self) -> Vec<u8> {
self.hash.to_vec()
}
}
impl Default for Package {

View file

@ -1,5 +1,7 @@
use std::env;
use crate::file::calculate_hash;
fn env_collector() -> Vec<String> {
let mut env_values = env::args().collect::<Vec<String>>();
env_values.remove(0);
@ -47,6 +49,25 @@ pub async fn user_interaction() {
delete_package(package_name).await;
return;
}
"list_installed_packages" => {
list_installed_packages().await;
return;
}
"update_package" => {
let package_name = match env_values.get(i + 1) {
Some(package_name) => package_name,
None => {
eprintln!("Length is not enough");
return;
}
};
update_package(package_name).await;
return;
}
"update_all_packages" => {
update_all_packages().await;
return;
}
_ => {
eprintln!("Need an Argument");
return;
@ -92,3 +113,65 @@ async fn delete_package(package_name: &String) {
Err(err_val) => eprintln!("Error: Delete Package | {}", err_val),
}
}
async fn list_installed_packages() {
match crate::file::list_installed_packages().await {
Ok(package_names) => {
if package_names.is_empty() {
println!("There is no installed package");
return;
}
for package_name in package_names {
println!("{}", package_name);
}
}
Err(err_val) => eprintln!("Error: List Installed Packages | {}", err_val),
}
}
async fn update_package(package_name: &String) {
let target_package_local_hash = match calculate_hash(package_name.to_owned()).await {
Ok(target_package_local_hash) => match target_package_local_hash {
Some(target_package_local_hash) => target_package_local_hash,
None => {
eprintln!(
"Error: No Metadata Found for Local Hash Calculation | {}",
package_name
);
return;
}
},
Err(err_val) => {
eprintln!(
"Error: Local Hash Calculation | {} | {}",
package_name, err_val
);
return;
}
};
match crate::request::read_package(package_name.to_owned()).await {
Some(package) => match package.get_hash().eq(&target_package_local_hash) {
true => println!("Package is Already Up to Date"),
false => {
println!("New Version is Found, Installing");
install_package(package_name).await;
}
},
None => eprintln!("Error: Update Package | {}", package_name),
}
}
async fn update_all_packages() {
match crate::file::list_installed_packages().await {
Ok(package_names) => {
if package_names.is_empty() {
println!("There is no installed package");
return;
}
for package_name in package_names {
update_package(&package_name).await;
}
}
Err(err_val) => eprintln!("Error: List Installed Packages | {}", err_val),
}
}