gsutil 0.2.2

Incomplete replacement for the official gsutil
Documentation
use crate::{color::ColorCtx, util};
use anyhow::Context as _;

#[derive(clap::Parser, Debug)]
pub struct Args {
    /// The gs:// url to the object to stat
    url: url::Url,
}

pub async fn cmd(ctx: &util::RequestContext, args: Args) -> anyhow::Result<()> {
    let oid = util::gs_url_to_object_id(&args.url)?;
    let cc = ColorCtx::from_env();

    let get_req = ctx.obj.get(
        &(
            oid.bucket(),
            oid.object().context("invalid object name specified")?,
        ),
        None,
    )?;
    let get_res: tame_gcs::objects::GetObjectResponse = util::execute(ctx, get_req).await?;

    let md = get_res.metadata;

    // Print out the information the same way gsutil does, except with RFC-2822 date formatting
    println!("{}", cc.paint(nu_ansi_term::Color::Cyan, args.url.as_str()));
    println!(
        "    Creation time:\t{}",
        md.time_created
            .expect("time_created")
            .format(&time::format_description::well_known::Rfc2822)
            .unwrap()
    );
    println!(
        "    Update time:\t{}",
        md.updated
            .expect("updated")
            .format(&time::format_description::well_known::Rfc2822)
            .unwrap()
    );
    println!(
        "    Storage class:\t{}",
        md.storage_class.expect("storage_class")
    );
    println!("    Content-Length:\t{}", md.size.expect("size"));
    println!(
        "    Content-Type:\t{}",
        md.content_type.as_deref().unwrap_or("None")
    );

    if let Some(md) = &md.metadata {
        for (k, v) in md {
            println!("        {k}:\t\t{v}");
        }
    }

    println!("    Hash (crc32c):\t{}", md.crc32c.expect("crc32c"));
    println!("    Hash (md5):\t\t{}", md.md5_hash.expect("md5_hash"));
    println!("    ETag:\t\t{}", md.etag.expect("etag"));
    println!("    Generation:\t\t{}", md.generation.expect("generation"));
    println!(
        "    Metageneration:\t{}",
        md.metageneration.expect("metageneration")
    );

    Ok(())
}