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, add::add_args};
pub const NAME: &str = "add";
pub struct WorkspaceAddCmd;
#[async_trait]
impl RunCmd for WorkspaceAddCmd {
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,
};
add_args()
.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(
Arg::new("directory")
.long("directory")
.short('d')
.help("The destination directory to add the workspace to")
.default_value("."),
)
.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, directory) = if repository.is_remote_mode() {
(&repository.workspace_name.clone().unwrap(), ".")
} else {
let directory = args.get_one::<String>("directory").unwrap();
let workspace_name = args.get_one::<String>("workspace-name");
let workspace_id = args.get_one::<String>("workspace-id");
match workspace_id {
Some(id) => (id, directory.as_str()),
None => {
if let Some(name) = workspace_name {
(name, directory.as_str())
} 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 add after filtering with .oxenignore.",
));
}
api::client::workspaces::files::add(
&remote_repo,
workspace_identifier,
directory,
paths,
&None,
)
.await?;
Ok(())
}
}