use crate::constants::DEFAULT_REMOTE_NAME;
use crate::error::OxenError;
use crate::model::{LocalRepository, RemoteRepository};
use crate::opts::CloneOpts;
use crate::{api, repositories, util};
use colored::Colorize;
use std::path::Path;
use uuid::Uuid;
pub async fn clone_repo(
remote_repo: RemoteRepository,
opts: &CloneOpts,
) -> Result<LocalRepository, OxenError> {
api::client::repositories::pre_clone(&remote_repo).await?;
let repo_path = &opts.dst;
if repo_path.exists() {
let err = format!("Directory already exists: {}", repo_path.to_string_lossy());
return Err(OxenError::basic_str(err));
}
util::fs::create_dir_all(repo_path)?;
let oxen_hidden_path = util::fs::oxen_hidden_dir(repo_path);
util::fs::create_dir_all(&oxen_hidden_path)?;
let mut local_repo = LocalRepository::from_remote(remote_repo.clone(), repo_path)?;
repo_path.clone_into(&mut local_repo.path);
local_repo.set_remote(DEFAULT_REMOTE_NAME, &remote_repo.remote.url);
local_repo.set_min_version(remote_repo.min_version());
local_repo.set_subtree_paths(opts.fetch_opts.subtree_paths.clone());
local_repo.set_depth(opts.fetch_opts.depth);
local_repo.set_version_store(&opts.storage_opts).await?;
if opts.is_vfs {
local_repo.set_vfs(Some(true));
} else {
local_repo.set_vfs(None);
}
local_repo.save()?;
if remote_repo.is_empty {
println!(
"The remote repository is empty. Oxen has configured the local repository, but there are no files yet."
);
return Ok(local_repo);
}
repositories::fetch::fetch_branch(&local_repo, &opts.fetch_opts).await?;
repositories::checkout::checkout(&local_repo, opts.fetch_opts.branch.as_str()).await?;
api::client::repositories::post_clone(&remote_repo).await?;
Ok(local_repo)
}
pub async fn clone_repo_remote_mode(
remote_repo: RemoteRepository,
opts: &CloneOpts,
) -> Result<LocalRepository, OxenError> {
api::client::repositories::pre_clone(&remote_repo).await?;
let repo_path = &opts.dst;
if repo_path.exists() {
let err = format!("Directory already exists: {}", repo_path.to_string_lossy());
return Err(OxenError::basic_str(err));
}
util::fs::create_dir_all(repo_path)?;
let oxen_hidden_path = util::fs::oxen_hidden_dir(repo_path);
util::fs::create_dir_all(&oxen_hidden_path)?;
let branch_name = &opts.fetch_opts.branch;
let workspace_id = Uuid::new_v4().to_string();
let name = format!("{}: {workspace_id}", branch_name.clone());
let mut local_repo = LocalRepository::from_remote(remote_repo.clone(), repo_path)?;
repo_path.clone_into(&mut local_repo.path);
local_repo.set_remote(DEFAULT_REMOTE_NAME, &remote_repo.remote.url);
local_repo.set_min_version(remote_repo.min_version());
local_repo.set_remote_mode(Some(true));
local_repo.set_version_store(&opts.storage_opts).await?;
if opts.is_vfs {
local_repo.set_vfs(Some(true));
} else {
local_repo.set_vfs(None);
}
let workspace = api::client::workspaces::create_with_path(
&remote_repo,
&branch_name,
&workspace_id,
Path::new("/"),
Some(name.clone()),
)
.await?;
match workspace.status.as_str() {
"resource_created" => {
println!(
"{}",
"Remote-mode repository initialized successfully!"
.green()
.bold()
);
}
"resource_found" => {
let err_msg = format!(
"Remote-mode repo for workspace {} already exists",
workspace_id.clone()
);
println!("{}", err_msg.yellow().bold());
return Err(OxenError::basic_str("Err: Cannot "));
}
other => {
println!("{}", format!("Unexpected workspace status: {other}").red());
}
}
println!("{} {}", "Workspace ID:".green().bold(), workspace.id.bold());
local_repo.add_workspace(name.clone());
local_repo.set_workspace(name.clone())?;
local_repo.save()?;
if remote_repo.is_empty {
println!(
"The remote repository is empty. Oxen has configured the local repository, but there are no files yet."
);
return Ok(local_repo);
}
repositories::fetch::fetch_branch(&local_repo, &opts.fetch_opts).await?;
repositories::branches::set_head(&local_repo, branch_name)?;
api::client::repositories::post_clone(&remote_repo).await?;
Ok(local_repo)
}