Skip to content

Commit

Permalink
feat(download): introduce ability to download arbitrary files
Browse files Browse the repository at this point in the history
  • Loading branch information
QaidVoid committed Oct 11, 2024
1 parent c2409fe commit 7f7339a
Show file tree
Hide file tree
Showing 4 changed files with 91 additions and 0 deletions.
9 changes: 9 additions & 0 deletions src/cli.rs
Original file line number Diff line number Diff line change
Expand Up @@ -109,4 +109,13 @@ pub enum Commands {
#[arg(required = true)]
package: String,
},

/// Download arbitrary files
#[command(arg_required_else_help = true)]
#[clap(name = "download", visible_alias = "dl")]
Download {
/// Links to files
#[arg(required = true)]
links: Vec<String>,
},
}
5 changes: 5 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use anyhow::Result;
use clap::Parser;
use cli::{Args, Commands};
use misc::download::download_and_save;
use registry::PackageRegistry;

use core::{
Expand All @@ -10,6 +11,7 @@ use core::{

mod cli;
mod core;
mod misc;
mod registry;

pub async fn init() -> Result<()> {
Expand Down Expand Up @@ -54,6 +56,9 @@ pub async fn init() -> Result<()> {
Commands::Use { package } => {
registry.use_package(&package).await?;
}
Commands::Download { links } => {
download_and_save(links.as_ref()).await?;
}
};

Ok(())
Expand Down
76 changes: 76 additions & 0 deletions src/misc/download.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
use std::{fs::Permissions, os::unix::fs::PermissionsExt, path::Path};

use anyhow::{Context, Result};
use chrono::Utc;
use futures::StreamExt;
use reqwest::Url;
use tokio::fs;

use crate::core::util::format_bytes;

fn extract_filename(url: &str) -> String {
Path::new(url)
.file_name()
.map(|name| name.to_string_lossy().to_string())
.unwrap_or_else(|| {
let dt = Utc::now().timestamp();
dt.to_string()
})
}

fn is_elf(content: &[u8]) -> bool {
let magic_bytes = &content[..4.min(content.len())];
let elf_bytes = [0x7f, 0x45, 0x4c, 0x46];
magic_bytes == elf_bytes
}

async fn download(url: &str) -> Result<()> {
let client = reqwest::Client::new();
let response = client.get(url).send().await?;

if !response.status().is_success() {
return Err(anyhow::anyhow!(
"Error fetching {} [{}]",
url,
response.status()
));
}

let filename = extract_filename(url);
let mut content = Vec::new();

println!(
"Downloading file from {} [{}]",
url,
format_bytes(response.content_length().unwrap_or_default())
);

let mut stream = response.bytes_stream();

while let Some(chunk) = stream.next().await {
let chunk = chunk.context("Failed to read chunk")?;
content.extend_from_slice(&chunk);
}

fs::write(&filename, &content).await?;

if is_elf(&content) {
fs::set_permissions(&filename, Permissions::from_mode(0o755)).await?;
}

println!("Downloaded {}", filename);

Ok(())
}

pub async fn download_and_save(links: &[String]) -> Result<()> {
for link in links {
if let Ok(url) = Url::parse(link) {
download(url.as_str()).await?;
} else {
eprintln!("{} is not a valid URL", link);
};
}

Ok(())
}
1 change: 1 addition & 0 deletions src/misc/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
pub mod download;

0 comments on commit 7f7339a

Please sign in to comment.