Skip to content

Commit f07a05d

Browse files
committed
feat: add attributes feature to allow ignore-only stacks.
1 parent 58b0e6f commit f07a05d

File tree

6 files changed

+39
-10
lines changed

6 files changed

+39
-10
lines changed

gix-worktree/Cargo.toml

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,11 @@ autotests = false
1414
doctest = false
1515

1616
[features]
17+
default = ["attributes"]
18+
## Instantiate stacks that can access `.gitattributes` information.
19+
attributes = ["dep:gix-attributes"]
1720
## Data structures implement `serde::Serialize` and `serde::Deserialize`.
18-
serde = [ "dep:serde", "bstr/serde", "gix-index/serde", "gix-hash/serde", "gix-object/serde", "gix-attributes/serde", "gix-ignore/serde" ]
21+
serde = [ "dep:serde", "bstr/serde", "gix-index/serde", "gix-hash/serde", "gix-object/serde", "gix-attributes?/serde", "gix-ignore/serde" ]
1922

2023
[dependencies]
2124
gix-index = { version = "^0.23.1", path = "../gix-index" }
@@ -24,7 +27,7 @@ gix-hash = { version = "^0.12.0", path = "../gix-hash" }
2427
gix-object = { version = "^0.35.0", path = "../gix-object" }
2528
gix-glob = { version = "^0.11.0", path = "../gix-glob" }
2629
gix-path = { version = "^0.9.0", path = "../gix-path" }
27-
gix-attributes = { version = "^0.17.0", path = "../gix-attributes" }
30+
gix-attributes = { version = "^0.17.0", path = "../gix-attributes", optional = true }
2831
gix-ignore = { version = "^0.6.0", path = "../gix-ignore" }
2932
gix-features = { version = "^0.33.0", path = "../gix-features" }
3033

