Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Quality of Life improvements #211

Merged
merged 5 commits into from
Nov 14, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion omnibor-cli/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -28,14 +28,16 @@ path = "src/main.rs"

[dependencies]

anyhow = "1.0.80"
async-walkdir = "1.0.0"
clap = { version = "4.5.1", features = ["derive", "env"] }
clap-verbosity-flag = "2.2.2"
dirs = "5.0.1"
dyn-clone = "1.0.17"
futures-lite = "2.2.0"
omnibor = { version = "0.6.0", path = "../omnibor" }
pathbuf = "1.0.0"
serde_json = "1.0.114"
thiserror = "2.0.3"
tokio = { version = "1.36.0", features = [
"fs",
"io-std",
Expand Down
30 changes: 15 additions & 15 deletions omnibor-cli/src/cli.rs
Original file line number Diff line number Diff line change
@@ -1,19 +1,16 @@
//! Defines the Command Line Interface.

#![allow(unused)]

use anyhow::anyhow;
use omnibor::hashes::Sha256;
use omnibor::ArtifactId;
use omnibor::IntoArtifactId;
use crate::error::Error;
use clap_verbosity_flag::{InfoLevel, Verbosity};
use omnibor::{hashes::Sha256, ArtifactId, IntoArtifactId};
use pathbuf::pathbuf;
use std::default::Default;
use std::fmt::Display;
use std::fmt::Formatter;
use std::path::Path;
use std::path::PathBuf;
use std::str::FromStr;
use std::sync::OnceLock;
use std::{
default::Default,
fmt::{Display, Formatter},
path::{Path, PathBuf},
str::FromStr,
sync::OnceLock,
};

// The default root directory for OmniBOR.
// We use a `static` here to make sure we can safely give out
Expand Down Expand Up @@ -71,6 +68,9 @@ pub struct Config {
)]
dir: Option<PathBuf>,

#[command(flatten)]
pub verbose: Verbosity<InfoLevel>,

#[command(subcommand)]
command: Option<Command>,
}
Expand Down Expand Up @@ -234,13 +234,13 @@ pub enum IdentifiableArg {
}

