Add --schema arg to list command
This commit is contained in:
@@ -1,5 +1,6 @@
|
|||||||
use anyhow::{Context, Result};
|
use anyhow::{Context, Result};
|
||||||
use clap::Args;
|
use clap::Args;
|
||||||
|
use pile_config::Label;
|
||||||
use pile_config::objectpath::ObjectPath;
|
use pile_config::objectpath::ObjectPath;
|
||||||
use pile_dataset::Datasets;
|
use pile_dataset::Datasets;
|
||||||
use pile_toolbox::cancelabletask::{CancelFlag, CancelableTaskError};
|
use pile_toolbox::cancelabletask::{CancelFlag, CancelableTaskError};
|
||||||
@@ -12,7 +13,7 @@ use crate::{CliCmd, GlobalContext};
|
|||||||
|
|
||||||
#[derive(Debug, Args)]
|
#[derive(Debug, Args)]
|
||||||
pub struct ListCommand {
|
pub struct ListCommand {
|
||||||
/// Path to query, e.g. $.flac.artist
|
/// Path to query, e.g. $.flac.artist (or schema field name when --schema is set)
|
||||||
#[clap(default_value = "$")]
|
#[clap(default_value = "$")]
|
||||||
path: String,
|
path: String,
|
||||||
|
|
||||||
@@ -20,6 +21,10 @@ pub struct ListCommand {
|
|||||||
#[arg(long)]
|
#[arg(long)]
|
||||||
invert: bool,
|
invert: bool,
|
||||||
|
|
||||||
|
/// Treat path as a schema field name and resolve via schema paths
|
||||||
|
#[arg(long)]
|
||||||
|
schema: bool,
|
||||||
|
|
||||||
/// Path to dataset config
|
/// Path to dataset config
|
||||||
#[arg(long, short = 'c', default_value = "./pile.toml")]
|
#[arg(long, short = 'c', default_value = "./pile.toml")]
|
||||||
config: PathBuf,
|
config: PathBuf,
|
||||||
@@ -44,14 +49,24 @@ impl CliCmd for ListCommand {
|
|||||||
_ctx: GlobalContext,
|
_ctx: GlobalContext,
|
||||||
flag: CancelFlag,
|
flag: CancelFlag,
|
||||||
) -> Result<i32, CancelableTaskError<anyhow::Error>> {
|
) -> Result<i32, CancelableTaskError<anyhow::Error>> {
|
||||||
let path = ObjectPath::from_str(&self.path)
|
|
||||||
.with_context(|| format!("invalid path {:?}", self.path))?;
|
|
||||||
let path = Arc::new(path);
|
|
||||||
|
|
||||||
let ds = Datasets::open(&self.config, &self.workdir)
|
let ds = Datasets::open(&self.config, &self.workdir)
|
||||||
.await
|
.await
|
||||||
.with_context(|| format!("while opening dataset for {}", self.config.display()))?;
|
.with_context(|| format!("while opening dataset for {}", self.config.display()))?;
|
||||||
|
|
||||||
|
// Resolve path arg: either schema field paths or a single ObjectPath
|
||||||
|
let schema_paths: Arc<Vec<ObjectPath>> = if self.schema {
|
||||||
|
let label = Label::new(&self.path)
|
||||||
|
.ok_or_else(|| anyhow::anyhow!("invalid schema field name {:?}", self.path))?;
|
||||||
|
let spec = ds.config.schema.get(&label).ok_or_else(|| {
|
||||||
|
anyhow::anyhow!("schema field {:?} not found in config", self.path)
|
||||||
|
})?;
|
||||||
|
Arc::new(spec.path.clone())
|
||||||
|
} else {
|
||||||
|
let path = ObjectPath::from_str(&self.path)
|
||||||
|
.with_context(|| format!("invalid path {:?}", self.path))?;
|
||||||
|
Arc::new(vec![path])
|
||||||
|
};
|
||||||
|
|
||||||
let jobs = self.jobs.max(1);
|
let jobs = self.jobs.max(1);
|
||||||
let state = ExtractState { ignore_mime: false };
|
let state = ExtractState { ignore_mime: false };
|
||||||
|
|
||||||
@@ -81,16 +96,20 @@ impl CliCmd for ListCommand {
|
|||||||
let item = item.clone();
|
let item = item.clone();
|
||||||
let source_name = name.to_string();
|
let source_name = name.to_string();
|
||||||
let key = item.key().to_string();
|
let key = item.key().to_string();
|
||||||
let path = path.clone();
|
let schema_paths = schema_paths.clone();
|
||||||
let invert = self.invert;
|
let invert = self.invert;
|
||||||
let state = state.clone();
|
let state = state.clone();
|
||||||
|
|
||||||
join_set.spawn(async move {
|
join_set.spawn(async move {
|
||||||
let item = PileValue::Item(item);
|
let pv = PileValue::Item(item);
|
||||||
let value = item.query(&state, &path).await?;
|
let mut is_present = false;
|
||||||
|
for path in schema_paths.as_ref() {
|
||||||
let is_present =
|
let value = pv.query(&state, path).await?;
|
||||||
matches!(value, Some(v) if !matches!(v, PileValue::Null));
|
if matches!(value, Some(v) if !matches!(v, PileValue::Null)) {
|
||||||
|
is_present = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
let should_print = if invert { !is_present } else { is_present };
|
let should_print = if invert { !is_present } else { is_present };
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user