Compare commits

..

4 commits

Author SHA1 Message Date
95a1526cde refactor: rewrite git crate's mock repository
All checks were successful
ci/woodpecker/push/cron-docker-builder Pipeline was successful
ci/woodpecker/push/push-next Pipeline was successful
ci/woodpecker/push/tag-created Pipeline was successful
2024-06-09 10:02:13 +01:00
dcd94736a9 refactor: git::push::reset takes all params as refs
All checks were successful
Rust / build (push) Successful in 59s
ci/woodpecker/push/push-next Pipeline was successful
ci/woodpecker/push/cron-docker-builder Pipeline was successful
ci/woodpecker/push/tag-created Pipeline was successful
2024-06-09 09:49:54 +01:00
c6a1d2c21b refactor: merge git::branch module into git::push
All checks were successful
Rust / build (push) Successful in 1m3s
ci/woodpecker/push/cron-docker-builder Pipeline was successful
ci/woodpecker/push/push-next Pipeline was successful
ci/woodpecker/push/tag-created Pipeline was successful
2024-06-09 09:49:54 +01:00
65e9ddf5db fix: remove unused GitDir::into_string() function
All checks were successful
Rust / build (push) Successful in 1m18s
ci/woodpecker/push/push-next Pipeline was successful
ci/woodpecker/push/cron-docker-builder Pipeline was successful
ci/woodpecker/push/tag-created Pipeline was successful
2024-06-09 09:49:54 +01:00
14 changed files with 232 additions and 321 deletions

View file

@ -20,10 +20,6 @@ impl GitDir {
pub const fn pathbuf(&self) -> &PathBuf { pub const fn pathbuf(&self) -> &PathBuf {
&self.0 &self.0
} }
pub fn into_string(self) -> String {
self.to_string()
}
} }
impl std::fmt::Display for GitDir { impl std::fmt::Display for GitDir {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {

View file

@ -724,8 +724,7 @@ mod given {
use crate::{ use crate::{
server::{Http, ServerConfig, ServerStorage, Webhook}, server::{Http, ServerConfig, ServerStorage, Webhook},
BranchName, ForgeAlias, ForgeConfig, ForgeType, RepoAlias, RepoBranches, ServerRepoConfig, ForgeAlias, ForgeConfig, ForgeType, RepoAlias, RepoBranches, ServerRepoConfig, WebhookId,
WebhookId,
}; };
pub fn a_name() -> String { pub fn a_name() -> String {

View file

@ -1,37 +0,0 @@
//
use crate as git;
use git_next_config as config;
pub type Result<T> = core::result::Result<T, Error>;
#[derive(Debug, thiserror::Error)]
pub enum Error {
#[error("network: {0}")]
Network(#[from] kxio::network::NetworkError),
#[error("fetch: {0}")]
Fetch(#[from] git::fetch::Error),
#[error("push: {0}")]
Push(#[from] git::push::Error),
#[error("lock")]
Lock,
#[error("gix iter: {0}")]
GixIter(#[from] gix::reference::iter::Error),
#[error("gix iter init: {0}")]
GixIterInit(#[from] gix::reference::iter::init::Error),
}
pub fn reset(
repository: &git::OpenRepository,
repo_details: &git::RepoDetails,
branch_name: config::BranchName,
to_commit: git::GitRef,
force: git::push::Force,
) -> Result<()> {
repository.fetch()?;
Ok(repository.push(repo_details, branch_name, to_commit, force)?)
}

View file

@ -1,5 +1,4 @@
// //
pub mod branch;
pub mod commit; pub mod commit;
pub mod common; pub mod common;
pub mod fetch; pub mod fetch;

View file

@ -1,4 +1,6 @@
use super::GitRef; use super::GitRef;
use crate as git;
use git_next_config as config;
#[derive(Debug)] #[derive(Debug)]
pub enum Force { pub enum Force {
@ -14,16 +16,39 @@ impl std::fmt::Display for Force {
} }
} }
pub type Result<T> = core::result::Result<T, Error>;
#[derive(Debug, thiserror::Error)] #[derive(Debug, thiserror::Error)]
pub enum Error { pub enum Error {
#[error("gix open: {0}")] #[error("io")]
Open(#[from] Box<gix::open::Error>), Io(#[from] std::io::Error),
#[error("io: {0}")] #[error("network: {0}")]
Push(#[from] std::io::Error), Network(#[from] kxio::network::NetworkError),
#[error("fetch: {0}")]
Fetch(#[from] git::fetch::Error),
#[error("lock")] #[error("lock")]
Lock, Lock,
#[error("gix open: {0}")]
Open(#[from] Box<gix::open::Error>),
#[error("gix iter: {0}")]
GixIter(#[from] gix::reference::iter::Error),
#[error("gix iter init: {0}")]
GixIterInit(#[from] gix::reference::iter::init::Error),
} }
pub type Result<T> = core::result::Result<T, Error>; pub fn reset(
repository: &git::OpenRepository,
repo_details: &git::RepoDetails,
branch_name: &config::BranchName,
to_commit: &git::GitRef,
force: &git::push::Force,
) -> Result<()> {
repository.fetch()?;
repository.push(repo_details, branch_name, to_commit, force)
}

View file

@ -6,42 +6,43 @@ use std::{
sync::{Arc, Mutex}, sync::{Arc, Mutex},
}; };
use super::Error; use crate::{self as git, Repository};
use crate as git;
use crate::{ use crate::{
repository::{ repository::{
open::{OpenRepository, OpenRepositoryLike}, open::{OpenRepository, OpenRepositoryLike},
Direction, RepositoryLike, Result, Direction, RepositoryLike,
}, },
GitRemote, RepoDetails, GitRemote, RepoDetails,
}; };
use git_next_config as config; use git_next_config as config;
#[derive(Debug, Default, Clone)] #[derive(Debug, Default, Clone)]
pub struct MockRepository(Arc<Mutex<Reality>>); pub struct MockRepository {
open_repos: Arc<Mutex<HashMap<config::GitDir, MockOpenRepository>>>,
}
impl MockRepository { impl MockRepository {
pub fn new() -> Self { pub fn new() -> Self {
Self(Arc::new(Mutex::new(Reality::default()))) Self {
open_repos: Default::default(),
} }
pub fn can_open_repo(&mut self, gitdir: &config::GitDir) -> Result<MockOpenRepository> { }
self.0
pub fn given_can_be_opened(&mut self, gitdir: &config::GitDir) -> MockOpenRepository {
let open_repo = MockOpenRepository::new();
#[allow(clippy::unwrap_used)]
self.open_repos
.lock() .lock()
.map_err(|_| Error::MockLock) .map(|mut or| or.insert(gitdir.clone(), open_repo.clone()))
.map(|mut r| r.can_open_repo(gitdir)) .unwrap();
open_repo
} }
fn open_repository(
&self, pub fn seal(self) -> (Repository, Self) {
gitdir: &config::GitDir, (Repository::Mock(self.clone()), self)
) -> std::result::Result<MockOpenRepository, crate::repository::Error> {
self.0.lock().map_err(|_| Error::MockLock).and_then(|r| {
r.open_repository(gitdir)
.ok_or_else(|| Error::Open(format!("mock - could not open: {}", gitdir)))
})
} }
fn clone_repository( pub fn unseal(self, _repository: Repository) -> Self {
&self, // drop repository to allow same mutable access to mock repository
) -> std::result::Result<MockOpenRepository, crate::repository::Error> { self
todo!()
} }
} }
impl RepositoryLike for MockRepository { impl RepositoryLike for MockRepository {
@ -49,149 +50,101 @@ impl RepositoryLike for MockRepository {
&self, &self,
gitdir: &config::GitDir, gitdir: &config::GitDir,
) -> std::result::Result<OpenRepository, crate::repository::Error> { ) -> std::result::Result<OpenRepository, crate::repository::Error> {
Ok(OpenRepository::Mock(self.open_repository(gitdir)?)) #[allow(clippy::unwrap_used)]
self.open_repos
.lock()
.map_err(|_| crate::repository::Error::MockLock)
.map(|or| or.get(gitdir).cloned())
.transpose()
.unwrap_or_else(|| Err(crate::repository::Error::InvalidGitDir(gitdir.clone())))
.map(|mor| mor.into())
} }
fn git_clone( fn git_clone(
&self, &self,
_repo_details: &RepoDetails, _repo_details: &RepoDetails,
) -> std::result::Result<OpenRepository, crate::repository::Error> { ) -> std::result::Result<OpenRepository, crate::repository::Error> {
Ok(OpenRepository::Mock(self.clone_repository()?)) todo!("MockRepository::git_clone")
} }
} }
#[derive(Debug, Default)]
pub struct Reality {
openable_repos: HashMap<config::GitDir, MockOpenRepository>,
}
impl Reality {
pub fn can_open_repo(&mut self, gitdir: &config::GitDir) -> MockOpenRepository {
let mor = self.openable_repos.get(gitdir);
match mor {
Some(mor) => mor.clone(),
None => {
let mor = MockOpenRepository::default();
self.openable_repos.insert(gitdir.clone(), mor.clone());
mor
}
}
}
pub fn open_repository(&self, gitdir: &config::GitDir) -> Option<MockOpenRepository> {
self.openable_repos.get(gitdir).cloned()
}
}
#[derive(Clone, Debug, Default)]
pub struct InnerMockOpenRepository {
default_push_remote: Option<GitRemote>,
default_fetch_remote: Option<GitRemote>,
}
#[derive(Clone, Debug, Default)] #[derive(Clone, Debug, Default)]
pub struct MockOpenRepository { pub struct MockOpenRepository {
inner: Arc<Mutex<InnerMockOpenRepository>>, default_push_remote: Arc<Mutex<Option<GitRemote>>>,
default_fetch_remote: Arc<Mutex<Option<GitRemote>>>,
} }
impl std::ops::Deref for MockOpenRepository { impl MockOpenRepository {
type Target = Arc<Mutex<InnerMockOpenRepository>>; pub fn new() -> Self {
Self::default()
fn deref(&self) -> &Self::Target { }
&self.inner pub fn given_has_default_remote(&mut self, direction: Direction, remote: Option<GitRemote>) {
#[allow(clippy::unwrap_used)]
match direction {
Direction::Push => self
.default_push_remote
.lock()
.map(|mut o| match remote {
Some(gr) => o.replace(gr),
None => o.take(),
})
.unwrap(),
Direction::Fetch => self
.default_fetch_remote
.lock()
.map(|mut o| match remote {
Some(gr) => o.replace(gr),
None => o.take(),
})
.unwrap(),
};
} }
} }
impl From<MockOpenRepository> for OpenRepository {
impl InnerMockOpenRepository { fn from(value: MockOpenRepository) -> Self {
pub fn has_default_remote(&mut self, direction: Direction, git_remote: GitRemote) { Self::Mock(value)
match direction {
Direction::Push => self.default_push_remote.replace(git_remote),
Direction::Fetch => self.default_fetch_remote.replace(git_remote),
};
} }
} }
#[allow(clippy::unwrap_used)] #[allow(clippy::unwrap_used)]
impl OpenRepositoryLike for MockOpenRepository { impl OpenRepositoryLike for MockOpenRepository {
fn remote_branches(&self) -> git::branch::Result<Vec<config::BranchName>> { fn remote_branches(&self) -> git::push::Result<Vec<config::BranchName>> {
self.inner todo!("MockOpenRepository::remote_branched")
.lock()
.map(|inner| inner.remote_branches())
.unwrap()
}
fn find_default_remote(&self, direction: Direction) -> Option<GitRemote> {
self.inner
.lock()
.map(|inner| inner.find_default_remote(direction))
.unwrap()
}
fn fetch(&self) -> core::result::Result<(), crate::fetch::Error> {
self.inner.lock().map(|inner| inner.fetch()).unwrap()
}
fn push(
&self,
repo_details: &RepoDetails,
branch_name: git_next_config::BranchName,
to_commit: crate::GitRef,
force: crate::push::Force,
) -> core::result::Result<(), crate::push::Error> {
self.inner
.lock()
.map(|inner| inner.push(repo_details, branch_name, to_commit, force))
.unwrap()
}
fn commit_log(
&self,
branch_name: &git_next_config::BranchName,
find_commits: &[git::Commit],
) -> core::result::Result<Vec<crate::Commit>, git::commit::log::Error> {
self.inner
.lock()
.map(|inner| inner.commit_log(branch_name, find_commits))
.unwrap()
}
fn read_file(
&self,
branch_name: &git_next_config::BranchName,
file_name: &str,
) -> git::file::Result<String> {
self.inner
.lock()
.map(|inner| inner.read_file(branch_name, file_name))
.unwrap()
}
}
impl OpenRepositoryLike for InnerMockOpenRepository {
fn remote_branches(&self) -> git::branch::Result<Vec<config::BranchName>> {
todo!();
} }
fn find_default_remote(&self, direction: Direction) -> Option<GitRemote> { fn find_default_remote(&self, direction: Direction) -> Option<GitRemote> {
match direction { match direction {
Direction::Push => self.default_push_remote.clone(), Direction::Push => self
Direction::Fetch => self.default_fetch_remote.clone(), .default_push_remote
.lock()
.map(|r| r.clone())
.unwrap_or(None),
Direction::Fetch => self
.default_fetch_remote
.lock()
.map(|r| r.clone())
.unwrap_or(None),
} }
} }
fn fetch(&self) -> core::result::Result<(), crate::fetch::Error> { fn fetch(&self) -> core::result::Result<(), crate::fetch::Error> {
todo!() todo!("MockOpenRepository::fetch")
} }
fn push( fn push(
&self, &self,
_repo_details: &RepoDetails, _repo_details: &RepoDetails,
_branch_name: git_next_config::BranchName, _branch_name: &git_next_config::BranchName,
_to_commit: crate::GitRef, _to_commit: &crate::GitRef,
_force: crate::push::Force, _force: &crate::push::Force,
) -> core::result::Result<(), crate::push::Error> { ) -> core::result::Result<(), crate::push::Error> {
todo!() todo!("MockOpenRepository::push")
} }
fn commit_log( fn commit_log(
&self, &self,
_branch_name: &git_next_config::BranchName, _branch_name: &git_next_config::BranchName,
_find_commits: &[git::Commit], _find_commits: &[git::Commit],
) -> core::result::Result<Vec<crate::Commit>, crate::commit::log::Error> { ) -> core::result::Result<Vec<crate::Commit>, git::commit::log::Error> {
todo!() todo!("MockOpenRepository::commit_log")
} }
fn read_file( fn read_file(
@ -199,6 +152,6 @@ impl OpenRepositoryLike for InnerMockOpenRepository {
_branch_name: &git_next_config::BranchName, _branch_name: &git_next_config::BranchName,
_file_name: &str, _file_name: &str,
) -> git::file::Result<String> { ) -> git::file::Result<String> {
todo!() todo!("MockOpenRepository::read_file")
} }
} }

View file

@ -9,10 +9,11 @@ mod tests;
use git_next_config as config; use git_next_config as config;
use git_next_config::GitDir; use git_next_config::GitDir;
pub use mock::MockRepository;
pub use open::OpenRepository; pub use open::OpenRepository;
use tracing::info; use tracing::info;
use crate::{repository::mock::MockRepository, validation::repo::validate_repo}; use crate::validation::repo::validate_repo;
use super::RepoDetails; use super::RepoDetails;
@ -24,9 +25,9 @@ pub enum Repository {
pub const fn new() -> Repository { pub const fn new() -> Repository {
Repository::Real Repository::Real
} }
pub fn mock() -> (Repository, MockRepository) { pub fn mock() -> MockRepository {
let mock_repository = MockRepository::new(); MockRepository::new()
(Repository::Mock(mock_repository.clone()), mock_repository) // (Repository::Mock(mock_repository.clone()), mock_repository)
} }
/// Opens a repository, cloning if necessary /// Opens a repository, cloning if necessary

View file

@ -28,15 +28,15 @@ impl OpenRepository {
} }
} }
pub trait OpenRepositoryLike { pub trait OpenRepositoryLike {
fn remote_branches(&self) -> git::branch::Result<Vec<config::BranchName>>; fn remote_branches(&self) -> git::push::Result<Vec<config::BranchName>>;
fn find_default_remote(&self, direction: Direction) -> Option<git::GitRemote>; fn find_default_remote(&self, direction: Direction) -> Option<git::GitRemote>;
fn fetch(&self) -> Result<(), git::fetch::Error>; fn fetch(&self) -> Result<(), git::fetch::Error>;
fn push( fn push(
&self, &self,
repo_details: &git::RepoDetails, repo_details: &git::RepoDetails,
branch_name: config::BranchName, branch_name: &config::BranchName,
to_commit: git::GitRef, to_commit: &git::GitRef,
force: git::push::Force, force: &git::push::Force,
) -> git::push::Result<()>; ) -> git::push::Result<()>;
/// List of commits in a branch, optionally up-to any specified commit. /// List of commits in a branch, optionally up-to any specified commit.

View file

@ -10,11 +10,11 @@ use tracing::{info, warn};
#[derive(Clone, Debug, derive_more::Constructor)] #[derive(Clone, Debug, derive_more::Constructor)]
pub struct RealOpenRepository(Arc<Mutex<gix::Repository>>); pub struct RealOpenRepository(Arc<Mutex<gix::Repository>>);
impl super::OpenRepositoryLike for RealOpenRepository { impl super::OpenRepositoryLike for RealOpenRepository {
fn remote_branches(&self) -> git::branch::Result<Vec<config::BranchName>> { fn remote_branches(&self) -> git::push::Result<Vec<config::BranchName>> {
let refs = self let refs = self
.0 .0
.lock() .lock()
.map_err(|_| git::branch::Error::Lock) .map_err(|_| git::push::Error::Lock)
.and_then(|repo| { .and_then(|repo| {
Ok(repo.references()?).and_then(|refs| { Ok(repo.references()?).and_then(|refs| {
Ok(refs.remote_branches().map(|rb| { Ok(refs.remote_branches().map(|rb| {
@ -73,9 +73,9 @@ impl super::OpenRepositoryLike for RealOpenRepository {
fn push( fn push(
&self, &self,
repo_details: &git::RepoDetails, repo_details: &git::RepoDetails,
branch_name: config::BranchName, branch_name: &config::BranchName,
to_commit: git::GitRef, to_commit: &git::GitRef,
force: git::push::Force, force: &git::push::Force,
) -> Result<(), git::push::Error> { ) -> Result<(), git::push::Error> {
let origin = repo_details.origin(); let origin = repo_details.origin();
let force = match force { let force = match force {

View file

@ -1,14 +1,12 @@
mod validate { use crate as git;
mod validate {
use crate::{validation::repo::validate_repo, GitRemote, RepoDetails};
use super::*;
use assert2::let_assert; use assert2::let_assert;
use git_next_config::{ForgeDetails, GitDir, Hostname, RepoPath}; use git_next_config::{ForgeDetails, GitDir, Hostname, RepoPath};
use crate::{
repository,
validation::{self, repo::validate_repo},
GitRemote, RepoDetails,
};
#[test] #[test]
fn should_ok_a_valid_repo() { fn should_ok_a_valid_repo() {
let repo_details = RepoDetails::default() let repo_details = RepoDetails::default()
@ -22,25 +20,17 @@ mod validate {
RepoPath::new("kemitix/test".to_string()), RepoPath::new("kemitix/test".to_string()),
); );
let (repository, mut reality) = repository::mock(); let mut mock_repository = git::repository::mock();
let_assert!( {
Ok(_) = reality.can_open_repo(&gitdir).map( let mut mock_open_repo = mock_repository.given_can_be_opened(&gitdir);
#[allow(clippy::significant_drop_tightening)] mock_open_repo
|open_repo| { .given_has_default_remote(git::repository::Direction::Push, Some(remote.clone()));
let_assert!( mock_open_repo
Ok(_) = open_repo.lock().map(|mut open_repo| { .given_has_default_remote(git::repository::Direction::Fetch, Some(remote));
open_repo
.has_default_remote(repository::Direction::Push, remote.clone());
open_repo.has_default_remote(repository::Direction::Fetch, remote);
})
);
} }
) let (repository, _mock_repository) = mock_repository.seal();
);
let_assert!(Ok(open_repository) = repository.open(&gitdir)); let_assert!(Ok(open_repository) = repository.open(&gitdir));
let_assert!(Ok(_) = validate_repo(&open_repository, &repo_details));
let_assert!(Ok(_) = validation::repo::validate_repo(&open_repository, &repo_details));
} }
#[test] #[test]
@ -56,23 +46,15 @@ mod validate {
RepoPath::new("kemitix/test".to_string()), RepoPath::new("kemitix/test".to_string()),
); );
let (repository, mut reality) = repository::mock(); let mut mock_repository = git::repository::mock();
let_assert!( {
Ok(_) = reality.can_open_repo(&gitdir).map( let mut mock_open_repo = mock_repository.given_can_be_opened(&gitdir);
#[allow(clippy::significant_drop_tightening)] mock_open_repo.given_has_default_remote(git::repository::Direction::Push, None);
|open_repo| { mock_open_repo
let_assert!( .given_has_default_remote(git::repository::Direction::Fetch, Some(remote));
Ok(_) = open_repo.lock().map(|mut open_repo| {
// INFO: open_repo.has_default_remote(Direction::Push, remote.clone());
open_repo.has_default_remote(repository::Direction::Fetch, remote);
})
);
} }
) let (repository, _mock_repository) = mock_repository.seal();
);
let_assert!(Ok(open_repository) = repository.open(&gitdir)); let_assert!(Ok(open_repository) = repository.open(&gitdir));
let_assert!(Err(_) = validate_repo(&open_repository, &repo_details)); let_assert!(Err(_) = validate_repo(&open_repository, &repo_details));
} }
#[test] #[test]
@ -88,23 +70,15 @@ mod validate {
RepoPath::new("kemitix/test".to_string()), RepoPath::new("kemitix/test".to_string()),
); );
let (repository, mut reality) = repository::mock(); let mut mock_repository = git::repository::mock();
let_assert!( {
Ok(_) = reality.can_open_repo(&gitdir).map( let mut mock_open_repo = mock_repository.given_can_be_opened(&gitdir);
#[allow(clippy::significant_drop_tightening)] mock_open_repo.given_has_default_remote(git::repository::Direction::Push, None);
|open_repo| { mock_open_repo
let_assert!( .given_has_default_remote(git::repository::Direction::Fetch, Some(remote));
Ok(_) = open_repo.lock().map(|mut open_repo| {
open_repo.has_default_remote(repository::Direction::Push, remote);
// INFO: open_repo.has_default_remote(Direction::Fetch, remote);
})
);
} }
) let (repository, _mock_repository) = mock_repository.seal();
);
let_assert!(Ok(open_repository) = repository.open(&gitdir)); let_assert!(Ok(open_repository) = repository.open(&gitdir));
let_assert!(Err(_) = validate_repo(&open_repository, &repo_details)); let_assert!(Err(_) = validate_repo(&open_repository, &repo_details));
} }
#[test] #[test]
@ -124,23 +98,16 @@ mod validate {
RepoPath::new("kemitix/other".to_string()), RepoPath::new("kemitix/other".to_string()),
); );
let (repository, mut reality) = repository::mock(); let mut mock_repository = git::repository::mock();
let_assert!( {
Ok(_) = reality.can_open_repo(&gitdir).map( let mut mock_open_repo = mock_repository.given_can_be_opened(&gitdir);
#[allow(clippy::significant_drop_tightening)] mock_open_repo
|open_repo| { .given_has_default_remote(git::repository::Direction::Push, Some(other_remote));
let_assert!( mock_open_repo
Ok(_) = open_repo.lock().map(|mut open_repo| { .given_has_default_remote(git::repository::Direction::Fetch, Some(remote));
open_repo.has_default_remote(repository::Direction::Push, other_remote);
open_repo.has_default_remote(repository::Direction::Fetch, remote);
})
);
} }
) let (repository, _mock_repository) = mock_repository.seal();
);
let_assert!(Ok(open_repository) = repository.open(&gitdir)); let_assert!(Ok(open_repository) = repository.open(&gitdir));
let_assert!(Err(_) = validate_repo(&open_repository, &repo_details)); let_assert!(Err(_) = validate_repo(&open_repository, &repo_details));
} }
#[test] #[test]
@ -160,33 +127,25 @@ mod validate {
RepoPath::new("kemitix/other".to_string()), RepoPath::new("kemitix/other".to_string()),
); );
let (repository, mut reality) = repository::mock(); let mut mock_repository = git::repository::mock();
let_assert!( {
Ok(_) = reality.can_open_repo(&gitdir).map( let mut mock_open_repo = mock_repository.given_can_be_opened(&gitdir);
#[allow(clippy::significant_drop_tightening)] mock_open_repo.given_has_default_remote(git::repository::Direction::Push, Some(remote));
|open_repo| { mock_open_repo
let_assert!( .given_has_default_remote(git::repository::Direction::Fetch, Some(other_remote));
Ok(_) = open_repo.lock().map(|mut open_repo| {
open_repo.has_default_remote(repository::Direction::Push, remote);
open_repo
.has_default_remote(repository::Direction::Fetch, other_remote);
})
);
} }
) let (repository, _mock_repository) = mock_repository.seal();
);
let_assert!(Ok(open_repository) = repository.open(&gitdir)); let_assert!(Ok(open_repository) = repository.open(&gitdir));
let_assert!(Err(_) = validate_repo(&open_repository, &repo_details)); let_assert!(Err(_) = validate_repo(&open_repository, &repo_details));
} }
} }
mod git_clone { mod git_clone {
use super::*;
use assert2::let_assert; use assert2::let_assert;
use git_next_config::{ForgeDetails, GitDir, Hostname, RepoPath}; use git_next_config::{ForgeDetails, GitDir, Hostname, RepoPath};
use crate::{repository, GitRemote, RepoDetails}; use crate::{GitRemote, RepoDetails};
#[test] #[test]
#[ignore] // slow test ~1.5 seconds #[ignore] // slow test ~1.5 seconds
@ -200,7 +159,9 @@ mod git_clone {
.with_gitdir(GitDir::new(fs.base())) .with_gitdir(GitDir::new(fs.base()))
.with_repo_path(RepoPath::new("kemitix/git-next".to_string())); .with_repo_path(RepoPath::new("kemitix/git-next".to_string()));
let_assert!(Ok(open_repo) = r.git_clone(&repo_details)); let_assert!(Ok(open_repo) = r.git_clone(&repo_details));
let_assert!(Some(remote) = open_repo.find_default_remote(repository::Direction::Fetch)); let_assert!(
Some(remote) = open_repo.find_default_remote(git::repository::Direction::Fetch)
);
assert_eq!( assert_eq!(
remote, remote,
GitRemote::new( GitRemote::new(

View file

@ -81,9 +81,7 @@ mod gitremote {
} }
} }
mod push { mod push {
use crate::{commit, Commit, GitRef}; use crate::{commit, push::Force, Commit, GitRef};
use crate::push::Force;
#[test] #[test]
fn force_no_should_display() { fn force_no_should_display() {
@ -100,6 +98,34 @@ mod push {
"force-if-from:sha" "force-if-from:sha"
) )
} }
// TODO:
// mod reset {
// use assert2::let_assert;
// use crate::tests::given;
// use super::*;
// // #[test]
// // fn should_perform_a_fetch() {
// // let fs = given::a_filesystem();
// // let (repository, _mock) = given::an_open_repository(&fs);
// // let repo_details = given::repo_details(&fs);
// // let branch_name = &repo_details.branch;
// // let commit = given::a_commit();
// // let gitref = GitRef::from(commit);
// // let_assert!(
// // Ok(_) = git::push::reset(
// // &repository,
// // &repo_details,
// // branch_name,
// // &gitref,
// // &git::push::Force::No
// // )
// // );
// // // let operations = mock.operations();
// // // assert_eq!(operations, vec![format!("push reset { /}")])
// // todo!()
// // }
// }
} }
mod repo_details { mod repo_details {
@ -174,26 +200,6 @@ mod repo_details {
); );
} }
} }
// mod branch {
// use super::*;
// use assert2::let_assert;
// #[test]
// fn reset_should_fetch_then_push() {
// // let repository = given::a_mock_open_repository();
// let fs = given::a_filesystem();
// let repo_detauls = given::repo_details(&fs);
// let repository = given::a_mock_open_repository();
// let_assert!(
// Ok(result) = git::branch::reset(
// repository,
// &repo_details,
// &repo_details.branch,
// git_ref,
// force
// )
// );
// }
// }
mod given { mod given {
#![allow(dead_code)] #![allow(dead_code)]
// //
@ -356,4 +362,12 @@ mod given {
gitdir, gitdir,
) )
} }
// pub fn an_open_repository(fs: &kxio::fs::FileSystem) -> (OpenRepository, MockRepository) {
// let (repo, mock) = git::repository::mock();
//
// let gitdir = a_git_dir(fs);
// let op = repo.open(&gitdir).unwrap();
// (op, mock)
// }
} }

View file

@ -66,12 +66,12 @@ pub fn validate_positions(
let next_is_ancestor_of_dev = commit_histories.dev.iter().any(|dev| dev == &next); let next_is_ancestor_of_dev = commit_histories.dev.iter().any(|dev| dev == &next);
if !next_is_ancestor_of_dev { if !next_is_ancestor_of_dev {
info!("Next is not an ancestor of dev - resetting next to main"); info!("Next is not an ancestor of dev - resetting next to main");
if let Err(err) = git::branch::reset( if let Err(err) = git::push::reset(
repository, repository,
repo_details, repo_details,
repo_config.branches().next(), &repo_config.branches().next(),
main.into(), &main.into(),
git::push::Force::From(next.clone().into()), &git::push::Force::From(next.clone().into()),
) { ) {
warn!(?err, "Failed to reset next to main"); warn!(?err, "Failed to reset next to main");
return Err(git::validation::positions::Error::FailedToResetBranch { return Err(git::validation::positions::Error::FailedToResetBranch {
@ -96,12 +96,12 @@ pub fn validate_positions(
repo_config.branches().main(), repo_config.branches().main(),
repo_config.branches().next() repo_config.branches().next()
); );
if let Err(err) = git::branch::reset( if let Err(err) = git::push::reset(
repository, repository,
repo_details, repo_details,
repo_config.branches().next(), &repo_config.branches().next(),
main.into(), &main.into(),
git::push::Force::From(next.clone().into()), &git::push::Force::From(next.clone().into()),
) { ) {
warn!(?err, "Failed to reset next to main"); warn!(?err, "Failed to reset next to main");
return Err(git::validation::positions::Error::FailedToResetBranch { return Err(git::validation::positions::Error::FailedToResetBranch {

View file

@ -30,12 +30,12 @@ pub async fn advance_next(
return; return;
} }
info!("Advancing next to commit '{}'", commit); info!("Advancing next to commit '{}'", commit);
if let Err(err) = git::branch::reset( if let Err(err) = git::push::reset(
&repository, &repository,
&repo_details, &repo_details,
repo_config.branches().next(), &repo_config.branches().next(),
commit.into(), &commit.into(),
git::push::Force::No, &git::push::Force::No,
) { ) {
warn!(?err, "Failed") warn!(?err, "Failed")
} }
@ -84,12 +84,12 @@ pub async fn advance_main(
repository: &git::OpenRepository, repository: &git::OpenRepository,
) { ) {
info!("Advancing main to next"); info!("Advancing main to next");
if let Err(err) = git::branch::reset( if let Err(err) = git::push::reset(
repository, repository,
repo_details, repo_details,
repo_config.branches().main(), &repo_config.branches().main(),
next.into(), &next.into(),
git::push::Force::No, &git::push::Force::No,
) { ) {
warn!(?err, "Failed") warn!(?err, "Failed")
}; };

View file

@ -42,7 +42,7 @@ pub enum Error {
File(git::file::Error), File(git::file::Error),
Config(config::server::Error), Config(config::server::Error),
Toml(toml::de::Error), Toml(toml::de::Error),
Branch(git::branch::Error), Branch(git::push::Error),
BranchNotFound(config::BranchName), BranchNotFound(config::BranchName),
} }