Skip to content

Commit 2d0b661

Browse files
committed
Explicitly pass pathspec to include more files
With this change, when `get_status` is run in a sub-directory, it also returns matches in sub-directories that don’t share a prefix with the sub-directory it is being run in.
1 parent e413548 commit 2d0b661

File tree

3 files changed

+58
-1
lines changed

3 files changed

+58
-1
lines changed

asyncgit/src/error.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,10 @@ pub enum Error {
123123
#[from] gix::object::find::existing::with_conversion::Error,
124124
),
125125

126+
///
127+
#[error("gix::pathspec::init::Error error: {0}")]
128+
GixPathspecInit(#[from] Box<gix::pathspec::init::Error>),
129+
126130
///
127131
#[error("gix::reference::head_tree_id::Error error: {0}")]
128132
GixReferenceHeadTreeId(
@@ -191,6 +195,12 @@ impl From<gix::discover::Error> for Error {
191195
}
192196
}
193197

198+
impl From<gix::pathspec::init::Error> for Error {
199+
fn from(error: gix::pathspec::init::Error) -> Self {
200+
Self::GixPathspecInit(Box::new(error))
201+
}
202+
}
203+
194204
impl From<gix::status::Error> for Error {
195205
fn from(error: gix::status::Error) -> Self {
196206
Self::GixStatus(Box::new(error))

asyncgit/src/sync/status.rs

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -213,6 +213,14 @@ pub fn get_status(
213213
repo.index_or_empty()?,
214214
);
215215

216+
let mut pathspec = repo.pathspec(
217+
false, /* empty patterns match prefix */
218+
None::<&str>,
219+
true, /* inherit ignore case */
220+
&gix::index::State::new(repo.object_hash()),
221+
gix::worktree::stack::state::attributes::Source::WorktreeThenIdMapping
222+
)?;
223+
216224
let cb =
217225
|change_ref: gix::diff::index::ChangeRef<'_, '_>,
218226
_: &gix::index::State,
@@ -229,7 +237,7 @@ pub fn get_status(
229237
repo.tree_index_status(
230238
&tree_id,
231239
&worktree_index,
232-
None,
240+
Some(&mut pathspec),
233241
gix::status::tree_index::TrackRenames::default(),
234242
cb,
235243
)?;

asyncgit/src/sync/utils.rs

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -230,6 +230,7 @@ mod tests {
230230
},
231231
};
232232
use std::{
233+
env,
233234
fs::{self, remove_file, File},
234235
io::Write,
235236
path::Path,
@@ -270,6 +271,44 @@ mod tests {
270271
assert_eq!(get_statuses(repo_path), (1, 1));
271272
}
272273

274+
#[test]
275+
fn test_staging_one_file_from_different_sub_directory() {
276+
// This test case covers an interaction between current working directory and the way
277+
// `gitoxide` handles pathspecs.
278+
//
279+
// When staging a new file in one sub-directory, then running running `get_status` in a
280+
// different sub-directory, `repo.pathspec` in `get_status` has to initialized with
281+
// `empty_patterns_match_prefix` set to `false` for `get_status` to report the staged file’s
282+
// status.
283+
let file_path = Path::new("untracked/file1.txt");
284+
let (_td, repo) = repo_init().unwrap();
285+
let root = repo.path().parent().unwrap();
286+
let repo_path: &RepoPath =
287+
&root.as_os_str().to_str().unwrap().into();
288+
289+
fs::create_dir(root.join("untracked")).unwrap();
290+
291+
File::create(root.join(file_path))
292+
.unwrap()
293+
.write_all(b"test file1 content")
294+
.unwrap();
295+
296+
let sub_dir_path = root.join("unrelated");
297+
298+
fs::create_dir(root.join("unrelated")).unwrap();
299+
300+
let current_dir = env::current_dir().unwrap();
301+
env::set_current_dir(sub_dir_path).unwrap();
302+
303+
assert_eq!(get_statuses(repo_path), (1, 0));
304+
305+
stage_add_file(repo_path, file_path).unwrap();
306+
307+
assert_eq!(get_statuses(repo_path), (0, 1));
308+
309+
env::set_current_dir(current_dir).unwrap();
310+
}
311+
273312
#[test]
274313
fn test_staging_folder() -> Result<()> {
275314
let (_td, repo) = repo_init().unwrap();

0 commit comments

Comments
 (0)