use std::path::PathBuf;
use async_trait::async_trait;
use clap::{Arg, ArgGroup, ArgMatches, Command};
use liboxen::{api, core::oxenignore, error::OxenError, model::LocalRepository};
use crate::cmd::RunCmd;
pub const NAME: &str = "rm";
pub struct WorkspaceRmCmd;
#[async_trait]
impl RunCmd for WorkspaceRmCmd {
fn name(&self) -> &str {
NAME
}
fn args(&self) -> Command {
let is_remote_repo = match LocalRepository::from_current_dir() {
Ok(repo) => repo.is_remote_mode(),
Err(_) => false,
};
Command::new(NAME)
.about("Removes the specified files from the index")
.arg(
Arg::new("files")
.required(true)
.action(clap::ArgAction::Append),
)
.arg(
Arg::new("staged")
.long("staged")
.help("Removes the file from the staging area.")
.action(clap::ArgAction::SetTrue),
)
.arg(
Arg::new("workspace-id")
.long("workspace-id")
.short('w')
.help("The workspace ID of the workspace")
.conflicts_with("workspace-name"),
)
.arg(
Arg::new("workspace-name")
.long("workspace-name")
.short('n')
.help("The name of the workspace")
.conflicts_with("workspace-id"),
)
.group(
ArgGroup::new("workspace-identifier")
.args(["workspace-id", "workspace-name"])
.required(!is_remote_repo),
)
.arg_required_else_help(true)
}
async fn run(&self, args: &ArgMatches) -> Result<(), OxenError> {
let mut paths: Vec<PathBuf> = args
.get_many::<String>("files")
.expect("Must supply files")
.map(PathBuf::from)
.collect();
let repository = LocalRepository::from_current_dir()?;
let workspace_identifier = if repository.is_remote_mode() {
&repository.workspace_name.clone().unwrap()
} else {
let workspace_name = args.get_one::<String>("workspace-name");
let workspace_id = args.get_one::<String>("workspace-id");
match workspace_id {
Some(id) => id,
None => {
if let Some(name) = workspace_name {
name
} else {
return Err(OxenError::basic_str(
"Either workspace-id or workspace-name must be provided.",
));
}
}
}
};
let remote_repo = api::client::repositories::get_default_remote(&repository).await?;
let ignore = oxenignore::create(&repository);
if let Some(ignore) = &ignore {
paths.retain(|path| !ignore.matched(path, path.is_dir()).is_ignore());
}
if paths.is_empty() {
return Err(OxenError::basic_str(
"No files to remove after filtering with .oxenignore.",
));
}
if args.get_flag("staged") {
api::client::workspaces::files::rm_files_from_staged(
&repository,
&remote_repo,
workspace_identifier,
paths,
)
.await?;
} else {
api::client::workspaces::files::rm_files(
&repository,
&remote_repo,
workspace_identifier,
paths,
)
.await?;
}
Ok(())
}
}