Skip to content

Commit

Permalink
cli: rewrite base GitIgnoreFile lookup to use gitoxide instead of lib…
Browse files Browse the repository at this point in the history
…git2

Since gix::Repository::config_snapshot() borrows the repo instance, it has to
be allocated in caller's stack. That's why GitBackend::git_config() is removed.
  • Loading branch information
yuja committed Oct 31, 2023
1 parent 328a303 commit 7bb7358
Show file tree
Hide file tree
Showing 4 changed files with 26 additions and 28 deletions.
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions cli/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ dirs = { workspace = true }
esl01-renderdag = { workspace = true }
futures = { workspace = true }
git2 = { workspace = true }
gix = { workspace = true }
hex = { workspace = true }
indexmap = { workspace = true }
itertools = { workspace = true }
Expand Down
41 changes: 20 additions & 21 deletions cli/src/cli_util.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,14 +17,14 @@ use std::env::{self, ArgsOs, VarError};
use std::ffi::{OsStr, OsString};
use std::fmt::Debug;
use std::io::Write as _;
use std::iter;
use std::ops::Deref;
use std::path::{Path, PathBuf};
use std::process::ExitCode;
use std::rc::Rc;
use std::str::FromStr;
use std::sync::Arc;
use std::time::SystemTime;
use std::{iter, str};

use clap::builder::{NonEmptyStringValueParser, TypedValueParser, ValueParserFactory};
use clap::{Arg, ArgAction, ArgMatches, Command, FromArgMatches};
Expand Down Expand Up @@ -926,16 +926,18 @@ impl WorkspaceCommandHelper {
}
}

pub fn git_config(&self) -> Result<git2::Config, git2::Error> {
if let Some(git_backend) = self.git_backend() {
git_backend.git_config()
} else {
git2::Config::open_default()
}
}

#[instrument(skip_all)]
pub fn base_ignores(&self) -> Arc<GitIgnoreFile> {
fn get_excludes_file_path(config: &gix::config::File) -> Option<PathBuf> {
// TODO: maybe use path_by_key() and interpolate(), which can process non-utf-8
// path on Unix.
if let Some(value) = config.string_by_key("core.excludesFile") {
str::from_utf8(&value).ok().map(expand_git_path)
} else {
xdg_config_home().ok().map(|x| x.join("git").join("ignore"))
}
}

fn xdg_config_home() -> Result<PathBuf, VarError> {
if let Ok(x) = std::env::var("XDG_CONFIG_HOME") {
if !x.is_empty() {
Expand All @@ -946,20 +948,17 @@ impl WorkspaceCommandHelper {
}

let mut git_ignores = GitIgnoreFile::empty();
if let Ok(excludes_file_path) = self
.git_config()
.and_then(|git_config| {
git_config
.get_string("core.excludesFile")
.map(expand_git_path)
})
.or_else(|_| xdg_config_home().map(|x| x.join("git").join("ignore")))
{
git_ignores = git_ignores.chain_with_file("", excludes_file_path);
}
if let Some(git_backend) = self.git_backend() {
let git_repo = git_backend.git_repo();
if let Some(excludes_file_path) = get_excludes_file_path(&git_repo.config_snapshot()) {
git_ignores = git_ignores.chain_with_file("", excludes_file_path);
}
git_ignores = git_ignores
.chain_with_file("", git_backend.git_repo_path().join("info").join("exclude"));
} else if let Ok(git_config) = gix::config::File::from_globals() {
if let Some(excludes_file_path) = get_excludes_file_path(&git_config) {
git_ignores = git_ignores.chain_with_file("", excludes_file_path);
}
}
git_ignores
}
Expand Down Expand Up @@ -1853,7 +1852,7 @@ export or their "parent" branches."#,
}

/// Expands "~/" to "$HOME/" as Git seems to do for e.g. core.excludesFile.
fn expand_git_path(path_str: String) -> PathBuf {
fn expand_git_path(path_str: &str) -> PathBuf {
if let Some(remainder) = path_str.strip_prefix("~/") {
if let Ok(home_dir_str) = std::env::var("HOME") {
return PathBuf::from(home_dir_str).join(remainder);
Expand Down
11 changes: 4 additions & 7 deletions lib/src/git_backend.rs
Original file line number Diff line number Diff line change
Expand Up @@ -206,19 +206,16 @@ impl GitBackend {
self.repo.lock().unwrap()
}

// TODO: add public API to obtain new gix::Repository from base_repo
/// Returns new thread-local instance to access to the underlying Git repo.
pub fn git_repo(&self) -> gix::Repository {
self.base_repo.to_thread_local()
}

/// Creates new owned git repository instance.
pub fn open_git_repo(&self) -> Result<git2::Repository, git2::Error> {
git2::Repository::open(self.git_repo_path())
}

/// Git configuration for this repository.
pub fn git_config(&self) -> Result<git2::Config, git2::Error> {
// TODO: switch to gix config type
self.open_git_repo().and_then(|repo| repo.config())
}

/// Path to the `.git` directory or the repository itself if it's bare.
pub fn git_repo_path(&self) -> &Path {
self.base_repo.path()
Expand Down

0 comments on commit 7bb7358

Please sign in to comment.