fix(git_branch): more robust handling of .git (#3290)
This commit is contained in:
parent
1109fd6997
commit
e3a88a6ec1
|
@ -274,7 +274,8 @@ impl<'a> Context<'a> {
|
|||
}?;
|
||||
Ok(Repo {
|
||||
branch: get_current_branch(&repository),
|
||||
root: repository.workdir().map(Path::to_path_buf),
|
||||
workdir: repository.workdir().map(Path::to_path_buf),
|
||||
path: Path::to_path_buf(repository.path()),
|
||||
state: repository.state(),
|
||||
remote: get_remote_repository_info(&repository),
|
||||
})
|
||||
|
@ -433,7 +434,10 @@ pub struct Repo {
|
|||
|
||||
/// If `current_dir` is a git repository or is contained within one,
|
||||
/// this is the path to the root of that repo.
|
||||
pub root: Option<PathBuf>,
|
||||
pub workdir: Option<PathBuf>,
|
||||
|
||||
/// The path of the repository's `.git` directory.
|
||||
pub path: PathBuf,
|
||||
|
||||
/// State
|
||||
pub state: RepositoryState,
|
||||
|
@ -442,6 +446,13 @@ pub struct Repo {
|
|||
pub remote: Option<Remote>,
|
||||
}
|
||||
|
||||
impl Repo {
|
||||
/// Opens the associated git repository.
|
||||
pub fn open(&self) -> Result<Repository, git2::Error> {
|
||||
Repository::open(&self.path)
|
||||
}
|
||||
}
|
||||
|
||||
/// Remote repository
|
||||
pub struct Remote {
|
||||
pub branch: Option<String>,
|
||||
|
|
|
@ -53,7 +53,7 @@ pub fn module<'a>(context: &'a Context) -> Option<Module<'a>> {
|
|||
// Otherwise use the logical path, automatically contracting
|
||||
let repo = context.get_repo().ok();
|
||||
let dir_string = if config.truncate_to_repo {
|
||||
repo.and_then(|r| r.root.as_ref())
|
||||
repo.and_then(|r| r.workdir.as_ref())
|
||||
.filter(|&root| root != &home_dir)
|
||||
.and_then(|root| contract_repo_path(display_dir, root))
|
||||
} else {
|
||||
|
@ -99,7 +99,7 @@ pub fn module<'a>(context: &'a Context) -> Option<Module<'a>> {
|
|||
String::from("")
|
||||
};
|
||||
|
||||
let path_vec = match &repo.and_then(|r| r.root.as_ref()) {
|
||||
let path_vec = match &repo.and_then(|r| r.workdir.as_ref()) {
|
||||
Some(repo_root) if config.repo_root_style.is_some() => {
|
||||
let contracted_path = contract_repo_path(display_dir, repo_root)?;
|
||||
let repo_path_vec: Vec<&str> = contracted_path.split('/').collect();
|
||||
|
|
|
@ -54,7 +54,7 @@ pub fn module<'a>(context: &'a Context) -> Option<Module<'a>> {
|
|||
.map(|variable| match variable {
|
||||
"version" => {
|
||||
let version = if enable_heuristic {
|
||||
let repo_root = context.get_repo().ok().and_then(|r| r.root.as_deref());
|
||||
let repo_root = context.get_repo().ok().and_then(|r| r.workdir.as_deref());
|
||||
estimate_dotnet_version(
|
||||
context,
|
||||
&dotnet_files,
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
use unicode_segmentation::UnicodeSegmentation;
|
||||
|
||||
use super::{Context, Module, RootModuleConfig};
|
||||
use git2::Repository;
|
||||
|
||||
use crate::configs::git_branch::GitBranchConfig;
|
||||
use crate::formatter::StringFormatter;
|
||||
|
@ -27,13 +26,13 @@ pub fn module<'a>(context: &'a Context) -> Option<Module<'a>> {
|
|||
|
||||
let repo = context.get_repo().ok()?;
|
||||
|
||||
if let Some(repo_root) = repo.root.as_ref() {
|
||||
let git_repo = Repository::open(repo_root).ok()?;
|
||||
let is_detached = git_repo.head_detached().ok()?;
|
||||
if config.only_attached && is_detached {
|
||||
if config.only_attached {
|
||||
if let Ok(git_repo) = repo.open() {
|
||||
if git_repo.head_detached().ok()? {
|
||||
return None;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let branch_name = repo.branch.as_ref()?;
|
||||
let mut graphemes: Vec<&str> = branch_name.graphemes(true).collect();
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
use super::{Context, Module, RootModuleConfig};
|
||||
use crate::formatter::string_formatter::StringFormatterError;
|
||||
use git2::Repository;
|
||||
use git2::Time;
|
||||
|
||||
use crate::configs::git_commit::GitCommitConfig;
|
||||
|
@ -14,8 +13,7 @@ pub fn module<'a>(context: &'a Context) -> Option<Module<'a>> {
|
|||
let config: GitCommitConfig = GitCommitConfig::try_load(module.config);
|
||||
|
||||
let repo = context.get_repo().ok()?;
|
||||
let repo_root = repo.root.as_ref()?;
|
||||
let git_repo = Repository::open(repo_root).ok()?;
|
||||
let git_repo = repo.open().ok()?;
|
||||
|
||||
let is_detached = git_repo.head_detached().ok()?;
|
||||
if config.only_detached && !is_detached {
|
||||
|
|
|
@ -21,13 +21,15 @@ pub fn module<'a>(context: &'a Context) -> Option<Module<'a>> {
|
|||
};
|
||||
|
||||
let repo = context.get_repo().ok()?;
|
||||
let repo_root = repo.root.as_ref()?;
|
||||
let repo_root = repo.workdir.as_ref()?;
|
||||
|
||||
let diff = context
|
||||
.exec_cmd(
|
||||
"git",
|
||||
&[
|
||||
OsStr::new("-C"),
|
||||
OsStr::new("--git-dir"),
|
||||
repo.path.as_os_str(),
|
||||
OsStr::new("--work-tree"),
|
||||
repo_root.as_os_str(),
|
||||
OsStr::new("--no-optional-locks"),
|
||||
OsStr::new("diff"),
|
||||
|
|
|
@ -1,8 +1,9 @@
|
|||
use git2::RepositoryState;
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::path::PathBuf;
|
||||
|
||||
use super::{Context, Module, RootModuleConfig};
|
||||
use crate::configs::git_state::GitStateConfig;
|
||||
use crate::context::Repo;
|
||||
use crate::formatter::StringFormatter;
|
||||
|
||||
/// Creates a module with the state of the git repository at the current directory
|
||||
|
@ -14,10 +15,8 @@ pub fn module<'a>(context: &'a Context) -> Option<Module<'a>> {
|
|||
let config: GitStateConfig = GitStateConfig::try_load(module.config);
|
||||
|
||||
let repo = context.get_repo().ok()?;
|
||||
let repo_root = repo.root.as_ref()?;
|
||||
let repo_state = repo.state;
|
||||
|
||||
let state_description = get_state_description(repo_state, repo_root, &config)?;
|
||||
let state_description = get_state_description(repo, &config)?;
|
||||
|
||||
let parsed = StringFormatter::new(config.format).and_then(|formatter| {
|
||||
formatter
|
||||
|
@ -52,11 +51,10 @@ pub fn module<'a>(context: &'a Context) -> Option<Module<'a>> {
|
|||
///
|
||||
/// During a git operation it will show: REBASING, BISECTING, MERGING, etc.
|
||||
fn get_state_description<'a>(
|
||||
state: RepositoryState,
|
||||
root: &'a Path,
|
||||
repo: &'a Repo,
|
||||
config: &GitStateConfig<'a>,
|
||||
) -> Option<StateDescription<'a>> {
|
||||
match state {
|
||||
match repo.state {
|
||||
RepositoryState::Clean => None,
|
||||
RepositoryState::Merge => Some(StateDescription {
|
||||
label: config.merge,
|
||||
|
@ -98,13 +96,13 @@ fn get_state_description<'a>(
|
|||
current: None,
|
||||
total: None,
|
||||
}),
|
||||
RepositoryState::Rebase => Some(describe_rebase(root, config.rebase)),
|
||||
RepositoryState::RebaseInteractive => Some(describe_rebase(root, config.rebase)),
|
||||
RepositoryState::RebaseMerge => Some(describe_rebase(root, config.rebase)),
|
||||
RepositoryState::Rebase => Some(describe_rebase(repo, config.rebase)),
|
||||
RepositoryState::RebaseInteractive => Some(describe_rebase(repo, config.rebase)),
|
||||
RepositoryState::RebaseMerge => Some(describe_rebase(repo, config.rebase)),
|
||||
}
|
||||
}
|
||||
|
||||
fn describe_rebase<'a>(root: &'a Path, rebase_config: &'a str) -> StateDescription<'a> {
|
||||
fn describe_rebase<'a>(repo: &'a Repo, rebase_config: &'a str) -> StateDescription<'a> {
|
||||
/*
|
||||
* Sadly, libgit2 seems to have some issues with reading the state of
|
||||
* interactive rebases. So, instead, we'll poke a few of the .git files
|
||||
|
@ -113,25 +111,13 @@ fn describe_rebase<'a>(root: &'a Path, rebase_config: &'a str) -> StateDescripti
|
|||
* The following is based heavily on: https://github.com/magicmonty/bash-git-prompt
|
||||
*/
|
||||
|
||||
let dot_git = root.join(".git");
|
||||
let dot_git = if let Ok(conf) = std::fs::read_to_string(&dot_git) {
|
||||
let gitdir_re = regex::Regex::new(r"(?m)^gitdir: (.*)$").unwrap();
|
||||
if let Some(caps) = gitdir_re.captures(&conf) {
|
||||
root.join(caps.get(1).unwrap().as_str())
|
||||
} else {
|
||||
dot_git
|
||||
}
|
||||
} else {
|
||||
dot_git
|
||||
};
|
||||
|
||||
let has_path = |relative_path: &str| {
|
||||
let path = dot_git.join(PathBuf::from(relative_path));
|
||||
let path = repo.path.join(PathBuf::from(relative_path));
|
||||
path.exists()
|
||||
};
|
||||
|
||||
let file_to_usize = |relative_path: &str| {
|
||||
let path = dot_git.join(PathBuf::from(relative_path));
|
||||
let path = repo.path.join(PathBuf::from(relative_path));
|
||||
let contents = crate::utils::read_file(path).ok()?;
|
||||
let quantity = contents.trim().parse::<usize>().ok()?;
|
||||
Some(quantity)
|
||||
|
|
Loading…
Reference in New Issue