nu_plugin_cloud 0.2.11+0.110.0

A nushell plugin for working with cloud storage services
Documentation
use std::{path::PathBuf, str::FromStr, vec};

use nu_plugin::{EngineInterface, PluginCommand};
use nu_protocol::{
    Category, Example, LabeledError, PipelineData, ShellError, Signature, Spanned, SyntaxShape,
    Type,
};
use object_store::ObjectStoreExt;
use url::Url;

use crate::CloudPlugin;

pub struct Remove;

impl PluginCommand for Remove {
    type Plugin = CloudPlugin;

    fn name(&self) -> &str {
        "cloud rm"
    }

    fn signature(&self) -> nu_protocol::Signature {
        Signature::build("cloud rm")
            .input_output_types(vec![(Type::Any, Type::Nothing)])
            .required("uri", SyntaxShape::String, "The file url to use.")
            .category(Category::FileSystem)
    }

    fn description(&self) -> &str {
        "Remove a file from cloud sotrage"
    }

    fn examples(&self) -> Vec<Example<'_>> {
        vec![Example {
            description: "Remove a file from s3.",
            example: "cloud rm s3://mybucket/file.txt",
            result: None,
        }]
    }

    fn run(
        &self,
        plugin: &Self::Plugin,
        engine: &EngineInterface,
        call: &nu_plugin::EvaluatedCall,
        _input: PipelineData,
    ) -> Result<PipelineData, LabeledError> {
        plugin
            .rt
            .block_on(command(engine, plugin, call))
            .map_err(LabeledError::from)
    }
}

async fn command(
    engine: &EngineInterface,
    plugin: &CloudPlugin,
    call: &nu_plugin::EvaluatedCall,
) -> Result<PipelineData, ShellError> {
    let call_span = call.head;
    let url_path: Spanned<PathBuf> = call.req(0)?;
    let url = url_path
        .item
        .to_str()
        .expect("The path should already be unicode")
        .to_string();
    let url = Spanned {
        item: Url::from_str(&url).map_err(|e| ShellError::IncorrectValue {
            msg: format!("Invalid Url: {e}"),
            val_span: url_path.span,
            call_span,
        })?,
        span: url_path.span,
    };
    let (object_store, path) = plugin.parse_url(engine, &url, call_span).await?;

    object_store
        .object_store()
        .delete(&path)
        .await
        .map_err(|e| ShellError::GenericError {
            error: format!("Could not delete delete from cloud storage: {e}"),
            msg: "".into(),
            span: Some(call_span),
            help: None,
            inner: vec![],
        })?;

    Ok(PipelineData::empty())
}