Skip to content

Commit 3c979dd

Browse files
feat(cli): add manifest find command
This adds a new `manifest find` command, which works similarly to `id find`, but instead searches for build inputs across Input Manifests. Signed-off-by: Andrew Lilley Brinker <alilleybrinker@gmail.com>
1 parent 54c44b9 commit 3c979dd

File tree

8 files changed

+138
-0
lines changed

8 files changed

+138
-0
lines changed

omnibor-cli/src/cli.rs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -180,6 +180,8 @@ pub struct ManifestArgs {
180180
pub enum ManifestCommand {
181181
/// Create a new manifest and add it to the store
182182
Create(ManifestCreateArgs),
183+
/// Find manifests containing an Artifact ID.
184+
Find(ManifestFindArgs),
183185
}
184186

185187
#[derive(Debug, clap::Args)]
@@ -202,6 +204,18 @@ pub struct ManifestCreateArgs {
202204
pub store: bool,
203205
}
204206

207+
#[derive(Debug, clap::Args)]
208+
#[command(arg_required_else_help = true)]
209+
pub struct ManifestFindArgs {
210+
/// Artifact ID to match
211+
#[arg(short = 'a', long = "aid", help_heading = IMPORTANT)]
212+
pub aid: ArtifactId<Sha256>,
213+
214+
/// The root path to search under
215+
#[arg(short = 'p', long = "path", help_heading = IMPORTANT)]
216+
pub path: PathBuf,
217+
}
218+
205219
#[derive(Debug, clap::Args)]
206220
#[command(arg_required_else_help = true)]
207221
pub struct StoreArgs {

omnibor-cli/src/cmd/manifest/find.rs

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
//! The `manifest find` command, which searches in manifests.
2+
3+
use crate::{
4+
app::App,
5+
cli::{Format, ManifestFindArgs},
6+
error::{Error, Result},
7+
fs::*,
8+
print::{msg::manifest_find::ManifestFindMsg, PrintSender, PrinterCmd},
9+
};
10+
use async_channel::{bounded, Receiver};
11+
use futures_lite::stream::StreamExt as _;
12+
use futures_util::pin_mut;
13+
use omnibor::{hash_algorithm::Sha256, ArtifactId, InputManifest};
14+
use std::path::PathBuf;
15+
use tokio::task::JoinSet;
16+
use tracing::debug;
17+
18+
/// Run the `manifest find` subcommand.
19+
pub async fn run(app: &App, args: &ManifestFindArgs) -> Result<()> {
20+
let ManifestFindArgs { aid, path } = args;
21+
22+
let (sender, receiver) = bounded(app.config.perf.work_queue_size());
23+
24+
tokio::spawn(walk_target(
25+
sender,
26+
app.print_tx.clone(),
27+
app.args.format(),
28+
path.to_path_buf(),
29+
));
30+
31+
let mut join_set = JoinSet::new();
32+
33+
let num_workers = app.config.perf.num_workers();
34+
debug!(num_workers = %num_workers);
35+
36+
for _ in 0..num_workers {
37+
join_set.spawn(open_and_match_manifests(
38+
receiver.clone(),
39+
app.print_tx.clone(),
40+
app.args.format(),
41+
*aid,
42+
));
43+
}
44+
45+
while let Some(result) = join_set.join_next().await {
46+
result.map_err(Error::CouldNotJoinWorker)??;
47+
}
48+
49+
Ok(())
50+
}
51+
52+
async fn open_and_match_manifests(
53+
path_rx: Receiver<PathBuf>,
54+
tx: PrintSender,
55+
format: Format,
56+
target_aid: ArtifactId<Sha256>,
57+
) -> Result<()> {
58+
pin_mut!(path_rx);
59+
60+
while let Some(path) = path_rx.next().await {
61+
if let Ok(manifest) = InputManifest::<Sha256>::from_path(&path) {
62+
if manifest.contains_input(target_aid) {
63+
tx.send(PrinterCmd::msg(
64+
ManifestFindMsg {
65+
path: path.to_path_buf(),
66+
manifest: manifest.clone(),
67+
},
68+
format,
69+
))
70+
.await?;
71+
}
72+
}
73+
}
74+
75+
Ok(())
76+
}

omnibor-cli/src/cmd/manifest/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
11
pub mod create;
2+
pub mod find;

omnibor-cli/src/main.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,7 @@ async fn run_cmd(app: &App) -> Result<()> {
7272
},
7373
Command::Manifest(ref args) => match args.command {
7474
ManifestCommand::Create(ref args) => manifest::create::run(app, args).await,
75+
ManifestCommand::Find(ref args) => manifest::find::run(app, args).await,
7576
},
7677
Command::Store(ref args) => match args.command {
7778
StoreCommand::Add(ref args) => store::add::run(app, args).await,
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
use crate::print::{CommandOutput, Status};
2+
use omnibor::{hash_algorithm::Sha256, InputManifest};
3+
use std::path::PathBuf;
4+
5+
#[derive(Debug, Clone)]
6+
pub struct ManifestFindMsg {
7+
/// The path the Manifest was found in.
8+
pub path: PathBuf,
9+
/// The Input Manifest
10+
pub manifest: InputManifest<Sha256>,
11+
}
12+
13+
impl CommandOutput for ManifestFindMsg {
14+
fn plain_output(&self) -> String {
15+
let mut output = String::new();
16+
17+
output.push_str(&format!("Found in '{}'\n", self.path.display()));
18+
19+
output.push_str(&self.manifest.header().to_string());
20+
21+
for relation in self.manifest.relations() {
22+
output.push_str(&relation.to_string());
23+
}
24+
25+
output
26+
}
27+
28+
fn short_output(&self) -> String {
29+
self.plain_output()
30+
}
31+
32+
fn json_output(&self) -> serde_json::Value {
33+
serde_json::json!({"path": self.path.display().to_string(), "manifest": self.plain_output()})
34+
}
35+
36+
fn status(&self) -> Status {
37+
Status::Success
38+
}
39+
}

omnibor-cli/src/print/msg/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ pub mod error;
22
pub mod find_file;
33
pub mod id_file;
44
pub mod manifest_create;
5+
pub mod manifest_find;
56
pub mod paths;
67
pub mod store_get;
78
pub mod store_remove;

omnibor-cli/tests/snapshots/test__manifest_no_args.snap

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ Usage: omnibor manifest [OPTIONS] <COMMAND>
1616

1717
Commands:
1818
create Create a new manifest and add it to the store
19+
find Find manifests containing an Artifact ID
1920
help Print this message or the help of the given subcommand(s)
2021

2122
Options:

omnibor/src/input_manifest/input_manifest.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,11 @@ impl<H: HashAlgorithm> InputManifest<H> {
8888
&self.relations[..]
8989
}
9090

91+
/// Check if the manifest contains the given input.
92+
pub fn contains_input(&self, input_aid: ArtifactId<H>) -> bool {
93+
self.relations().iter().any(|rel| rel.artifact == input_aid)
94+
}
95+
9196
/// Construct an [`InputManifest`] from a file at a specified path.
9297
pub fn from_path(path: &Path) -> Result<Self, InputManifestError> {
9398
let file = BufReader::new(

0 commit comments

Comments
 (0)