use crate::api;
use crate::core::index::{pusher, EntryIndexer};
use crate::error::OxenError;
use crate::model::{Branch, LocalRepository, RemoteBranch, RemoteRepository};
pub async fn push(repo: &LocalRepository) -> Result<RemoteRepository, OxenError> {
let indexer = EntryIndexer::new(repo)?;
let mut rb = RemoteBranch::default();
if let Some(current_branch) = api::local::branches::current_branch(repo)? {
rb.branch = current_branch.name;
}
indexer.push(&rb).await
}
pub async fn push_remote_branch(
repo: &LocalRepository,
remote: &str,
branch: &str,
) -> Result<RemoteRepository, OxenError> {
let indexer = EntryIndexer::new(repo)?;
let rb = RemoteBranch {
remote: String::from(remote),
branch: String::from(branch),
};
indexer.push(&rb).await
}
pub async fn push_remote_repo_branch(
local_repo: LocalRepository,
remote_repo: RemoteRepository,
branch: Branch,
) -> Result<RemoteRepository, OxenError> {
pusher::push_remote_repo(&local_repo, remote_repo, branch).await
}
pub async fn push_remote_repo_branch_name(
local_repo: LocalRepository,
remote_repo: RemoteRepository,
branch_name: &str,
) -> Result<RemoteRepository, OxenError> {
let branch = api::local::branches::get_by_name(&local_repo, branch_name)?
.ok_or(OxenError::local_branch_not_found(branch_name))?;
push_remote_repo_branch(local_repo, remote_repo, branch).await
}
#[cfg(test)]
mod tests {
use crate::command;
use crate::constants;
use crate::error::OxenError;
use crate::test;
#[tokio::test]
async fn test_cannot_push_two_separate_cloned_repos() -> Result<(), OxenError> {
test::run_training_data_fully_sync_remote(|_, remote_repo_1| async move {
let remote_repo_1_copy = remote_repo_1.clone();
test::run_training_data_fully_sync_remote(|_, remote_repo_2| async move {
let remote_repo_2_copy = remote_repo_2.clone();
test::run_empty_dir_test_async(|first_repo_dir| async move {
let first_cloned_repo = command::clone_url(
&remote_repo_1.remote.url,
&first_repo_dir.join("first_repo_dir"),
)
.await?;
test::run_empty_dir_test_async(|second_repo_dir| async move {
let mut second_cloned_repo = command::clone_url(
&remote_repo_2.remote.url,
&second_repo_dir.join("second_repo_dir"),
)
.await?;
let new_file = "new_file.txt";
let new_file_path = first_cloned_repo.path.join(new_file);
let new_file_path =
test::write_txt_file_to_path(new_file_path, "new file")?;
command::add(&first_cloned_repo, &new_file_path)?;
command::commit(&first_cloned_repo, "Adding first file path.")?;
command::push(&first_cloned_repo).await?;
let first_remote = test::repo_remote_url_from(&first_cloned_repo.dirname());
command::config::set_remote(
&mut second_cloned_repo,
constants::DEFAULT_REMOTE_NAME,
&first_remote,
)?;
let new_file = "new_file_2.txt";
let new_file_path = second_cloned_repo.path.join(new_file);
let new_file_path =
test::write_txt_file_to_path(new_file_path, "new file 2")?;
command::add(&second_cloned_repo, &new_file_path)?;
command::commit(&second_cloned_repo, "Adding second file path.")?;
let new_file = "new_file_3.txt";
let new_file_path = second_cloned_repo.path.join(new_file);
let new_file_path =
test::write_txt_file_to_path(new_file_path, "new file 3")?;
command::add(&second_cloned_repo, &new_file_path)?;
command::commit(&second_cloned_repo, "Adding third file path.")?;
let result = command::push(&second_cloned_repo).await;
assert!(result.is_err());
Ok(second_repo_dir)
})
.await?;
Ok(first_repo_dir)
})
.await?;
Ok(remote_repo_2_copy)
})
.await?;
Ok(remote_repo_1_copy)
})
.await
}
#[tokio::test]
async fn test_cannot_push_when_remote_repo_is_ahead_new_file() -> Result<(), OxenError> {
test::run_training_data_fully_sync_remote(|_, remote_repo| async move {
let remote_repo_copy = remote_repo.clone();
test::run_empty_dir_test_async(|user_a_repo_dir| async move {
let user_a_repo_dir_copy = user_a_repo_dir.join("user_a_repo");
let user_a_repo =
command::clone_url(&remote_repo.remote.url, &user_a_repo_dir_copy).await?;
test::run_empty_dir_test_async(|user_b_repo_dir| async move {
let user_b_repo_dir_copy = user_b_repo_dir.join("user_b_repo");
let user_b_repo =
command::clone_url(&remote_repo.remote.url, &user_b_repo_dir_copy).await?;
let new_file = "new_file.txt";
let new_file_path = user_a_repo.path.join(new_file);
let new_file_path = test::write_txt_file_to_path(new_file_path, "new file")?;
command::add(&user_a_repo, &new_file_path)?;
command::commit(&user_a_repo, "Adding first file path.")?;
command::push(&user_a_repo).await?;
let different_file = "another_file.txt";
let new_file_path = user_b_repo.path.join(different_file);
let new_file_path = test::write_txt_file_to_path(new_file_path, "newer file")?;
command::add(&user_b_repo, &new_file_path)?;
command::commit(&user_b_repo, "Adding second file path.")?;
let result = command::push(&user_b_repo).await;
assert!(result.is_err());
command::pull(&user_b_repo).await?;
command::push(&user_b_repo).await?;
Ok(user_b_repo_dir_copy)
})
.await?;
Ok(user_a_repo_dir_copy)
})
.await?;
Ok(remote_repo_copy)
})
.await
}
#[tokio::test]
async fn test_cannot_push_when_remote_repo_is_many_commits_ahead_new_file(
) -> Result<(), OxenError> {
test::run_training_data_fully_sync_remote(|_, remote_repo| async move {
let remote_repo_copy = remote_repo.clone();
test::run_empty_dir_test_async(|user_a_repo_dir| async move {
let user_a_repo_dir_copy = user_a_repo_dir.join("user_a_repo");
let user_a_repo =
command::clone_url(&remote_repo.remote.url, &user_a_repo_dir_copy).await?;
test::run_empty_dir_test_async(|user_b_repo_dir| async move {
let user_b_repo_dir_copy = user_b_repo_dir.join("user_b_repo");
let user_b_repo =
command::clone_url(&remote_repo.remote.url, &user_b_repo_dir_copy).await?;
let new_file = "new_file.txt";
let new_file_path = user_a_repo.path.join(new_file);
let new_file_path = test::write_txt_file_to_path(new_file_path, "new file")?;
command::add(&user_a_repo, &new_file_path)?;
command::commit(&user_a_repo, "Adding first file path.")?;
command::push(&user_a_repo).await?;
let new_file = "new_file_2.txt";
let new_file_path = user_a_repo.path.join(new_file);
let new_file_path = test::write_txt_file_to_path(new_file_path, "new file")?;
command::add(&user_a_repo, &new_file_path)?;
command::commit(&user_a_repo, "Adding second file path.")?;
command::push(&user_a_repo).await?;
let new_file = "new_file_3.txt";
let new_file_path = user_a_repo.path.join(new_file);
let new_file_path = test::write_txt_file_to_path(new_file_path, "new file")?;
command::add(&user_a_repo, &new_file_path)?;
command::commit(&user_a_repo, "Adding third file path.")?;
command::push(&user_a_repo).await?;
let different_file = "another_file.txt";
let new_file_path = user_b_repo.path.join(different_file);
let new_file_path = test::write_txt_file_to_path(new_file_path, "newer file")?;
command::add(&user_b_repo, &new_file_path)?;
command::commit(&user_b_repo, "User B adding second file path.")?;
let result = command::push(&user_b_repo).await;
assert!(result.is_err());
command::pull(&user_b_repo).await?;
command::push(&user_b_repo).await?;
command::pull_all(&user_b_repo).await?;
command::push(&user_b_repo).await?;
Ok(user_b_repo_dir_copy)
})
.await?;
Ok(user_a_repo_dir_copy)
})
.await?;
Ok(remote_repo_copy)
})
.await
}
}