use clap::Parser;
use std::io::Write;
use futures::stream::StreamExt;
use std::path::PathBuf;
#[derive(Parser, Debug)]
#[command(author, version)]
struct Args {
#[clap(long)]
trust: bool,
#[clap(long)]
debug: bool,
#[clap(long)]
trace: bool,
#[clap(long)]
disable_net_access: bool,
#[clap(long)]
check: bool,
#[clap(default_value = ".")]
path: PathBuf,
#[clap(long)]
scan: bool,
#[clap(long)]
from_homepage: Option<url::Url>,
#[clap(long)]
from_repology: Option<String>,
#[clap(long)]
consult_external_directory: bool,
}
#[tokio::main]
async fn main() {
let args = Args::parse();
env_logger::builder()
.format(|buf, record| writeln!(buf, "{}", record.args()))
.filter(
None,
if args.trace {
log::LevelFilter::Trace
} else if args.debug {
log::LevelFilter::Debug
} else {
log::LevelFilter::Info
},
)
.init();
if let Some(from_homepage) = args.from_homepage {
for d in upstream_ontologist::homepage::guess_from_homepage(&from_homepage)
.await
.unwrap()
{
println!(
"{}: {:?} - certainty {} (from {:?})",
d.datum.field(),
d.datum,
d.certainty
.map_or_else(|| "unknown".to_string(), |d| d.to_string()),
d.origin
);
}
} else if let Some(id) = args.from_repology {
for d in upstream_ontologist::repology::find_upstream_from_repology(&id)
.await
.unwrap()
{
println!(
"{}: {:?} - certainty {} (from {:?})",
d.datum.field(),
d.datum,
d.certainty
.map_or_else(|| "unknown".to_string(), |d| d.to_string()),
d.origin
);
}
} else if args.scan {
let stream = upstream_ontologist::upstream_metadata_stream(
&args.path.canonicalize().unwrap(),
Some(args.trust),
);
tokio::pin!(stream);
while let Some(entry) = stream.next().await {
let entry = entry.unwrap();
println!(
"{}: {:?} - certainty {}{}",
entry.datum.field(),
entry.datum,
entry
.certainty
.map_or("unknown".to_string(), |c| c.to_string()),
entry
.origin
.map_or_else(|| "".to_string(), |o| format!(" (from {:?})", o))
);
}
} else {
let metadata = match upstream_ontologist::guess_upstream_metadata(
&args.path.canonicalize().unwrap(),
Some(args.trust),
Some(!args.disable_net_access),
Some(args.consult_external_directory),
Some(args.check),
)
.await
{
Ok(m) => m,
Err(upstream_ontologist::ProviderError::ParseError(e)) => {
eprintln!("Error parsing metadata: {}", e);
std::process::exit(1);
}
Err(upstream_ontologist::ProviderError::IoError(e)) => {
eprintln!("I/O Error: {}", e);
std::process::exit(1);
}
Err(upstream_ontologist::ProviderError::Other(e)) => {
eprintln!("Error: {}", e);
std::process::exit(1);
}
Err(upstream_ontologist::ProviderError::HttpJsonError(e)) => {
eprintln!("Error: {}", e);
std::process::exit(1);
}
Err(upstream_ontologist::ProviderError::ExtrapolationLimitExceeded(l)) => {
eprintln!("Extraoplation limit exceeded: {}", l);
std::process::exit(1);
}
};
let out = serde_yaml::to_value(&metadata).unwrap();
std::io::stdout()
.write_all(serde_yaml::to_string(&out).unwrap().as_bytes())
.unwrap();
}
}