gix-worktree/src/stack/delegate.rs

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ pub(crate) type FindFn<'a> = dyn for<'b> FnMut(
2727
pub(crate) struct StackDelegate<'a, 'find> {
2828
pub state: &'a mut State,
2929
pub buf: &'a mut Vec<u8>,
30+
#[cfg_attr(not(feature = "attributes"), allow(dead_code))]
3031
pub is_dir: bool,
3132
pub id_mappings: &'a Vec<PathIdMapping>,
3233
pub find: &'find mut FindFn<'find>,
@@ -54,6 +55,7 @@ impl<'a, 'find> gix_fs::stack::Delegate for StackDelegate<'a, 'find> {
5455
rela_dir_cow.as_ref()
5556
};
5657
match &mut self.state {
58+
#[cfg(feature = "attributes")]
5759
State::CreateDirectoryAndAttributesStack { attributes, .. } => {
5860
attributes.push_directory(
5961
stack.root(),
@@ -65,6 +67,7 @@ impl<'a, 'find> gix_fs::stack::Delegate for StackDelegate<'a, 'find> {
6567
&mut self.statistics.attributes,
6668
)?;
6769
}
70+
#[cfg(feature = "attributes")]
6871
State::AttributesAndIgnoreStack { ignore, attributes } => {
6972
attributes.push_directory(
7073
stack.root(),
@@ -86,6 +89,7 @@ impl<'a, 'find> gix_fs::stack::Delegate for StackDelegate<'a, 'find> {
8689
&mut self.statistics.ignore,
8790
)?
8891
}
92+
#[cfg(feature = "attributes")]
8993
State::AttributesStack(attributes) => attributes.push_directory(
9094
stack.root(),
9195
stack.current(),
@@ -109,9 +113,11 @@ impl<'a, 'find> gix_fs::stack::Delegate for StackDelegate<'a, 'find> {
109113
Ok(())
110114
}
111115

116+
#[cfg_attr(not(feature = "attributes"), allow(unused_variables))]
112117
fn push(&mut self, is_last_component: bool, stack: &gix_fs::Stack) -> std::io::Result<()> {
113118
self.statistics.delegate.push_element += 1;
114119
match &mut self.state {
120+
#[cfg(feature = "attributes")]
115121
State::CreateDirectoryAndAttributesStack {
116122
unlink_on_collision,
117123
attributes: _,
@@ -122,31 +128,37 @@ impl<'a, 'find> gix_fs::stack::Delegate for StackDelegate<'a, 'find> {
122128
&mut self.statistics.delegate.num_mkdir_calls,
123129
*unlink_on_collision,
124130
)?,
125-
State::AttributesAndIgnoreStack { .. } | State::IgnoreStack(_) | State::AttributesStack(_) => {}
131+
#[cfg(feature = "attributes")]
132+
State::AttributesAndIgnoreStack { .. } | State::AttributesStack(_) => {}
133+
State::IgnoreStack(_) => {}
126134
}
127135
Ok(())
128136
}
129137

130138
fn pop_directory(&mut self) {
131139
self.statistics.delegate.pop_directory += 1;
132140
match &mut self.state {
141+
#[cfg(feature = "attributes")]
133142
State::CreateDirectoryAndAttributesStack { attributes, .. } => {
134143
attributes.pop_directory();
135144
}
145+
#[cfg(feature = "attributes")]
136146
State::AttributesAndIgnoreStack { attributes, ignore } => {
137147
attributes.pop_directory();
138148
ignore.pop_directory();
139149
}
140-
State::IgnoreStack(ignore) => {
141-
ignore.pop_directory();
142-
}
150+
#[cfg(feature = "attributes")]
143151
State::AttributesStack(attributes) => {
144152
attributes.pop_directory();
145153
}
154+
State::IgnoreStack(ignore) => {
155+
ignore.pop_directory();
156+
}
146157
}
147158
}
148159
}
149160

161+
#[cfg(feature = "attributes")]
150162
fn create_leading_directory(
151163
is_last_component: bool,
152164
stack: &gix_fs::Stack,

gix-worktree/src/stack/mod.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ pub struct Statistics {
1616
/// Information about the stack delegate.
1717
pub delegate: delegate::Statistics,
1818
/// Information about attributes
19+
#[cfg(feature = "attributes")]
1920
pub attributes: state::attributes::Statistics,
2021
/// Information about the ignore stack
2122
pub ignore: state::ignore::Statistics,
@@ -24,20 +25,23 @@ pub struct Statistics {
2425
#[derive(Clone)]
2526
pub enum State {
2627
/// Useful for checkout where directories need creation, but we need to access attributes as well.
28+
#[cfg(feature = "attributes")]
2729
CreateDirectoryAndAttributesStack {
2830
/// If there is a symlink or a file in our path, try to unlink it before creating the directory.
2931
unlink_on_collision: bool,
3032
/// State to handle attribute information
3133
attributes: state::Attributes,
3234
},
3335
/// Used when adding files, requiring access to both attributes and ignore information, for example during add operations.
36+
#[cfg(feature = "attributes")]
3437
AttributesAndIgnoreStack {
3538
/// State to handle attribute information
3639
attributes: state::Attributes,
3740
/// State to handle exclusion information
3841
ignore: state::Ignore,
3942
},
4043
/// Used when only attributes are required, typically with fully virtual worktrees.
44+
#[cfg(feature = "attributes")]
4145
AttributesStack(state::Attributes),
4246
/// Used when providing worktree status information.
4347
IgnoreStack(state::Ignore),

gix-worktree/src/stack/platform.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ impl<'a> Platform<'a> {
4040
/// # Panics
4141
///
4242
/// If the cache was configured without attributes.
43+
#[cfg(feature = "attributes")]
4344
pub fn matching_attributes(&self, out: &mut gix_attributes::search::Outcome) -> bool {
4445
let attrs = self.parent.state.attributes_or_panic();
4546
let relative_path =

gix-worktree/src/stack/state/mod.rs

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,15 @@
1-
use std::path::PathBuf;
2-
31
use bstr::{BString, ByteSlice};
42
use gix_glob::pattern::Case;
53

64
use crate::{stack::State, PathIdMapping};
75

6+
#[cfg(feature = "attributes")]
87
type AttributeMatchGroup = gix_attributes::Search;
98
type IgnoreMatchGroup = gix_ignore::Search;
109

1110
/// State related to attributes associated with files in the repository.
1211
#[derive(Default, Clone)]
12+
#[cfg(feature = "attributes")]
1313
pub struct Attributes {
1414
/// Attribute patterns which aren't tied to the repository root, hence are global, they contribute first.
1515
globals: AttributeMatchGroup,
@@ -20,7 +20,7 @@ pub struct Attributes {
2020
stack: AttributeMatchGroup,
2121
/// The first time we push the root, we have to load additional information from this file if it exists along with the root attributes
2222
/// file if possible, and keep them there throughout.
23-
info_attributes: Option<PathBuf>,
23+
info_attributes: Option<std::path::PathBuf>,
2424
/// A lookup table to accelerate searches.
2525
collection: gix_attributes::search::MetadataCollection,
2626
/// Where to read `.gitattributes` data from.
@@ -50,13 +50,15 @@ pub struct Ignore {
5050
}
5151

5252
///
53+
#[cfg(feature = "attributes")]
5354
pub mod attributes;
5455
///
5556
pub mod ignore;
5657

5758
/// Initialization
5859
impl State {
5960
/// Configure a state to be suitable for checking out files, which only needs access to attribute files read from the index.
61+
#[cfg(feature = "attributes")]
6062
pub fn for_checkout(unlink_on_collision: bool, attributes: Attributes) -> Self {
6163
State::CreateDirectoryAndAttributesStack {
6264
unlink_on_collision,
@@ -65,6 +67,7 @@ impl State {
6567
}
6668

6769
/// Configure a state for adding files, with support for ignore files and attribute files.
70+
#[cfg(feature = "attributes")]
6871
pub fn for_add(attributes: Attributes, ignore: Ignore) -> Self {
6972
State::AttributesAndIgnoreStack { attributes, ignore }
7073
}
@@ -96,6 +99,7 @@ impl State {
9699
case: Case,
97100
) -> Vec<PathIdMapping> {
98101
let a1_backing;
102+
#[cfg(feature = "attributes")]
99103
let a2_backing;
100104
let names = match self {
101105
State::IgnoreStack(ignore) => {
@@ -105,6 +109,7 @@ impl State {
105109
)];
106110
a1_backing.as_ref()
107111
}
112+
#[cfg(feature = "attributes")]
108113
State::AttributesAndIgnoreStack { ignore, .. } => {
109114
a2_backing = [
110115
(
@@ -115,6 +120,7 @@ impl State {
115120
];
116121
a2_backing.as_ref()
117122
}
123+
#[cfg(feature = "attributes")]
118124
State::CreateDirectoryAndAttributesStack { .. } | State::AttributesStack(_) => {
119125
a1_backing = [(".gitattributes".into(), None)];
120126
a1_backing.as_ref()
@@ -160,13 +166,16 @@ impl State {
160166
pub(crate) fn ignore_or_panic(&self) -> &Ignore {
161167
match self {
162168
State::IgnoreStack(v) => v,
169+
#[cfg(feature = "attributes")]
163170
State::AttributesAndIgnoreStack { ignore, .. } => ignore,
171+
#[cfg(feature = "attributes")]
164172
State::AttributesStack(_) | State::CreateDirectoryAndAttributesStack { .. } => {
165173
unreachable!("BUG: must not try to check excludes without it being setup")
166174
}
167175
}
168176
}
169177

178+
#[cfg(feature = "attributes")]
170179
pub(crate) fn attributes_or_panic(&self) -> &Attributes {
171180
match self {
172181
State::AttributesStack(attributes)

gix-worktree/tests/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ path = "integrate.rs"
1717
gix-features-parallel = ["gix-features/parallel"]
1818

1919
[dev-dependencies]
20-
gix-worktree = { path = ".." }
20+
gix-worktree = { path = "..", features = ["attributes"] }
2121
gix-index = { path = "../../gix-index" }
2222
gix-fs = { path = "../../gix-fs" }
2323
gix-hash = { path = "../../gix-hash" }

0 commit comments

Comments
 (0)