mirror of
https://github.com/gitui-org/gitui
synced 2026-05-23 17:08:21 +00:00
Use gitoxide in get_status (#2673)
This commit is contained in:
parent
6d0a2ec115
commit
6685f9adb3
11 changed files with 494 additions and 60 deletions
219
Cargo.lock
generated
219
Cargo.lock
generated
|
|
@ -675,6 +675,20 @@ dependencies = [
|
|||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "dashmap"
|
||||
version = "6.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5041cc499144891f3790297212f32a74fb938e5136a14943f338ef9e0ae276cf"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"crossbeam-utils",
|
||||
"hashbrown 0.14.5",
|
||||
"lock_api",
|
||||
"once_cell",
|
||||
"parking_lot_core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "der"
|
||||
version = "0.7.9"
|
||||
|
|
@ -816,6 +830,15 @@ dependencies = [
|
|||
"zeroize",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "encoding_rs"
|
||||
version = "0.8.35"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "75030f3c4f45dafd7586dd6780965a8c7e8e285a5ecb86713e63a79c5b2766f3"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "env_filter"
|
||||
version = "0.1.3"
|
||||
|
|
@ -1212,16 +1235,21 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
checksum = "a61e71ec6817fc3c9f12f812682cfe51ee6ea0d2e27e02fc3849c35524617435"
|
||||
dependencies = [
|
||||
"gix-actor",
|
||||
"gix-attributes",
|
||||
"gix-command",
|
||||
"gix-commitgraph",
|
||||
"gix-config",
|
||||
"gix-date",
|
||||
"gix-diff",
|
||||
"gix-dir",
|
||||
"gix-discover",
|
||||
"gix-features",
|
||||
"gix-filter",
|
||||
"gix-fs",
|
||||
"gix-glob",
|
||||
"gix-hash",
|
||||
"gix-hashtable",
|
||||
"gix-ignore",
|
||||
"gix-index",
|
||||
"gix-lock",
|
||||
"gix-mailmap",
|
||||
|
|
@ -1229,6 +1257,7 @@ dependencies = [
|
|||
"gix-odb",
|
||||
"gix-pack",
|
||||
"gix-path",
|
||||
"gix-pathspec",
|
||||
"gix-protocol",
|
||||
"gix-ref",
|
||||
"gix-refspec",
|
||||
|
|
@ -1236,12 +1265,15 @@ dependencies = [
|
|||
"gix-revwalk",
|
||||
"gix-sec",
|
||||
"gix-shallow",
|
||||
"gix-status",
|
||||
"gix-submodule",
|
||||
"gix-tempfile",
|
||||
"gix-trace",
|
||||
"gix-traverse",
|
||||
"gix-url",
|
||||
"gix-utils",
|
||||
"gix-validate",
|
||||
"gix-worktree",
|
||||
"once_cell",
|
||||
"smallvec",
|
||||
"thiserror 2.0.12",
|
||||
|
|
@ -1261,6 +1293,23 @@ dependencies = [
|
|||
"winnow",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "gix-attributes"
|
||||
version = "0.25.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e4e25825e0430aa11096f8b65ced6780d4a96a133f81904edceebb5344c8dd7f"
|
||||
dependencies = [
|
||||
"bstr",
|
||||
"gix-glob",
|
||||
"gix-path",
|
||||
"gix-quote",
|
||||
"gix-trace",
|
||||
"kstring",
|
||||
"smallvec",
|
||||
"thiserror 2.0.12",
|
||||
"unicode-bom",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "gix-bitmap"
|
||||
version = "0.2.14"
|
||||
|
|
@ -1358,8 +1407,40 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
checksum = "a2c975dad2afc85e4e233f444d1efbe436c3cdcf3a07173984509c436d00a3f8"
|
||||
dependencies = [
|
||||
"bstr",
|
||||
"gix-attributes",
|
||||
"gix-command",
|
||||
"gix-filter",
|
||||
"gix-fs",
|
||||
"gix-hash",
|
||||
"gix-index",
|
||||
"gix-object",
|
||||
"gix-path",
|
||||
"gix-pathspec",
|
||||
"gix-tempfile",
|
||||
"gix-trace",
|
||||
"gix-traverse",
|
||||
"gix-worktree",
|
||||
"imara-diff",
|
||||
"thiserror 2.0.12",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "gix-dir"
|
||||
version = "0.13.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5879497bd3815d8277ed864ec8975290a70de5b62bb92d2d666a4cefc5d4793b"
|
||||
dependencies = [
|
||||
"bstr",
|
||||
"gix-discover",
|
||||
"gix-fs",
|
||||
"gix-ignore",
|
||||
"gix-index",
|
||||
"gix-object",
|
||||
"gix-path",
|
||||
"gix-pathspec",
|
||||
"gix-trace",
|
||||
"gix-utils",
|
||||
"gix-worktree",
|
||||
"thiserror 2.0.12",
|
||||
]
|
||||
|
||||
|
|
@ -1399,6 +1480,27 @@ dependencies = [
|
|||
"walkdir",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "gix-filter"
|
||||
version = "0.18.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cb2b2bbffdc5cc9b2b82fc82da1b98163c9b423ac2b45348baa83a947ac9ab89"
|
||||
dependencies = [
|
||||
"bstr",
|
||||
"encoding_rs",
|
||||
"gix-attributes",
|
||||
"gix-command",
|
||||
"gix-hash",
|
||||
"gix-object",
|
||||
"gix-packetline-blocking",
|
||||
"gix-path",
|
||||
"gix-quote",
|
||||
"gix-trace",
|
||||
"gix-utils",
|
||||
"smallvec",
|
||||
"thiserror 2.0.12",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "gix-fs"
|
||||
version = "0.14.0"
|
||||
|
|
@ -1448,6 +1550,19 @@ dependencies = [
|
|||
"parking_lot",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "gix-ignore"
|
||||
version = "0.14.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9a27c8380f493a10d1457f756a3f81924d578fc08d6535e304dfcafbf0261d18"
|
||||
dependencies = [
|
||||
"bstr",
|
||||
"gix-glob",
|
||||
"gix-path",
|
||||
"gix-trace",
|
||||
"unicode-bom",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "gix-index"
|
||||
version = "0.39.0"
|
||||
|
|
@ -1572,6 +1687,18 @@ dependencies = [
|
|||
"thiserror 2.0.12",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "gix-packetline-blocking"
|
||||
version = "0.18.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1ecf3ea2e105c7e45587bac04099824301262a6c43357fad5205da36dbb233b3"
|
||||
dependencies = [
|
||||
"bstr",
|
||||
"faster-hex",
|
||||
"gix-trace",
|
||||
"thiserror 2.0.12",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "gix-path"
|
||||
version = "0.10.15"
|
||||
|
|
@ -1585,6 +1712,21 @@ dependencies = [
|
|||
"thiserror 2.0.12",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "gix-pathspec"
|
||||
version = "0.10.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fef8422c3c9066d649074b24025125963f85232bfad32d6d16aea9453b82ec14"
|
||||
dependencies = [
|
||||
"bitflags 2.9.1",
|
||||
"bstr",
|
||||
"gix-attributes",
|
||||
"gix-config-value",
|
||||
"gix-glob",
|
||||
"gix-path",
|
||||
"thiserror 2.0.12",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "gix-protocol"
|
||||
version = "0.49.0"
|
||||
|
|
@ -1707,12 +1849,51 @@ dependencies = [
|
|||
"thiserror 2.0.12",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "gix-status"
|
||||
version = "0.18.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "605a6d0eb5891680c46e24b2ee7a63ef7bd39cb136dc7c7e55172960cf68b2f5"
|
||||
dependencies = [
|
||||
"bstr",
|
||||
"filetime",
|
||||
"gix-diff",
|
||||
"gix-dir",
|
||||
"gix-features",
|
||||
"gix-filter",
|
||||
"gix-fs",
|
||||
"gix-hash",
|
||||
"gix-index",
|
||||
"gix-object",
|
||||
"gix-path",
|
||||
"gix-pathspec",
|
||||
"gix-worktree",
|
||||
"portable-atomic",
|
||||
"thiserror 2.0.12",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "gix-submodule"
|
||||
version = "0.18.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "78c7390c2059505c365e9548016d4edc9f35749c6a9112b7b1214400bbc68da2"
|
||||
dependencies = [
|
||||
"bstr",
|
||||
"gix-config",
|
||||
"gix-path",
|
||||
"gix-pathspec",
|
||||
"gix-refspec",
|
||||
"gix-url",
|
||||
"thiserror 2.0.12",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "gix-tempfile"
|
||||
version = "17.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3d6de439bbb9a5d3550c9c7fab0e16d2d637d120fcbe0dfbc538772a187f099b"
|
||||
dependencies = [
|
||||
"dashmap",
|
||||
"gix-fs",
|
||||
"libc",
|
||||
"once_cell",
|
||||
|
|
@ -1779,6 +1960,7 @@ version = "0.2.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "189f8724cf903e7fd57cfe0b7bc209db255cacdcb22c781a022f52c3a774f8d0"
|
||||
dependencies = [
|
||||
"bstr",
|
||||
"fastrand",
|
||||
"unicode-normalization",
|
||||
]
|
||||
|
|
@ -1793,6 +1975,25 @@ dependencies = [
|
|||
"thiserror 2.0.12",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "gix-worktree"
|
||||
version = "0.40.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f7760dbc4b79aa274fed30adc0d41dca6b917641f26e7867c4071b1fb4dc727b"
|
||||
dependencies = [
|
||||
"bstr",
|
||||
"gix-attributes",
|
||||
"gix-features",
|
||||
"gix-fs",
|
||||
"gix-glob",
|
||||
"gix-hash",
|
||||
"gix-ignore",
|
||||
"gix-index",
|
||||
"gix-object",
|
||||
"gix-path",
|
||||
"gix-validate",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "group"
|
||||
version = "0.13.0"
|
||||
|
|
@ -2017,6 +2218,15 @@ dependencies = [
|
|||
"icu_properties",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "imara-diff"
|
||||
version = "0.1.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "17d34b7d42178945f775e84bc4c36dde7c1c6cdfea656d3354d009056f2bb3d2"
|
||||
dependencies = [
|
||||
"hashbrown 0.15.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "indexmap"
|
||||
version = "2.9.0"
|
||||
|
|
@ -2190,6 +2400,15 @@ dependencies = [
|
|||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "kstring"
|
||||
version = "2.0.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "558bf9508a558512042d3095138b1f7b8fe90c5467d94f9f1da28b3731c5dbd1"
|
||||
dependencies = [
|
||||
"static_assertions",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "lazy_static"
|
||||
version = "1.5.0"
|
||||
|
|
|
|||
|
|
@ -28,6 +28,7 @@ gix = { version = "0.71.0", default-features = false, features = [
|
|||
"max-performance",
|
||||
"revision",
|
||||
"mailmap",
|
||||
"status",
|
||||
] }
|
||||
log = "0.4"
|
||||
# git2 = { path = "../../extern/git2-rs", features = ["vendored-openssl"]}
|
||||
|
|
|
|||
|
|
@ -123,6 +123,44 @@ pub enum Error {
|
|||
#[from] gix::object::find::existing::with_conversion::Error,
|
||||
),
|
||||
|
||||
///
|
||||
#[error("gix::pathspec::init::Error error: {0}")]
|
||||
GixPathspecInit(#[from] Box<gix::pathspec::init::Error>),
|
||||
|
||||
///
|
||||
#[error("gix::reference::head_tree_id::Error error: {0}")]
|
||||
GixReferenceHeadTreeId(
|
||||
#[from] gix::reference::head_tree_id::Error,
|
||||
),
|
||||
|
||||
///
|
||||
#[error("gix::status::Error error: {0}")]
|
||||
GixStatus(#[from] Box<gix::status::Error>),
|
||||
|
||||
///
|
||||
#[error("gix::status::iter::Error error: {0}")]
|
||||
GixStatusIter(#[from] Box<gix::status::iter::Error>),
|
||||
|
||||
///
|
||||
#[error("gix::status::into_iter::Error error: {0}")]
|
||||
GixStatusIntoIter(#[from] Box<gix::status::into_iter::Error>),
|
||||
|
||||
///
|
||||
#[error("gix::status::index_worktree::Error error: {0}")]
|
||||
GixStatusIndexWorktree(
|
||||
#[from] Box<gix::status::index_worktree::Error>,
|
||||
),
|
||||
|
||||
///
|
||||
#[error("gix::status::tree_index::Error error: {0}")]
|
||||
GixStatusTreeIndex(#[from] Box<gix::status::tree_index::Error>),
|
||||
|
||||
///
|
||||
#[error("gix::worktree::open_index::Error error: {0}")]
|
||||
GixWorktreeOpenIndex(
|
||||
#[from] Box<gix::worktree::open_index::Error>,
|
||||
),
|
||||
|
||||
///
|
||||
#[error("amend error: config commit.gpgsign=true detected.\ngpg signing is not supported for amending non-last commits")]
|
||||
SignAmendNonLastCommit,
|
||||
|
|
@ -156,3 +194,45 @@ impl From<gix::discover::Error> for Error {
|
|||
Self::GixDiscover(Box::new(error))
|
||||
}
|
||||
}
|
||||
|
||||
impl From<gix::pathspec::init::Error> for Error {
|
||||
fn from(error: gix::pathspec::init::Error) -> Self {
|
||||
Self::GixPathspecInit(Box::new(error))
|
||||
}
|
||||
}
|
||||
|
||||
impl From<gix::status::Error> for Error {
|
||||
fn from(error: gix::status::Error) -> Self {
|
||||
Self::GixStatus(Box::new(error))
|
||||
}
|
||||
}
|
||||
|
||||
impl From<gix::status::iter::Error> for Error {
|
||||
fn from(error: gix::status::iter::Error) -> Self {
|
||||
Self::GixStatusIter(Box::new(error))
|
||||
}
|
||||
}
|
||||
|
||||
impl From<gix::status::into_iter::Error> for Error {
|
||||
fn from(error: gix::status::into_iter::Error) -> Self {
|
||||
Self::GixStatusIntoIter(Box::new(error))
|
||||
}
|
||||
}
|
||||
|
||||
impl From<gix::status::index_worktree::Error> for Error {
|
||||
fn from(error: gix::status::index_worktree::Error) -> Self {
|
||||
Self::GixStatusIndexWorktree(Box::new(error))
|
||||
}
|
||||
}
|
||||
|
||||
impl From<gix::status::tree_index::Error> for Error {
|
||||
fn from(error: gix::status::tree_index::Error) -> Self {
|
||||
Self::GixStatusTreeIndex(Box::new(error))
|
||||
}
|
||||
}
|
||||
|
||||
impl From<gix::worktree::open_index::Error> for Error {
|
||||
fn from(error: gix::worktree::open_index::Error) -> Self {
|
||||
Self::GixWorktreeOpenIndex(Box::new(error))
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
use crate::{
|
||||
error::Result,
|
||||
sync::{
|
||||
repo, CommitId, LogWalker, LogWalkerWithoutFilter, RepoPath,
|
||||
SharedCommitFilterFn,
|
||||
gix_repo, repo, CommitId, LogWalker, LogWalkerWithoutFilter,
|
||||
RepoPath, SharedCommitFilterFn,
|
||||
},
|
||||
AsyncGitNotification, Error,
|
||||
};
|
||||
|
|
@ -276,9 +276,7 @@ impl AsyncLog {
|
|||
let mut entries = vec![CommitId::default(); LIMIT_COUNT];
|
||||
entries.resize(0, CommitId::default());
|
||||
|
||||
let mut repo: gix::Repository =
|
||||
gix::ThreadSafeRepository::discover_with_environment_overrides(repo_path.gitpath())
|
||||
.map(Into::into)?;
|
||||
let mut repo: gix::Repository = gix_repo(repo_path)?;
|
||||
let mut walker =
|
||||
LogWalkerWithoutFilter::new(&mut repo, LIMIT_COUNT)?;
|
||||
|
||||
|
|
|
|||
|
|
@ -3,7 +3,10 @@ use std::fmt::Display;
|
|||
use super::RepoPath;
|
||||
use crate::{
|
||||
error::Result,
|
||||
sync::{commit_details::get_author_of_commit, repository::repo},
|
||||
sync::{
|
||||
commit_details::get_author_of_commit,
|
||||
repository::{gix_repo, repo},
|
||||
},
|
||||
};
|
||||
use git2::{Commit, Error, Oid};
|
||||
use scopetime::scope_time;
|
||||
|
|
@ -157,9 +160,7 @@ pub fn get_commit_info(
|
|||
) -> Result<CommitInfo> {
|
||||
scope_time!("get_commit_info");
|
||||
|
||||
let repo: gix::Repository =
|
||||
gix::ThreadSafeRepository::discover_with_environment_overrides(repo_path.gitpath())
|
||||
.map(Into::into)?;
|
||||
let repo: gix::Repository = gix_repo(repo_path)?;
|
||||
let mailmap = repo.open_mailmap();
|
||||
|
||||
let commit = repo.find_commit(*commit_id)?;
|
||||
|
|
|
|||
|
|
@ -56,6 +56,13 @@ pub fn untracked_files_config_repo(
|
|||
}
|
||||
}
|
||||
|
||||
// This does not reflect how git works according to its docs that say: "If this variable is not
|
||||
// specified, it defaults to `normal`."
|
||||
//
|
||||
// https://git-scm.com/docs/git-config#Documentation/git-config.txt-statusshowUntrackedFiles
|
||||
//
|
||||
// Note that this might become less relevant over time as more code gets migrated to `gitoxide`
|
||||
// because `gitoxide` respects `status.showUntrackedFiles` by default.
|
||||
Ok(ShowUntrackedFilesConfig::All)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -181,6 +181,7 @@ mod tests {
|
|||
use super::*;
|
||||
use crate::error::Result;
|
||||
use crate::sync::commit_filter::{SearchFields, SearchOptions};
|
||||
use crate::sync::repository::gix_repo;
|
||||
use crate::sync::tests::write_commit_file;
|
||||
use crate::sync::{
|
||||
commit, get_commits_info, stage_add_file,
|
||||
|
|
@ -266,10 +267,7 @@ mod tests {
|
|||
stage_add_file(repo_path, file_path).unwrap();
|
||||
let oid2 = commit(repo_path, "commit2").unwrap();
|
||||
|
||||
let mut repo: gix::Repository =
|
||||
gix::ThreadSafeRepository::discover_with_environment_overrides(repo_path.gitpath())
|
||||
.map(Into::into)
|
||||
.unwrap();
|
||||
let mut repo: gix::Repository = gix_repo(repo_path)?;
|
||||
let mut walk = LogWalkerWithoutFilter::new(&mut repo, 100)?;
|
||||
let mut items = Vec::new();
|
||||
assert!(matches!(walk.read(&mut items), Ok(2)));
|
||||
|
|
|
|||
|
|
@ -84,7 +84,7 @@ pub use remotes::{
|
|||
get_remote_url, get_remotes, push::AsyncProgress, rename_remote,
|
||||
tags::PushTagsProgress, update_remote_url, validate_remote_name,
|
||||
};
|
||||
pub(crate) use repository::repo;
|
||||
pub(crate) use repository::{gix_repo, repo};
|
||||
pub use repository::{RepoPath, RepoPathRef};
|
||||
pub use reset::{reset_repo, reset_stage, reset_workdir};
|
||||
pub use reword::reword;
|
||||
|
|
|
|||
|
|
@ -67,3 +67,12 @@ pub fn repo(repo_path: &RepoPath) -> Result<Repository> {
|
|||
|
||||
Ok(repo)
|
||||
}
|
||||
|
||||
pub fn gix_repo(repo_path: &RepoPath) -> Result<gix::Repository> {
|
||||
let repo = gix::ThreadSafeRepository::discover_with_environment_overrides(
|
||||
repo_path.gitpath(),
|
||||
)
|
||||
.map(Into::into)?;
|
||||
|
||||
Ok(repo)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,9 +1,11 @@
|
|||
//! sync git api for fetching a status
|
||||
|
||||
use crate::{
|
||||
error::Error,
|
||||
error::Result,
|
||||
sync::{config::untracked_files_config_repo, repository::repo},
|
||||
sync::{
|
||||
config::untracked_files_config_repo,
|
||||
repository::{gix_repo, repo},
|
||||
},
|
||||
};
|
||||
use git2::{Delta, Status, StatusOptions, StatusShow};
|
||||
use scopetime::scope_time;
|
||||
|
|
@ -28,6 +30,40 @@ pub enum StatusItemType {
|
|||
Conflicted,
|
||||
}
|
||||
|
||||
impl From<gix::status::index_worktree::iter::Summary>
|
||||
for StatusItemType
|
||||
{
|
||||
fn from(
|
||||
summary: gix::status::index_worktree::iter::Summary,
|
||||
) -> Self {
|
||||
use gix::status::index_worktree::iter::Summary;
|
||||
|
||||
match summary {
|
||||
Summary::Removed => Self::Deleted,
|
||||
Summary::Added
|
||||
| Summary::Copied
|
||||
| Summary::IntentToAdd => Self::New,
|
||||
Summary::Modified => Self::Modified,
|
||||
Summary::TypeChange => Self::Typechange,
|
||||
Summary::Renamed => Self::Renamed,
|
||||
Summary::Conflict => Self::Conflicted,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<gix::diff::index::ChangeRef<'_, '_>> for StatusItemType {
|
||||
fn from(change_ref: gix::diff::index::ChangeRef) -> Self {
|
||||
use gix::diff::index::ChangeRef;
|
||||
|
||||
match change_ref {
|
||||
ChangeRef::Addition { .. } => Self::New,
|
||||
ChangeRef::Deletion { .. } => Self::Deleted,
|
||||
ChangeRef::Modification { .. }
|
||||
| ChangeRef::Rewrite { .. } => Self::Modified,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Status> for StatusItemType {
|
||||
fn from(s: Status) -> Self {
|
||||
if s.is_index_new() || s.is_wt_new() {
|
||||
|
|
@ -126,6 +162,16 @@ pub fn is_workdir_clean(
|
|||
Ok(statuses.is_empty())
|
||||
}
|
||||
|
||||
impl From<ShowUntrackedFilesConfig> for gix::status::UntrackedFiles {
|
||||
fn from(value: ShowUntrackedFilesConfig) -> Self {
|
||||
match value {
|
||||
ShowUntrackedFilesConfig::All => Self::Files,
|
||||
ShowUntrackedFilesConfig::Normal => Self::Collapsed,
|
||||
ShowUntrackedFilesConfig::No => Self::None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// guarantees sorting
|
||||
pub fn get_status(
|
||||
repo_path: &RepoPath,
|
||||
|
|
@ -134,59 +180,91 @@ pub fn get_status(
|
|||
) -> Result<Vec<StatusItem>> {
|
||||
scope_time!("get_status");
|
||||
|
||||
let repo = repo(repo_path)?;
|
||||
let repo: gix::Repository = gix_repo(repo_path)?;
|
||||
|
||||
if repo.is_bare() && !repo.is_worktree() {
|
||||
return Ok(Vec::new());
|
||||
let mut status = repo.status(gix::progress::Discard)?;
|
||||
|
||||
if let Some(config) = show_untracked {
|
||||
status = status.untracked_files(config.into());
|
||||
}
|
||||
|
||||
let show_untracked = if let Some(config) = show_untracked {
|
||||
config
|
||||
} else {
|
||||
untracked_files_config_repo(&repo)?
|
||||
};
|
||||
let mut res = Vec::new();
|
||||
|
||||
let mut options = StatusOptions::default();
|
||||
options
|
||||
.show(status_type.into())
|
||||
.update_index(true)
|
||||
.include_untracked(show_untracked.include_untracked())
|
||||
.renames_head_to_index(true)
|
||||
.recurse_untracked_dirs(
|
||||
show_untracked.recurse_untracked_dirs(),
|
||||
);
|
||||
match status_type {
|
||||
StatusType::WorkingDir => {
|
||||
let iter = status.into_index_worktree_iter(Vec::new())?;
|
||||
|
||||
let statuses = repo.statuses(Some(&mut options))?;
|
||||
for item in iter {
|
||||
let item = item?;
|
||||
|
||||
let mut res = Vec::with_capacity(statuses.len());
|
||||
let status = item.summary().map(Into::into);
|
||||
|
||||
for e in statuses.iter() {
|
||||
let status: Status = e.status();
|
||||
if let Some(status) = status {
|
||||
let path = item.rela_path().to_string();
|
||||
|
||||
let path = match e.head_to_index() {
|
||||
Some(diff) => diff
|
||||
.new_file()
|
||||
.path()
|
||||
.and_then(Path::to_str)
|
||||
.map(String::from)
|
||||
.ok_or_else(|| {
|
||||
Error::Generic(
|
||||
"failed to get path to diff's new file."
|
||||
.to_string(),
|
||||
)
|
||||
})?,
|
||||
None => e.path().map(String::from).ok_or_else(|| {
|
||||
Error::Generic(
|
||||
"failed to get the path to indexed file."
|
||||
.to_string(),
|
||||
)
|
||||
})?,
|
||||
};
|
||||
res.push(StatusItem { path, status });
|
||||
}
|
||||
}
|
||||
}
|
||||
StatusType::Stage => {
|
||||
let tree_id: gix::ObjectId =
|
||||
repo.head_tree_id_or_empty()?.into();
|
||||
let worktree_index =
|
||||
gix::worktree::IndexPersistedOrInMemory::Persisted(
|
||||
repo.index_or_empty()?,
|
||||
);
|
||||
|
||||
res.push(StatusItem {
|
||||
path,
|
||||
status: StatusItemType::from(status),
|
||||
});
|
||||
let mut pathspec = repo.pathspec(
|
||||
false, /* empty patterns match prefix */
|
||||
None::<&str>,
|
||||
true, /* inherit ignore case */
|
||||
&gix::index::State::new(repo.object_hash()),
|
||||
gix::worktree::stack::state::attributes::Source::WorktreeThenIdMapping
|
||||
)?;
|
||||
|
||||
let cb =
|
||||
|change_ref: gix::diff::index::ChangeRef<'_, '_>,
|
||||
_: &gix::index::State,
|
||||
_: &gix::index::State|
|
||||
-> Result<gix::diff::index::Action> {
|
||||
let path = change_ref.fields().0.to_string();
|
||||
let status = change_ref.into();
|
||||
|
||||
res.push(StatusItem { path, status });
|
||||
|
||||
Ok(gix::diff::index::Action::Continue)
|
||||
};
|
||||
|
||||
repo.tree_index_status(
|
||||
&tree_id,
|
||||
&worktree_index,
|
||||
Some(&mut pathspec),
|
||||
gix::status::tree_index::TrackRenames::default(),
|
||||
cb,
|
||||
)?;
|
||||
}
|
||||
StatusType::Both => {
|
||||
let iter = status.into_iter(Vec::new())?;
|
||||
|
||||
for item in iter {
|
||||
let item = item?;
|
||||
|
||||
let path = item.location().to_string();
|
||||
|
||||
let status = match item {
|
||||
gix::status::Item::IndexWorktree(item) => {
|
||||
item.summary().map(Into::into)
|
||||
}
|
||||
gix::status::Item::TreeIndex(change_ref) => {
|
||||
Some(change_ref.into())
|
||||
}
|
||||
};
|
||||
|
||||
if let Some(status) = status {
|
||||
res.push(StatusItem { path, status });
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
res.sort_by(|a, b| {
|
||||
|
|
|
|||
|
|
@ -230,6 +230,7 @@ mod tests {
|
|||
},
|
||||
};
|
||||
use std::{
|
||||
env,
|
||||
fs::{self, remove_file, File},
|
||||
io::Write,
|
||||
path::Path,
|
||||
|
|
@ -270,6 +271,44 @@ mod tests {
|
|||
assert_eq!(get_statuses(repo_path), (1, 1));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_staging_one_file_from_different_sub_directory() {
|
||||
// This test case covers an interaction between current working directory and the way
|
||||
// `gitoxide` handles pathspecs.
|
||||
//
|
||||
// When staging a new file in one sub-directory, then running running `get_status` in a
|
||||
// different sub-directory, `repo.pathspec` in `get_status` has to initialized with
|
||||
// `empty_patterns_match_prefix` set to `false` for `get_status` to report the staged file’s
|
||||
// status.
|
||||
let file_path = Path::new("untracked/file1.txt");
|
||||
let (_td, repo) = repo_init().unwrap();
|
||||
let root = repo.path().parent().unwrap();
|
||||
let repo_path: &RepoPath =
|
||||
&root.as_os_str().to_str().unwrap().into();
|
||||
|
||||
fs::create_dir(root.join("untracked")).unwrap();
|
||||
|
||||
File::create(root.join(file_path))
|
||||
.unwrap()
|
||||
.write_all(b"test file1 content")
|
||||
.unwrap();
|
||||
|
||||
let sub_dir_path = root.join("unrelated");
|
||||
|
||||
fs::create_dir(root.join("unrelated")).unwrap();
|
||||
|
||||
let current_dir = env::current_dir().unwrap();
|
||||
env::set_current_dir(sub_dir_path).unwrap();
|
||||
|
||||
assert_eq!(get_statuses(repo_path), (1, 0));
|
||||
|
||||
stage_add_file(repo_path, file_path).unwrap();
|
||||
|
||||
assert_eq!(get_statuses(repo_path), (0, 1));
|
||||
|
||||
env::set_current_dir(current_dir).unwrap();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_staging_folder() -> Result<()> {
|
||||
let (_td, repo) = repo_init().unwrap();
|
||||
|
|
@ -289,6 +328,8 @@ mod tests {
|
|||
File::create(root.join(Path::new("a/f3.txt")))?
|
||||
.write_all(b"foo")?;
|
||||
|
||||
repo.config()?.set_str("status.showUntrackedFiles", "all")?;
|
||||
|
||||
assert_eq!(status_count(StatusType::WorkingDir), 3);
|
||||
|
||||
stage_add_all(repo_path, "a/d", None).unwrap();
|
||||
|
|
@ -351,6 +392,8 @@ mod tests {
|
|||
File::create(root.join(Path::new("f3.txt")))?
|
||||
.write_all(b"foo")?;
|
||||
|
||||
repo.config()?.set_str("status.showUntrackedFiles", "all")?;
|
||||
|
||||
assert_eq!(get_statuses(repo_path), (3, 0));
|
||||
|
||||
repo.config()?.set_str("status.showUntrackedFiles", "no")?;
|
||||
|
|
|
|||
Loading…
Reference in a new issue