+184
-27
lines changedFilter options
+184
-27
lines changed Original file line number Diff line number Diff line change
@@ -49,6 +49,7 @@ impl Mode {
49
49
) -> Option<Change> {
50
50
match self {
51
51
Mode::FILE if !stat.is_file() => (),
52
+
Mode::SYMLINK if stat.is_symlink() => return None,
52
53
Mode::SYMLINK if has_symlinks && !stat.is_symlink() => (),
53
54
Mode::SYMLINK if !has_symlinks && !stat.is_file() => (),
54
55
Mode::COMMIT | Mode::DIR if !stat.is_dir() => (),
Original file line number Diff line number Diff line change
@@ -53,7 +53,7 @@ mod access {
53
53
}
54
54
}
55
55
56
-
use crate::file;
56
+
use crate::{file, Target};
57
57
58
58
/// Access
59
59
impl file::Store {
@@ -78,6 +78,35 @@ mod access {
78
78
pub fn common_dir_resolved(&self) -> &Path {
79
79
self.common_dir.as_deref().unwrap_or(&self.git_dir)
80
80
}
81
+
82
+
/// Return `Some(true)` if this is a freshly initialized ref store without any observable changes.
83
+
/// Return `None` if `HEAD` couldn't be read.
84
+
///
85
+
/// This is the case if:
86
+
///
87
+
/// * the ref-store is valid
88
+
/// * `HEAD` exists
89
+
/// * `HEAD` still points to `default_ref`
90
+
/// * there are no packed refs
91
+
/// * There are no observable references in `refs/`
92
+
pub fn is_pristine(&self, default_ref: &crate::FullNameRef) -> Option<bool> {
93
+
let head = self.find_loose("HEAD").ok()?;
94
+
match head.target {
95
+
Target::Object(_) => return Some(false),
96
+
Target::Symbolic(name) => {
97
+
if name.as_ref() != default_ref {
98
+
return Some(false);
99
+
}
100
+
}
101
+
}
102
+
if self.loose_iter().ok()?.filter_map(Result::ok).next().is_some() {
103
+
return Some(false);
104
+
}
105
+
if self.packed_refs_path().is_file() {
106
+
return Some(false);
107
+
}
108
+
Some(true)
109
+
}
81
110
}
82
111
}
83
112
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
1
+
#!/usr/bin/env bash
2
+
set -eu -o pipefail
3
+
4
+
git init untouched
5
+
6
+
git init changed-headref
7
+
(cd changed-headref
8
+
echo "ref: refs/heads/other" >.git/HEAD
9
+
)
10
+
11
+
git init detached
12
+
(cd detached
13
+
echo "abcdefabcdefabcdefabcdefabcdefabcdefabcd" >.git/HEAD
14
+
)
15
+
16
+
git init invalid-loose-ref
17
+
(cd invalid-loose-ref
18
+
touch .git/refs/heads/empty
19
+
)
Original file line number Diff line number Diff line change
@@ -14,8 +14,12 @@ pub fn store_with_packed_refs() -> crate::Result<Store> {
14
14
}
15
15
16
16
pub fn store_at(name: &str) -> crate::Result<Store> {
17
-
let path = gix_testtools::scripted_fixture_read_only_standalone(name)?;
18
-
Ok(Store::at(path.join(".git"), Default::default()))
17
+
named_store_at(name, "")
18
+
}
19
+
20
+
pub fn named_store_at(script_name: &str, name: &str) -> crate::Result<Store> {
21
+
let path = gix_testtools::scripted_fixture_read_only_standalone(script_name)?;
22
+
Ok(Store::at(path.join(name).join(".git"), Default::default()))
19
23
}
20
24
21
25
pub fn store_at_with_args(name: &str, args: impl IntoIterator<Item = impl Into<String>>) -> crate::Result<Store> {
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
1
-
use crate::file::store;
1
+
use crate::file::{named_store_at, store};
2
2
3
3
#[test]
4
4
fn set_packed_buffer_mmap_threshold() -> crate::Result {
@@ -20,3 +20,22 @@ fn set_packed_buffer_mmap_threshold() -> crate::Result {
20
20
);
21
21
Ok(())
22
22
}
23
+
24
+
#[test]
25
+
fn is_pristine() -> crate::Result {
26
+
let store = named_store_at("make_pristine.sh", "untouched")?;
27
+
assert_eq!(store.is_pristine("refs/heads/main".try_into()?), Some(true));
28
+
assert_eq!(store.is_pristine("refs/heads/other".try_into()?), Some(false));
29
+
30
+
let store = named_store_at("make_pristine.sh", "changed-headref")?;
31
+
assert_eq!(store.is_pristine("refs/heads/other".try_into()?), Some(true));
32
+
assert_eq!(store.is_pristine("refs/heads/main".try_into()?), Some(false));
33
+
34
+
let store = named_store_at("make_pristine.sh", "detached")?;
35
+
assert_eq!(store.is_pristine("refs/heads/main".try_into()?), Some(false));
36
+
37
+
let store = named_store_at("make_pristine.sh", "invalid-loose-ref")?;
38
+
assert_eq!(store.is_pristine("refs/heads/main".try_into()?), Some(true));
39
+
40
+
Ok(())
41
+
}
Original file line number Diff line number Diff line change
@@ -9,6 +9,7 @@ mod existing {
9
9
"make_packed_ref_repository_for_overlay.sh",
10
10
] {
11
11
let store = store_at(fixture)?;
12
+
assert_eq!(store.is_pristine("refs/heads/main".try_into()?), Some(false));
12
13
let c1 = hex_to_id("134385f6d781b7e97062102c6a483440bfda2a03");
13
14
let r = store.find("main")?;
14
15
assert_eq!(r.target.into_id(), c1);
Original file line number Diff line number Diff line change
@@ -576,6 +576,7 @@ fn overlay_partial_prefix_iter_when_prefix_is_dir() -> crate::Result {
576
576
use gix_ref::Target::*;
577
577
578
578
let store = store_at("make_packed_ref_repository_for_overlay.sh")?;
579
+
assert_eq!(store.is_pristine("refs/heads/main".try_into()?), Some(false));
579
580
let c1 = hex_to_id("134385f6d781b7e97062102c6a483440bfda2a03");
580
581
581
582
let ref_names = store
Original file line number Diff line number Diff line change
@@ -84,6 +84,7 @@ mod read_only {
84
84
fn linked() -> crate::Result {
85
85
for packed in [false, true] {
86
86
let (store, odb, _tmp) = worktree_store(packed, "w1", Mode::Read)?;
87
+
assert_eq!(store.is_pristine("refs/heads/main".try_into()?), Some(false));
87
88
let peel = into_peel(&store, odb);
88
89
89
90
let w1_head_id = peel(store.find("HEAD").unwrap());
@@ -132,6 +133,7 @@ mod read_only {
132
133
fn main() -> crate::Result {
133
134
for packed in [false, true] {
134
135
let (store, odb, _tmp) = main_store(packed, Mode::Read)?;
136
+
assert_eq!(store.is_pristine("refs/heads/main".try_into()?), Some(false));
135
137
let peel = into_peel(&store, odb);
136
138
137
139
let head_id = peel(store.find("HEAD").unwrap());
Original file line number Diff line number Diff line change
@@ -408,12 +408,12 @@ impl<'index> State<'_, 'index> {
408
408
None => false,
409
409
};
410
410
411
-
// Here we implement racy-git. See racy-git.txt in the git documentation for a detailed documentation.
411
+
// We implement racy-git. See racy-git.txt in the git documentation for detailed documentation.
412
412
//
413
413
// A file is racy if:
414
-
// 1. its `mtime` is at or after the last index timestamp and its entry stat information
415
-
// matches the on-disk file but the file contents are actually modified
416
-
// 2. it's size is 0 (set after detecting a file was racy previously)
414
+
// 1. Its `mtime` is at or after the last index timestamp and its entry stat information
415
+
// matches the on-disk file, but the file contents are actually modified
416
+
// 2. Its size is 0 (set after detecting a file was racy previously)
417
417
//
418
418
// The first case is detected below by checking the timestamp if the file is marked unmodified.
419
419
// The second case is usually detected either because the on-disk file is not empty, hence
@@ -449,7 +449,16 @@ impl<'index> State<'_, 'index> {
449
449
file_len: file_size_bytes,
450
450
filter: &mut self.filter,
451
451
attr_stack: &mut self.attr_stack,
452
-
options: self.options,
452
+
core_symlinks:
453
+
// If this is legitimately a symlink, then pretend symlinks are enabled as the option seems stale.
454
+
// Otherwise, respect the option.
455
+
if metadata.is_symlink()
456
+
&& entry.mode.to_tree_entry_mode().map(|m| m.kind()) == Some(gix_object::tree::EntryKind::Link)
457
+
{
458
+
true
459
+
} else {
460
+
self.options.fs.symlink
461
+
},
453
462
id: &entry.id,
454
463
objects,
455
464
worktree_reads: self.worktree_reads,
@@ -517,7 +526,7 @@ where
517
526
entry: &'a gix_index::Entry,
518
527
filter: &'a mut gix_filter::Pipeline,
519
528
attr_stack: &'a mut gix_worktree::Stack,
520
-
options: &'a Options,
529
+
core_symlinks: bool,
521
530
id: &'a gix_hash::oid,
522
531
objects: Find,
523
532
worktree_bytes: &'a AtomicU64,
@@ -545,7 +554,7 @@ where
545
554
//
546
555
let is_symlink = self.entry.mode == gix_index::entry::Mode::SYMLINK;
547
556
// TODO: what to do about precompose unicode and ignore_case for symlinks
548
-
let out = if is_symlink && self.options.fs.symlink {
557
+
let out = if is_symlink && self.core_symlinks {
549
558
// conversion to bstr can never fail because symlinks are only used
550
559
// on unix (by git) so no reason to use the try version here
551
560
let symlink_path =
You can’t perform that action at this time.
RetroSearch is an open source project built by @garambo | Open a GitHub Issue
Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo
HTML:
3.2
| Encoding:
UTF-8
| Version:
0.7.4