diff --git a/CHANGELOG.md b/CHANGELOG.md index 23e2910b..a9ffebbf 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/). - The metadata repositories can now contain source files. - Support for unpacking bzip2 file formats. - The `msvc` requirement now supports specifiying version bounds using `msvc@`. +- Add support for path inputs in the `checksum` command. ### Changes - The test environment now uses a fresh environment for each test and can be used in parallel. diff --git a/docs/commands/util.md b/docs/commands/util.md index 173e3bb4..3820fb8e 100644 --- a/docs/commands/util.md +++ b/docs/commands/util.md @@ -25,7 +25,7 @@ The `--exclude` flag specifies packages to exclude when using the `--all` flag. The `checksum` command has the following syntax:
`pit util checksum ` -The command calculates the checksum of the file at the given URL. It also shows the size of the downloaded file in bytes. +The command calculates the checksum of the file at the given URL or system path. It also shows the size of the downloaded file in bytes. ## Portable repository The `portable-repo` command has the following syntax:
diff --git a/src/cli/commands/util/checksum.rs b/src/cli/commands/util/checksum.rs index 1a7656c7..28a3877b 100644 --- a/src/cli/commands/util/checksum.rs +++ b/src/cli/commands/util/checksum.rs @@ -1,5 +1,5 @@ // SPDX-License-Identifier: GPL-3.0-only -use std::process::exit; +use std::{fs, path::PathBuf, process::exit, str::FromStr}; use clap::Args; use url::Url; @@ -10,24 +10,38 @@ use crate::{ display::{Spinner, logging::error}, }, repositories::types::Checksum, - utils::requests, + utils::{ioerror::IOResultExt, requests, unwrap_or_exit::UnwrapOrExit}, }; /// Calculates the checksum for the file at the given url. #[derive(Args, Debug)] pub struct ChecksumArgs { - /// The url to request the file from - url: Url, + /// The url or path to request the file from + url: String, } impl HandleCommand for ChecksumArgs { fn handle(&self) { - println!("Trying to request file from '{}'", self.url); + let bytes = match Url::from_str(&self.url) { + Ok(url) => self.get_bytes_from_url(url), + Err(_) => self.get_bytes_from_path(&PathBuf::from(self.url.clone())), + }; + + let checksum = Checksum::from_bytes(&bytes); - let spinner = Spinner::new("Downloading file".into()); + println!("Checksum: {}", checksum); + println!("File size: {}", bytes.len()); + } +} + +impl ChecksumArgs { + /// Gets the bytes from a given url. + fn get_bytes_from_url(&self, url: Url) -> Vec { + let message = format!("Downloading file from {}", self.url); + let spinner = Spinner::new(message); spinner.show(); - let response = match requests::get(self.url.as_str()) { + let response = match requests::get(url.as_str()) { Ok(response) => response, Err(e) => { error!(e, "Unable to request file"); @@ -40,18 +54,19 @@ impl HandleCommand for ChecksumArgs { exit(1); } - let bytes = match response.bytes() { - Ok(bytes) => bytes, + spinner.finish(); + + match response.bytes() { + Ok(bytes) => bytes.into(), Err(e) => { error!(e, "Unable to get file bytes"); exit(1); }, - }; - - let checksum = Checksum::from_bytes(&bytes); + } + } - spinner.finish(); - println!("Checksum: {}", checksum); - println!("File size: {}", bytes.len()); + /// Gets the bytes from a given path. + fn get_bytes_from_path(&self, path: &PathBuf) -> Vec { + fs::read(path).err_with_path("read", path).unwrap_or_exit(1) } }