Skip to content

Commit 30d69d3

Browse files
committed
feat: Repository::is_dirty() now also checks for tree/index changes.
This copmpletes the `is_dirty()` implementation.
1 parent f0e23b4 commit 30d69d3

File tree

5 files changed

+45
-11
lines changed

5 files changed

+45
-11
lines changed

gix/src/config/cache/access.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -181,7 +181,7 @@ impl Cache {
181181
.user_agent
182182
.get_or_init(|| {
183183
self.resolved
184-
.string(Gitoxide::USER_AGENT.logical_name().as_str())
184+
.string(&Gitoxide::USER_AGENT)
185185
.map_or_else(|| crate::env::agent().into(), |s| s.to_string())
186186
})
187187
.to_owned();

gix/src/status/mod.rs

+23-6
Original file line numberDiff line numberDiff line change
@@ -129,7 +129,8 @@ impl Repository {
129129

130130
///
131131
pub mod is_dirty {
132-
use crate::Repository;
132+
use crate::{config, Repository};
133+
use std::convert::Infallible;
133134

134135
/// The error returned by [Repository::is_dirty()].
135136
#[derive(Debug, thiserror::Error)]
@@ -139,6 +140,10 @@ pub mod is_dirty {
139140
StatusPlatform(#[from] crate::status::Error),
140141
#[error(transparent)]
141142
CreateStatusIterator(#[from] crate::status::index_worktree::iter::Error),
143+
#[error(transparent)]
144+
TreeIndexStatus(#[from] crate::status::tree_index::Error),
145+
#[error(transparent)]
146+
HeadTreeId(#[from] crate::reference::head_tree_id::Error),
142147
}
143148

144149
impl Repository {
@@ -150,12 +155,24 @@ pub mod is_dirty {
150155
/// * submodules are taken in consideration, along with their `ignore` and `isActive` configuration
151156
///
152157
/// Note that *untracked files* do *not* affect this flag.
153-
///
154-
/// ### Incomplete Implementation Warning
155-
///
156-
/// Currently, this does not compute changes between the head and the index.
157-
// TODO: use iterator which also tests for head->index changes.
158158
pub fn is_dirty(&self) -> Result<bool, Error> {
159+
{
160+
let mut repo = self.clone();
161+
repo.config_snapshot_mut()
162+
.set_value(&config::tree::Status::RENAMES, "false")
163+
.expect("setting known values in memory always works");
164+
let head_tree_id = repo.head_tree_id()?;
165+
let mut index_is_dirty = false;
166+
167+
// Run this first as there is a high likelihood to find something, and it's very fast.
168+
repo.tree_index_status(&head_tree_id, None, |_, _, _| {
169+
index_is_dirty = true;
170+
Ok::<_, Infallible>(gix_diff::index::Action::Cancel)
171+
})?;
172+
if index_is_dirty {
173+
return Ok(true);
174+
}
175+
}
159176
let is_dirty = self
160177
.status(gix_features::progress::Discard)?
161178
.index_worktree_rewrites(None)
Binary file not shown.

gix/tests/fixtures/make_status_repos.sh

+8
Original file line numberDiff line numberDiff line change
@@ -13,3 +13,11 @@ git init -q untracked-only
1313
mkdir new
1414
touch new/untracked subdir/untracked
1515
)
16+
17+
git init git-mv
18+
(cd git-mv
19+
echo hi > file
20+
git add file && git commit -m "init"
21+
22+
git mv file renamed
23+
)

gix/tests/gix/status.rs

+13-4
Original file line numberDiff line numberDiff line change
@@ -134,7 +134,7 @@ mod index_worktree {
134134
}
135135

136136
mod is_dirty {
137-
use crate::status::submodule_repo;
137+
use crate::status::{repo, submodule_repo};
138138

139139
#[test]
140140
fn various_changes_positive() -> crate::Result {
@@ -155,7 +155,7 @@ mod is_dirty {
155155
let repo = submodule_repo("module1")?;
156156
assert_eq!(
157157
repo.status(gix::progress::Discard)?
158-
.into_index_worktree_iter(Vec::new())?
158+
.into_index_worktree_iter(None)?
159159
.count(),
160160
1,
161161
"there is one untracked file"
@@ -168,9 +168,18 @@ mod is_dirty {
168168
}
169169

170170
#[test]
171-
fn no_changes() -> crate::Result {
171+
fn index_changed() -> crate::Result {
172+
let repo = repo("git-mv")?;
173+
assert!(
174+
repo.is_dirty()?,
175+
"the only detectable change is in the index, in comparison to the HEAD^{{tree}}"
176+
);
177+
172178
let repo = submodule_repo("with-submodules")?;
173-
assert!(!repo.is_dirty()?, "there are no changes");
179+
assert!(
180+
repo.is_dirty()?,
181+
"the index changed here as well, this time there is also a new file"
182+
);
174183
Ok(())
175184
}
176185
}

0 commit comments

Comments
 (0)