impl FromStr for IdentifiableArg {
type Err = anyhow::Error;
type Err = Error;

fn from_str(s: &str) -> Result<Self, Self::Err> {
match (ArtifactId::from_str(s), PathBuf::from_str(s)) {
(Ok(aid), _) => Ok(IdentifiableArg::ArtifactId(aid)),
(_, Ok(path)) => Ok(IdentifiableArg::Path(path)),
(Err(_), Err(_)) => Err(anyhow!("input not recognized as Artifact ID or file path")),
(Err(_), Err(_)) => Err(Error::NotIdentifiable(s.to_string())),
}
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
//! The `artifact find` command, which finds files by ID.

use crate::cli::Config;
use crate::cli::FindArgs;
use crate::cli::SelectedHash;
use crate::fs::*;
use crate::print::PrinterCmd;
use anyhow::Result;
use crate::{
cli::{Config, FindArgs, SelectedHash},
error::{Error, Result},
fs::*,
print::{error::ErrorMsg, find_file::FindFileMsg, PrinterCmd},
};
use async_walkdir::WalkDir;
use futures_lite::stream::StreamExt as _;
use tokio::sync::mpsc::Sender;
Expand All @@ -21,7 +21,16 @@ pub async fn run(tx: &Sender<PrinterCmd>, config: &Config, args: &FindArgs) -> R
loop {
match entries.next().await {
None => break,
Some(Err(e)) => tx.send(PrinterCmd::error(e, config.format())).await?,
Some(Err(source)) => tx
.send(PrinterCmd::msg(
ErrorMsg::new(Error::WalkDirFailed {
path: path.to_path_buf(),
source,
}),
config.format(),
))
.await
.map_err(|_| Error::PrintChannelClose)?,
Some(Ok(entry)) => {
let path = &entry.path();

Expand All @@ -33,8 +42,15 @@ pub async fn run(tx: &Sender<PrinterCmd>, config: &Config, args: &FindArgs) -> R
let file_url = hash_file(SelectedHash::Sha256, &mut file, path).await?;

if url == file_url {
tx.send(PrinterCmd::find(path, &url, config.format()))
.await?;
tx.send(PrinterCmd::msg(
FindFileMsg {
path: path.to_path_buf(),
id: url.clone(),
},
config.format(),
))
.await
.map_err(|_| Error::PrintChannelClose)?;
}
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,17 +1,18 @@
//! The `artifact id` command, which identifies files.

use crate::cli::Config;
use crate::cli::IdArgs;
use crate::fs::*;
use crate::print::PrinterCmd;
use anyhow::Result;
use crate::{
cli::{Config, IdArgs},
error::Result,
fs::*,
print::PrinterCmd,
};
use tokio::sync::mpsc::Sender;

/// Run the `artifact id` subcommand.
pub async fn run(tx: &Sender<PrinterCmd>, config: &Config, args: &IdArgs) -> Result<()> {
let mut file = open_async_file(&args.path).await?;

if file_is_dir(&file).await? {
if file_is_dir(&file, &args.path).await? {
id_directory(tx, &args.path, config.format(), config.hash()).await?;
} else {
id_file(tx, &mut file, &args.path, config.format(), config.hash()).await?;
Expand Down
2 changes: 2 additions & 0 deletions omnibor-cli/src/cmd/artifact/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
pub mod find;
pub mod id;
19 changes: 19 additions & 0 deletions omnibor-cli/src/cmd/debug/config.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
//! The `debug config` command, which helps debug the CLI configuration.

use crate::{
cli::Config,
error::{Error, Result},
print::{root_dir::RootDirMsg, PrinterCmd},
};
use tokio::sync::mpsc::Sender;

/// Run the `debug config` subcommand.
pub async fn run(tx: &Sender<PrinterCmd>, config: &Config) -> Result<()> {
let root = config.dir().ok_or(Error::NoRoot)?.to_path_buf();

tx.send(PrinterCmd::msg(RootDirMsg { path: root }, config.format()))
.await
.map_err(|_| Error::PrintChannelClose)?;

Ok(())
}
1 change: 1 addition & 0 deletions omnibor-cli/src/cmd/debug/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
pub mod config;
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
//! The `manifest add` command, which adds manifests.

use crate::cli::Config;
use crate::cli::ManifestAddArgs;
use crate::print::PrinterCmd;
use anyhow::Result;
use crate::{
cli::{Config, ManifestAddArgs},
error::Result,
print::PrinterCmd,
};
use tokio::sync::mpsc::Sender;

/// Run the `manifest add` subcommand.
Expand Down
51 changes: 51 additions & 0 deletions omnibor-cli/src/cmd/manifest/create.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
//! The `manifest create` command, which creates manifests.

use crate::{
cli::{Config, ManifestCreateArgs},
error::{Error, Result},
print::PrinterCmd,
};
use omnibor::{
embedding::NoEmbed, hashes::Sha256, storage::FileSystemStorage, InputManifestBuilder,
IntoArtifactId, RelationKind,
};
use tokio::sync::mpsc::Sender;
use tracing::info;

/// Run the `manifest create` subcommand.
pub async fn run(
_tx: &Sender<PrinterCmd>,
config: &Config,
args: &ManifestCreateArgs,
) -> Result<()> {
let root = config.dir().ok_or_else(|| Error::NoRoot)?;

info!(root = %root.display());

let storage = FileSystemStorage::new(root).map_err(Error::StorageInitFailed)?;

let mut builder = InputManifestBuilder::<Sha256, NoEmbed, _>::with_storage(storage);

for input in &args.inputs {
let aid = input.clone().into_artifact_id().map_err(Error::IdFailed)?;
builder
.add_relation(RelationKind::Input, aid)
.map_err(Error::AddRelationFailed)?;
}

if let Some(built_by) = &args.built_by {
let aid = built_by
.clone()
.into_artifact_id()
.map_err(Error::IdFailed)?;
builder
.add_relation(RelationKind::BuiltBy, aid)
.map_err(Error::AddRelationFailed)?;
}

builder
.finish(&args.target)
.map_err(Error::ManifestBuildFailed)?;

Ok(())
}
3 changes: 3 additions & 0 deletions omnibor-cli/src/cmd/manifest/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
pub mod add;
pub mod create;
pub mod remove;
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
//! The `manifest remove` command, which removes manifests.

use crate::cli::Config;
use crate::cli::ManifestRemoveArgs;
use crate::print::PrinterCmd;
use anyhow::Result;
use crate::{
cli::{Config, ManifestRemoveArgs},
error::Result,
print::PrinterCmd,
};
use tokio::sync::mpsc::Sender;

/// Run the `manifest remove` subcommand.
Expand Down
5 changes: 5 additions & 0 deletions omnibor-cli/src/cmd/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
//! Defines individual subcommands.

pub mod artifact;
pub mod debug;
pub mod manifest;
13 changes: 0 additions & 13 deletions omnibor-cli/src/debug_config.rs

This file was deleted.

67 changes: 67 additions & 0 deletions omnibor-cli/src/error.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
//! Error types.

use omnibor::Error as OmniborError;
use std::{io::Error as IoError, path::PathBuf, result::Result as StdResult};

#[derive(Debug, thiserror::Error)]
pub enum Error {
#[error("could not identify '{0}'")]
NotIdentifiable(String),

#[error("could not find root directory")]
NoRoot,

#[error("failed to initialize file system storage")]
StorageInitFailed(#[source] OmniborError),

#[error("failed to generate Artifact ID")]
IdFailed(#[source] OmniborError),

#[error("failed to add relation to Input Manifest")]
AddRelationFailed(#[source] OmniborError),

#[error("failed to build Input Manifest")]
ManifestBuildFailed(#[source] OmniborError),

#[error("failed to write to stdout")]
StdoutWriteFailed(#[source] IoError),

#[error("failed to write to stderr")]
StderrWriteFailed(#[source] IoError),

#[error("failed walking under directory '{}'", path.display())]
WalkDirFailed { path: PathBuf, source: IoError },

#[error("unable to identify file type for '{}'", path.display())]
UnknownFileType {
path: PathBuf,
#[source]
source: IoError,
},

#[error("failed to open file '{}'", path.display())]
FileFailedToOpen {
path: PathBuf,
#[source]
source: IoError,
},

#[error("failed to get file metadata '{}'", path.display())]
FileFailedMetadata {
path: PathBuf,
#[source]
source: IoError,
},

#[error("failed to make Artifact ID for '{}'", path.display())]
FileFailedToId {
path: PathBuf,
#[source]
source: OmniborError,
},

#[error("print channel closed")]
PrintChannelClose,
}

pub type Result<T> = StdResult<T, Error>;
Loading