feat: ✨ list_installed_packages, update_package, update_all_packages for client
This commit is contained in:
parent
0f0e05ef91
commit
4ba4e6fe30
3 changed files with 107 additions and 18 deletions
|
@ -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)
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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),
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue