mirror of
https://github.com/gitbutlerapp/gitbutler.git
synced 2024-12-25 10:33:21 +03:00
Fix git head error handling and add symbolic head function
This commit is contained in:
parent
5960c1e6f5
commit
8c1bfe0617
@ -567,7 +567,7 @@ impl<E: GitExecutor + 'static> crate::Repository for Repository<E> {
|
||||
}
|
||||
}
|
||||
|
||||
async fn head(&self) -> Result<Option<String>, crate::Error<Self::Error>> {
|
||||
async fn head(&self) -> Result<String, crate::Error<Self::Error>> {
|
||||
let args = vec!["-C", &self.path, "rev-parse", "HEAD"];
|
||||
|
||||
let (status, stdout, stderr) = self
|
||||
@ -577,9 +577,49 @@ impl<E: GitExecutor + 'static> crate::Repository for Repository<E> {
|
||||
.map_err(Error::<E>::Exec)?;
|
||||
|
||||
if status == 0 {
|
||||
Ok(Some(stdout.to_owned()))
|
||||
} else if status != 0 && stderr.to_lowercase().contains("ambiguous argument") {
|
||||
Ok(None)
|
||||
Ok(stdout.to_owned())
|
||||
} else {
|
||||
Err(Error::<E>::Failed {
|
||||
status,
|
||||
args: args.into_iter().map(Into::into).collect(),
|
||||
stdout,
|
||||
stderr,
|
||||
})?
|
||||
}
|
||||
}
|
||||
|
||||
async fn symbolic_head(&self) -> Result<String, crate::Error<Self::Error>> {
|
||||
let args = vec!["-C", &self.path, "symbolic-ref", "HEAD"];
|
||||
|
||||
let (status, stdout, stderr) = self
|
||||
.exec
|
||||
.execute(&args, None)
|
||||
.await
|
||||
.map_err(Error::<E>::Exec)?;
|
||||
|
||||
if status != 0 {
|
||||
return Err(Error::<E>::Failed {
|
||||
status,
|
||||
args: args.into_iter().map(Into::into).collect(),
|
||||
stdout,
|
||||
stderr,
|
||||
})?;
|
||||
}
|
||||
|
||||
// now we try to rev-parse it because the Git CLI will always
|
||||
// return the default branch as a ref/head/... even if there
|
||||
// is nothing on that branch (no history).
|
||||
let refname = stdout.to_owned();
|
||||
let args = vec!["-C", &self.path, "rev-parse", "--verify", &refname];
|
||||
|
||||
let (status, stdout, stderr) = self
|
||||
.exec
|
||||
.execute(&args, None)
|
||||
.await
|
||||
.map_err(Error::<E>::Exec)?;
|
||||
|
||||
if status == 0 {
|
||||
Ok(refname)
|
||||
} else {
|
||||
Err(Error::<E>::Failed {
|
||||
status,
|
||||
|
@ -326,17 +326,22 @@ impl<R: ThreadedResource> crate::Repository for Repository<R> {
|
||||
.await
|
||||
}
|
||||
|
||||
async fn head(&self) -> Result<Option<String>, crate::Error<Self::Error>> {
|
||||
async fn head(&self) -> Result<String, crate::Error<Self::Error>> {
|
||||
self.repo
|
||||
.with(|repo| {
|
||||
let head = repo.head()?;
|
||||
|
||||
Ok(head
|
||||
.symbolic_target()
|
||||
.map(ToOwned::to_owned)
|
||||
.or_else(|| head.target().map(|oid| oid.to_string())))
|
||||
// We can unwrap here because we assert that the target of the
|
||||
// `.target()` call is a direct reference due to calling
|
||||
// `.resolve()` immediately before it.
|
||||
Ok(repo.head()?.resolve()?.target().unwrap().to_string())
|
||||
})
|
||||
.await
|
||||
.await
|
||||
}
|
||||
|
||||
async fn symbolic_head(&self) -> Result<String, crate::Error<Self::Error>> {
|
||||
self.repo
|
||||
.with(|repo| Ok(String::from_utf8_lossy(repo.head()?.name_bytes()).to_string()))
|
||||
.await
|
||||
.await
|
||||
}
|
||||
}
|
||||
|
@ -58,6 +58,18 @@ macro_rules! gitbutler_git_integration_tests {
|
||||
|
||||
assert_eq!(repo.remote("origin").await.unwrap(), "https://example.com/test.git".to_owned());
|
||||
}
|
||||
|
||||
async fn get_head_no_commits(repo) {
|
||||
use crate::*;
|
||||
assert!(repo.head().await.is_err());
|
||||
}
|
||||
|
||||
async fn get_symbolic_head_no_commits(repo) {
|
||||
use crate::*;
|
||||
assert!(repo.symbolic_head().await.is_err());
|
||||
}
|
||||
|
||||
// DO NOT ADD IO TESTS HERE. THIS IS THE WRONG SPOT.
|
||||
}
|
||||
|
||||
$crate::private::test_impl! {
|
||||
@ -124,10 +136,7 @@ macro_rules! gitbutler_git_integration_tests {
|
||||
}).await
|
||||
}
|
||||
|
||||
async fn get_head_no_commits(repo) {
|
||||
use crate::*;
|
||||
assert_eq!(repo.head().await.unwrap(), None);
|
||||
}
|
||||
// DO NOT ADD NON-IO TESTS HERE. THIS IS THE WRONG SPOT.
|
||||
}
|
||||
};
|
||||
}
|
||||
|
@ -117,8 +117,18 @@ pub trait Repository {
|
||||
async fn remote(&self, remote: &str) -> Result<String, Error<Self::Error>>;
|
||||
|
||||
/// Gets the current HEAD ref of the repository.
|
||||
/// If the repository is empty, this will return `None`.
|
||||
async fn head(&self) -> Result<Option<String>, Error<Self::Error>>;
|
||||
///
|
||||
/// Errors if the repository is empty.
|
||||
async fn head(&self) -> Result<String, Error<Self::Error>>;
|
||||
|
||||
/// Gets the symbolic HEAD of the repository.
|
||||
///
|
||||
/// Returns `"HEAD"` if the current HEAD
|
||||
/// is not a symbolic ref (e.g. a detached head state
|
||||
/// or a direct reference to a commit).
|
||||
///
|
||||
/// Errors if the repository is empty.
|
||||
async fn symbolic_head(&self) -> Result<String, Error<Self::Error>>;
|
||||
}
|
||||
|
||||
/// Provides authentication credentials when performing
|
||||
|
Loading…
Reference in New Issue
Block a user