pub mod constants;
pub mod file_management;
pub mod upload;
pub mod utils;
use clap::Parser;
use std::io;
use std::io::Write;
use upload::upload_object;
use utils::check_for_config;
use utils::initialize_config;
use utils::print_warning;
#[tokio::main]
async fn main() -> Result<(), anyhow::Error> {
let arguments = utils::Args::parse();
utils::setup_logging(arguments.verbose);
log::trace!("Arguments parsed: {:?} ", &arguments);
if arguments.init {
log::trace!("The --init parameter has been passed");
if check_for_config() {
log::trace!("The configuration already exists");
print_warning("****************************************");
print_warning("WARNING:");
println!("You are trying to initialize the Shuk configuration");
println!("This will overwrite your configuration files in $HOME/.config/shuk/");
print!("ARE YOU SURE YOU WANT DO TO THIS? Y/N: ");
io::stdout().flush()?;
let mut confirmation = String::new();
io::stdin().read_line(&mut confirmation)?;
if confirmation.trim().eq_ignore_ascii_case("y") {
print_warning("I ask AGAIN");
print!("ARE YOU SURE YOU WANT DO TO THIS? Y/N: ");
io::stdout().flush()?;
let mut confirmation = String::new();
io::stdin().read_line(&mut confirmation)?;
if confirmation.trim().eq_ignore_ascii_case("y") {
println!("----------------------------------------");
println!("📜 | Initializing Shuk configuration.");
initialize_config().await?;
}
}
} else {
log::trace!("The configuration does not exist");
println!("----------------------------------------");
println!("📜 | Initializing Shuk configuration.");
initialize_config().await?;
}
print_warning("Shuk will now exit");
std::process::exit(0);
}
let shuk_config = match utils::Config::load_config() {
Ok(config) => {
log::trace!("The configuration is loaded from the file: {:#?}", &config);
config
},
Err(e) => {
eprintln!("Failed to load configuration. Make sure that your config file is located at ~/.config/shuk: {}", e);
std::process::exit(1);
}
};
let config = utils::configure_aws(
shuk_config
.fallback_region
.as_deref()
.unwrap_or("us-east-1")
.to_string(),
shuk_config.aws_profile.as_ref(),
)
.await;
let s3_client = aws_sdk_s3::Client::new(&config);
let key = arguments.filename.clone();
let file_name = arguments
.filename
.expect("Unable to determine the file name from the command line parameters");
let key_file_name = key
.as_ref()
.and_then(|path| path.file_name())
.and_then(|name| name.to_str())
.map(|s| s.trim_matches('"'))
.ok_or_else(|| anyhow::anyhow!("Invalid filename provided"))?;
let key_full = if shuk_config.bucket_prefix.is_some() {
format!(
"{}{}",
&shuk_config
.bucket_prefix
.clone()
.unwrap_or_else(|| "".into()),
&key_file_name
)
} else {
key_file_name.to_string()
};
let md5_of_file = file_management::calculate_partial_hash(&file_name.clone())?;
let file_tags = file_management::ObjectTags {
managed_by: "shuk".into(),
start_hash: md5_of_file.start_hash,
end_hash: md5_of_file.end_hash,
};
log::trace!("File tags defined: {:#?}", &file_tags);
let just_upload = match file_management::file_exists_in_s3(
&s3_client,
&shuk_config.bucket_name,
key_full.as_str(),
)
.await
{
Ok(o) => {
log::trace!("The call to check if the file exists has been a success");
if o {
if file_management::quick_compare(
&file_name,
&shuk_config.bucket_name,
key_full.as_str(),
&file_tags,
&s3_client,
)
.await?
{
true
} else {
false
}
} else {
false
}
}
Err(e) => {
eprintln!("Error: Could not determine if a the file exists - {}", e);
false
}
};
match upload_object(
&s3_client,
&file_name,
key_file_name,
file_tags,
just_upload,
&shuk_config,
)
.await
{
Ok(presigned_url) => {
if shuk_config.use_clipboard.unwrap_or(false) {
if let Err(e) = utils::set_into_clipboard(presigned_url) {
eprintln!("Error setting clipboard: {}", e);
}
}
}
Err(e) => {
eprintln!("Error uploading file: {}", e);
std::process::exit(1);
}
}
Ok(())
}