rework cli interface

This commit is contained in:
Robin Appelman 2025-06-21 14:07:22 +02:00
commit 182b067fad
2 changed files with 72 additions and 34 deletions

View file

@ -6,7 +6,7 @@ hashes.
## Usage ## Usage
```bash ```bash
cargo r -- <app id> --depot <depot id> depot-prefetch fetch <app id> --depot <depot id>
``` ```
`--depot` can be specified multiple times, or left out to fetch all available `--depot` can be specified multiple times, or left out to fetch all available
@ -15,8 +15,13 @@ depots.
You can find depot id's for an app on You can find depot id's for an app on
[steamdb](https://steamdb.info/app/232250/depots/). [steamdb](https://steamdb.info/app/232250/depots/).
If you only care about knowing the latest manifest, you can pass `--dont-fetch` If you only care about knowing the latest manifest, you can use
to disable pre-fetching the manifest's data.
```bash
depot-prefetch manifest <app id> --depot <depot id>
```
instead.
## Output ## Output

View file

@ -1,15 +1,29 @@
use crate::prefetch::prefetch;
use crate::product_info::{ProductInfoError, ProductInfoFetcher};
use clap::Parser; use clap::Parser;
use crate::product_info::ProductInfoFetcher;
use main_error::MainResult; use main_error::MainResult;
use serde::Serialize; use serde::Serialize;
use crate::prefetch::prefetch;
mod product_info;
mod error; mod error;
mod prefetch; mod prefetch;
mod product_info;
#[derive(Debug, Parser)] #[derive(Debug, Parser)]
struct Args { struct Args {
#[command(subcommand)]
command: Command,
}
#[derive(Debug, Parser)]
enum Command {
/// Get the latest manifest and pre-fetch it
Fetch(ProductArgs),
/// Get the latest manifest without fetching
Manifest(ProductArgs),
}
#[derive(Debug, Parser)]
struct ProductArgs {
/// App to prefetch depots for /// App to prefetch depots for
app_id: u32, app_id: u32,
/// Branch to prefetch, defaults to "public" /// Branch to prefetch, defaults to "public"
@ -18,8 +32,6 @@ struct Args {
/// Only prefetch the listed depot(s) /// Only prefetch the listed depot(s)
#[clap(long)] #[clap(long)]
depot: Vec<u32>, depot: Vec<u32>,
#[clap(long)]
dont_fetch: bool,
} }
#[tokio::main] #[tokio::main]
@ -27,37 +39,58 @@ async fn main() -> MainResult {
let args = Args::parse(); let args = Args::parse();
let info_fetcher = ProductInfoFetcher::new().await?; let info_fetcher = ProductInfoFetcher::new().await?;
let depots = info_fetcher.fetch_depots(args.app_id).await?;
let manifests = depots.into_iter() match args.command {
.filter(|(depot_id, _)| args.depot.is_empty() || args.depot.contains(depot_id)) Command::Fetch(args) => {
.flat_map(|(depot_id, depot)| depot.branches.into_iter().map(move |(branch, manifest)| (depot_id, branch, manifest))) let inputs = get_manifests(&info_fetcher, &args).await?;
.filter(|(_, branch, _)| &args.branch == branch) let outputs = inputs.into_iter()
.map(|(depot_id, _, manifest)| ManifestInput { .map(|input| {
app_id: args.app_id, prefetch(&input).map(|hash| ManifestOutput {
depot_id, app_id: input.app_id,
manifest: manifest.gid, depot_id: input.depot_id,
}); manifest: input.manifest,
hash,
})
})
.collect::<Result<Vec<_>, _>>()?;
if args.dont_fetch { serde_json::to_writer_pretty(std::io::stdout(), &outputs)?;
let inputs = manifests.collect::<Vec<_>>(); }
serde_json::to_writer_pretty(std::io::stdout(), &inputs)?; Command::Manifest(args) => {
} else { let inputs = get_manifests(&info_fetcher, &args).await?;
let outputs = manifests.map(|input| { serde_json::to_writer_pretty(std::io::stdout(), &inputs)?;
prefetch(&input).map(|hash| ManifestOutput { }
app_id: input.app_id,
depot_id: input.depot_id,
manifest: input.manifest,
hash,
})
}).collect::<Result<Vec<_>, _>>()?;
serde_json::to_writer_pretty(std::io::stdout(), &outputs)?;
} }
Ok(()) Ok(())
} }
async fn get_manifests(
info_fetcher: &ProductInfoFetcher,
product_args: &ProductArgs,
) -> Result<Vec<ManifestInput>, ProductInfoError> {
let depots = info_fetcher.fetch_depots(product_args.app_id).await?;
Ok(depots
.into_iter()
.filter(|(depot_id, _)| {
product_args.depot.is_empty() || product_args.depot.contains(depot_id)
})
.flat_map(|(depot_id, depot)| {
depot
.branches
.into_iter()
.map(move |(branch, manifest)| (depot_id, branch, manifest))
})
.filter(|(_, branch, _)| &product_args.branch == branch)
.map(|(depot_id, _, manifest)| ManifestInput {
app_id: product_args.app_id,
depot_id,
manifest: manifest.gid,
})
.collect())
}
#[derive(Debug, Serialize)] #[derive(Debug, Serialize)]
struct ManifestInput { struct ManifestInput {
app_id: u32, app_id: u32,