History

Merge branch 'worktree-organization'

Sebastian Thiel committed 3 years ago

Commit 8d0d8e02 parents ef54aab e5717e193 files · +424 −252Browse files

Unified · Split

93 files
  1. Cargo.lock +38 −4
  2. Cargo.toml +2 −0
  3. README.md +2 −0
  4. crate-status.md +28 −20
  5. etc/gix-components.monopic +0 −0
  6. etc/gix-components.txt +3 −0
  7. gitoxide-core/src/hours/core.rs +2 −2
  8. gitoxide-core/src/index/checkout.rs +4 −4
  9. gitoxide-core/src/repository/attributes/query.rs +4 −4
  10. gitoxide-core/src/repository/clone.rs +1 −1
  11. gitoxide-core/src/repository/index/entries.rs +7 −7
  12. gix-archive/tests/archive.rs +5 −5
  13. gix-diff/Cargo.toml +11 −1
  14. gix-diff/src/lib.rs +7 −0
  15. gix-filter/tests/pipeline/mod.rs +8 −8
  16. gix-status/CHANGELOG.md +0 −0
  17. gix-status/Cargo.toml +37 −0
  18. gix-status/LICENSE-APACHE +1 −0
  19. gix-status/LICENSE-MIT +1 −0
  20. gix-status/src/index_as_worktree/content.rs +0 −0
  21. gix-status/src/index_as_worktree/function.rs +3 −3
  22. gix-status/src/index_as_worktree/mod.rs +0 −0
  23. gix-status/src/index_as_worktree/recorder.rs +1 −1
  24. gix-status/src/index_as_worktree/types.rs +2 −2
  25. gix-status/src/lib.rs +15 −0
  26. gix-status/src/read.rs +1 −2
  27. gix-status/tests/fixtures/generated-archives/.gitignore +2 −0
  28. gix-status/tests/fixtures/generated-archives/racy_git.tar.xz +3 −0
  29. gix-status/tests/fixtures/generated-archives/status_conflict.tar.xz +3 −0
  30. gix-status/tests/fixtures/generated-archives/status_intent_to_add.tar.xz +3 −0
  31. gix-status/tests/fixtures/generated-archives/status_removed.tar.xz +3 −0
  32. gix-status/tests/fixtures/racy_git.sh +0 −0
  33. gix-status/tests/fixtures/status_changed.sh +0 −0
  34. gix-status/tests/fixtures/status_conflict.sh +0 −0
  35. gix-status/tests/fixtures/status_intent_to_add.sh +0 −0
  36. gix-status/tests/fixtures/status_removed.sh +0 −0
  37. gix-status/tests/fixtures/status_unchanged.sh +0 −0
  38. gix-status/tests/status-multi-threaded.rs +4 −0
  39. gix-status/tests/status-single-threaded.rs +4 −0
  40. gix-status/tests/status/index_as_worktree.rs +6 −6
  41. gix-status/tests/status/mod.rs +7 −0
  42. gix-worktree-state/Cargo.toml +44 −0
  43. gix-worktree-state/LICENSE-APACHE +1 −0
  44. gix-worktree-state/LICENSE-MIT +1 −0
  45. gix-worktree-state/src/checkout/chunk.rs +3 −2
  46. gix-worktree-state/src/checkout/entry.rs +2 −2
  47. gix-worktree-state/src/checkout/function.rs +4 −3
  48. gix-worktree-state/src/checkout/mod.rs +1 −1
  49. gix-worktree-state/src/lib.rs +6 −0
  50. gix-worktree-state/tests/fixtures/generated-archives/.gitignore +5 −0
  51. gix-worktree-state/tests/fixtures/generated-archives/make_ignorecase_collisions.tar.xz +0 −0
  52. gix-worktree-state/tests/fixtures/make_dangerous_symlink.sh +0 −0
  53. gix-worktree-state/tests/fixtures/make_ignorecase_collisions.sh +0 −0
  54. gix-worktree-state/tests/fixtures/make_mixed_without_submodules.sh +0 −0
  55. gix-worktree-state/tests/fixtures/make_mixed_without_submodules_and_symlinks.sh +0 −0
  56. gix-worktree-state/tests/state-multi-threaded.rs +4 −0
  57. gix-worktree-state/tests/state-single-threaded.rs +4 −0
  58. gix-worktree-state/tests/state/checkout.rs +10 −10
  59. gix-worktree-state/tests/state/mod.rs +10 −0
  60. gix-worktree-stream/tests/stream.rs +5 −5
  61. gix-worktree/Cargo.toml +1 −9
  62. gix-worktree/src/lib.rs +5 −14
  63. gix-worktree/src/stack/delegate.rs +1 −1
  64. gix-worktree/src/stack/mod.rs +10 −10
  65. gix-worktree/src/stack/platform.rs +1 −1
  66. gix-worktree/src/stack/state/attributes.rs +5 −5
  67. gix-worktree/src/stack/state/ignore.rs +2 −2
  68. gix-worktree/src/stack/state/mod.rs +1 −1
  69. gix-worktree/src/untracked.rs +0 −1
  70. gix-worktree/tests/fixtures/generated-archives/.gitignore +0 −5
  71. gix-worktree/tests/fixtures/generated-archives/make_special_exclude_case.tar.xz +2 −2
  72. gix-worktree/tests/fixtures/generated-archives/racy_git.tar.xz +0 −3
  73. gix-worktree/tests/fixtures/generated-archives/status_conflict.tar.xz +0 −3
  74. gix-worktree/tests/fixtures/generated-archives/status_intent_to_add.tar.xz +0 −3
  75. gix-worktree/tests/fixtures/generated-archives/status_removed.tar.xz +0 −3
  76. gix-worktree/tests/fixtures/make_ignore_setup.sh +0 −18
  77. gix-worktree/tests/worktree/mod.rs +2 −10
  78. gix-worktree/tests/worktree/stack/attributes.rs +4 −4
  79. gix-worktree/tests/worktree/stack/create_directory.rs +9 −9
  80. gix-worktree/tests/worktree/stack/ignore.rs +7 −7
  81. gix-worktree/tests/worktree/stack/mod.rs +0 −0
  82. gix/Cargo.toml +1 −0
  83. gix/src/clone/checkout.rs +6 −5
  84. gix/src/config/cache/access.rs +9 −9
  85. gix/src/filter.rs +3 −3
  86. gix/src/pathspec.rs +4 −4
  87. gix/src/repository/attributes.rs +13 −13
  88. gix/src/repository/filter.rs +2 −2
  89. gix/src/repository/pathspec.rs +1 −1
  90. gix/src/repository/worktree.rs +1 −1
  91. gix/src/types.rs +1 −1
  92. gix/src/worktree/mod.rs +8 −7
  93. justfile +8 −3
Cargo.lock+38−4
@@ -1240,6 +1240,7 @@ dependencies = [ · 1239 unmodified lines
1240 "gix-utils 0.1.5",1240 "gix-utils 0.1.5",
1241 "gix-validate 0.8.0",1241 "gix-validate 0.8.0",
1242 "gix-worktree 0.24.0",1242 "gix-worktree 0.24.0",
1243 "gix-worktree-state",
1243 "gix-worktree-stream",1244 "gix-worktree-stream",
1244 "is_ci",1245 "is_ci",
1245 "log",1246 "log",
@@ -1497,6 +1498,7 @@ dependencies = [ · 251 unmodified lines
1497name = "gix-diff"1498name = "gix-diff"
1498version = "0.34.0"1499version = "0.34.0"
1499dependencies = [1500dependencies = [
1501 "document-features",
1500 "getrandom",1502 "getrandom",
1501 "gix-hash 0.11.4",1503 "gix-hash 0.11.4",
1502 "gix-object 0.34.0",1504 "gix-object 0.34.0",
@@ -2215,6 +2217,22 @@ dependencies = [ · 712 unmodified lines
2215name = "gix-sequencer"2217name = "gix-sequencer"
2216version = "0.0.0"2218version = "0.0.0"
2217 2219
2220[[package]]
2221name = "gix-status"
2222version = "0.1.0"
2223dependencies = [
2224 "bstr",
2225 "filetime",
2226 "gix-features 0.32.1",
2227 "gix-fs 0.4.1",
2228 "gix-hash 0.11.4",
2229 "gix-index 0.22.0",
2230 "gix-object 0.34.0",
2231 "gix-path 0.8.4",
2232 "gix-testtools",
2233 "thiserror",
2234]
2235
2218[[package]]2236[[package]]
2219name = "gix-submodule"2237name = "gix-submodule"
2220version = "0.1.0"2238version = "0.1.0"
@@ -2449,10 +2467,8 @@ version = "0.24.0" · 228 unmodified lines
2449dependencies = [2467dependencies = [
2450 "bstr",2468 "bstr",
2451 "document-features",2469 "document-features",
2452 "filetime",
2453 "gix-attributes 0.16.0",2470 "gix-attributes 0.16.0",
2454 "gix-features 0.32.1",2471 "gix-features 0.32.1",
2455 "gix-filter",
2456 "gix-fs 0.4.1",2472 "gix-fs 0.4.1",
2457 "gix-glob 0.10.2",2473 "gix-glob 0.10.2",
2458 "gix-hash 0.11.4",2474 "gix-hash 0.11.4",
@@ -2462,11 +2478,29 @@ dependencies = [ · 3 unmodified lines
2462 "gix-odb",2478 "gix-odb",
2463 "gix-path 0.8.4",2479 "gix-path 0.8.4",
2464 "gix-testtools",2480 "gix-testtools",
2481 "serde",
2482 "symlink",
2483]
2484
2485[[package]]
2486name = "gix-worktree-state"
2487version = "0.1.0"
2488dependencies = [
2489 "bstr",
2490 "gix-features 0.32.1",
2491 "gix-filter",
2492 "gix-fs 0.4.1",
2493 "gix-glob 0.10.2",
2494 "gix-hash 0.11.4",
2495 "gix-index 0.22.0",
2496 "gix-object 0.34.0",
2497 "gix-odb",
2498 "gix-path 0.8.4",
2499 "gix-testtools",
2500 "gix-worktree 0.24.0",
2465 "io-close",2501 "io-close",
2466 "once_cell",2502 "once_cell",
2467 "serde",
2468 "symlink",2503 "symlink",
2469 "tempfile",
2470 "thiserror",2504 "thiserror",
2471 "walkdir",2505 "walkdir",
2472]2506]
Cargo.toml+2−0
@@ -235,6 +235,8 @@ members = [ · 234 unmodified lines
235 "gix-index",235 "gix-index",
236 "gix-bitmap",236 "gix-bitmap",
237 "gix-worktree",237 "gix-worktree",
238 "gix-worktree-state",
239 "gix-status",
238 "gix-revision",240 "gix-revision",
239 "gix-packetline",241 "gix-packetline",
240 "gix-packetline-blocking",242 "gix-packetline-blocking",
README.md+2−0
@@ -95,6 +95,8 @@ is usable to some extent. · 94 unmodified lines
95 * [gix-worktree-stream](https://github.com/Byron/gitoxide/blob/main/crate-status.md#gix-worktree-stream)95 * [gix-worktree-stream](https://github.com/Byron/gitoxide/blob/main/crate-status.md#gix-worktree-stream)
96 * [gix-archive](https://github.com/Byron/gitoxide/blob/main/crate-status.md#gix-archive)96 * [gix-archive](https://github.com/Byron/gitoxide/blob/main/crate-status.md#gix-archive)
97 * [gix-submodule](https://github.com/Byron/gitoxide/blob/main/crate-status.md#gix-submodule)97 * [gix-submodule](https://github.com/Byron/gitoxide/blob/main/crate-status.md#gix-submodule)
98 * [gix-status](https://github.com/Byron/gitoxide/blob/main/crate-status.md#gix-status)
99 * [gix-worktree-state](https://github.com/Byron/gitoxide/blob/main/crate-status.md#gix-worktree-state)
98 * `gitoxide-core`100 * `gitoxide-core`
99* **very early** _(possibly without any documentation and many rough edges)_101* **very early** _(possibly without any documentation and many rough edges)_
100 * [gix-date](https://github.com/Byron/gitoxide/blob/main/crate-status.md#gix-date)102 * [gix-date](https://github.com/Byron/gitoxide/blob/main/crate-status.md#gix-date)
crate-status.md+28−20
@@ -453,28 +453,36 @@ Make it the best-performing implementation and the most convenient one. · 452 unmodified lines
453### gix-glob453### gix-glob
454* [x] parse pattern454* [x] parse pattern
455* [x] a type for pattern matching of paths and non-paths, optionally case-insensitively.455* [x] a type for pattern matching of paths and non-paths, optionally case-insensitively.
456 456
457### gix-worktree457### gix-status
458* [x] differences between index and worktree to turn index into worktree
459* [ ] differences between tree and index to turn tree into index
460* [ ] untracked files
461* [ ] fast answer to 'is it dirty'.
462*
463### gix-worktree-state
458* handle the working **tree/checkout**464* handle the working **tree/checkout**
459 - [x] checkout an index of files, executables and symlinks just as fast as git465 - [x] checkout an index of files, executables and symlinks just as fast as git
460 - [x] forbid symlinks in directories466 - [x] forbid symlinks in directories
461 - [ ] handle submodules467 - [ ] handle submodules
462 - [ ] handle sparse directories468 - [ ] handle sparse directories
463 - [ ] handle sparse index469 - [ ] handle sparse index
464 - [x] linear scaling with multi-threading up to IO saturation470 - [x] linear scaling with multi-threading up to IO saturation
465 - supported attributes to affect working tree and index contents471 - supported attributes to affect working tree and index contents
466 - [ ] eol472 - [x] eol
467 - [ ] working-tree-encoding473 - [x] working-tree-encoding
468 - …more474 - …more
469 - **filtering** 475 - **filtering**
470 - [ ] `text`476 - [x] `text`
471 - [ ] `ident`477 - [x] `ident`
472 - [ ] filter processes478 - [x] filter processes
473 - [ ] single-invocation clean/smudge filters479 - [x] single-invocation clean/smudge filters
474* manage multiple worktrees
475* access to per-path information, like `.gitignore` and `.gitattributes` in a manner well suited for efficient lookups480* access to per-path information, like `.gitignore` and `.gitattributes` in a manner well suited for efficient lookups
476 * [x] _exclude_ information481 * [x] _exclude_ information
477 * [ ] attributes482 * [x] attributes
483
484### gix-worktree
485* [x] A stack to to efficiently generate attribute lists for matching paths against.
478 486
479### gix-revision487### gix-revision
480* [x] `describe()` (similar to `git name-rev`)488* [x] `describe()` (similar to `git name-rev`)
etc/gix-components.monopic+0−0

Binary file not shown.

etc/gix-components.txt+3−0
@@ -0,0 +1,3 @@
1╔════════════════╗
2║ gix-submodule ║
3╚════════════════╝
gitoxide-core/src/hours/core.rs+2−2
@@ -101,8 +101,8 @@ pub fn spawn_tree_delta_threads<'scope>( · 100 unmodified lines
101 repo.index_or_load_from_head().map_err(Into::into).and_then(|index| {101 repo.index_or_load_from_head().map_err(Into::into).and_then(|index| {
102 repo.attributes(102 repo.attributes(
103 &index,103 &index,
104 gix::worktree::cache::state::attributes::Source::IdMapping,104 gix::worktree::stack::state::attributes::Source::IdMapping,
105 gix::worktree::cache::state::ignore::Source::IdMapping,105 gix::worktree::stack::state::ignore::Source::IdMapping,
106 None,106 None,
107 )107 )
108 .map_err(Into::into)108 .map_err(Into::into)
gitoxide-core/src/index/checkout.rs+4−4
@@ -4,7 +4,7 @@ use std::{ · 3 unmodified lines
4};4};
5 5
6use anyhow::bail;6use anyhow::bail;
7use gix::{odb::FindExt, worktree::checkout, Progress};7use gix::{odb::FindExt, worktree::state::checkout, Progress};
8 8
9use crate::{9use crate::{
10 index,10 index,
@@ -55,7 +55,7 @@ pub fn checkout_exclusive( · 44 unmodified lines
55 progress.info(format!("Skipping {num_skipped} DIR/SYMLINK/COMMIT entries"));55 progress.info(format!("Skipping {num_skipped} DIR/SYMLINK/COMMIT entries"));
56 }56 }
57 57
58 let opts = gix::worktree::checkout::Options {58 let opts = gix::worktree::state::checkout::Options {
59 fs: gix::fs::Capabilities::probe(dest_directory),59 fs: gix::fs::Capabilities::probe(dest_directory),
60 60
61 destination_is_initially_empty: true,61 destination_is_initially_empty: true,
@@ -86,7 +86,7 @@ pub fn checkout_exclusive( · 24 unmodified lines
86 delayed_paths_unknown,86 delayed_paths_unknown,
87 delayed_paths_unprocessed,87 delayed_paths_unprocessed,
88 } = match repo {88 } = match repo {
89 Some(repo) => gix::worktree::checkout(89 Some(repo) => gix::worktree::state::checkout(
90 &mut index,90 &mut index,
91 dest_directory,91 dest_directory,
92 {92 {
@@ -109,7 +109,7 @@ pub fn checkout_exclusive( · 16 unmodified lines
109 should_interrupt,109 should_interrupt,
110 opts,110 opts,
111 ),111 ),
112 None => gix::worktree::checkout(112 None => gix::worktree::state::checkout(
113 &mut index,113 &mut index,
114 dest_directory,114 dest_directory,
115 |_, buf| {115 |_, buf| {
gitoxide-core/src/repository/attributes/query.rs+4−4
@@ -89,16 +89,16 @@ pub(crate) mod function { · 88 unmodified lines
89 89
90pub(crate) fn attributes_cache(90pub(crate) fn attributes_cache(
91 repo: &gix::Repository,91 repo: &gix::Repository,
92) -> anyhow::Result<(gix::worktree::Cache, IndexPersistedOrInMemory)> {92) -> anyhow::Result<(gix::worktree::Stack, IndexPersistedOrInMemory)> {
93 let index = repo.index_or_load_from_head()?;93 let index = repo.index_or_load_from_head()?;
94 let cache = repo.attributes(94 let cache = repo.attributes(
95 &index,95 &index,
96 if repo.is_bare() {96 if repo.is_bare() {
97 gix::worktree::cache::state::attributes::Source::IdMapping97 gix::worktree::stack::state::attributes::Source::IdMapping
98 } else {98 } else {
99 gix::worktree::cache::state::attributes::Source::WorktreeThenIdMapping99 gix::worktree::stack::state::attributes::Source::WorktreeThenIdMapping
100 },100 },
101 gix::worktree::cache::state::ignore::Source::IdMapping,101 gix::worktree::stack::state::ignore::Source::IdMapping,
102 None,102 None,
103 )?;103 )?;
104 Ok((cache, index))104 Ok((cache, index))
gitoxide-core/src/repository/clone.rs+1−1
@@ -111,7 +111,7 @@ pub(crate) mod function { · 110 unmodified lines
111 }111 }
112 };112 };
113 113
114 if let Some(gix::worktree::checkout::Outcome { collisions, errors, .. }) = outcome {114 if let Some(gix::worktree::state::checkout::Outcome { collisions, errors, .. }) = outcome {
115 if !(collisions.is_empty() && errors.is_empty()) {115 if !(collisions.is_empty() && errors.is_empty()) {
116 let mut messages = Vec::new();116 let mut messages = Vec::new();
117 if !errors.is_empty() {117 if !errors.is_empty() {
gitoxide-core/src/repository/index/entries.rs+7−7
@@ -56,22 +56,22 @@ pub(crate) mod function { · 55 unmodified lines
56 match attrs {56 match attrs {
57 Attributes::WorktreeAndIndex => {57 Attributes::WorktreeAndIndex => {
58 if repo.is_bare() {58 if repo.is_bare() {
59 gix::worktree::cache::state::attributes::Source::IdMapping59 gix::worktree::stack::state::attributes::Source::IdMapping
60 } else {60 } else {
61 gix::worktree::cache::state::attributes::Source::WorktreeThenIdMapping61 gix::worktree::stack::state::attributes::Source::WorktreeThenIdMapping
62 }62 }
63 }63 }
64 Attributes::Index => gix::worktree::cache::state::attributes::Source::IdMapping,64 Attributes::Index => gix::worktree::stack::state::attributes::Source::IdMapping,
65 },65 },
66 match attrs {66 match attrs {
67 Attributes::WorktreeAndIndex => {67 Attributes::WorktreeAndIndex => {
68 if repo.is_bare() {68 if repo.is_bare() {
69 gix::worktree::cache::state::ignore::Source::IdMapping69 gix::worktree::stack::state::ignore::Source::IdMapping
70 } else {70 } else {
71 gix::worktree::cache::state::ignore::Source::WorktreeThenIdMappingIfNotSkipped71 gix::worktree::stack::state::ignore::Source::WorktreeThenIdMappingIfNotSkipped
72 }72 }
73 }73 }
74 Attributes::Index => gix::worktree::cache::state::ignore::Source::IdMapping,74 Attributes::Index => gix::worktree::stack::state::ignore::Source::IdMapping,
75 },75 },
76 None,76 None,
77 )77 )
@@ -203,7 +203,7 @@ pub(crate) mod function { · 125 unmodified lines
203 pub excluded: usize,203 pub excluded: usize,
204 pub with_attributes: usize,204 pub with_attributes: usize,
205 pub max_attributes_per_path: usize,205 pub max_attributes_per_path: usize,
206 pub cache: Option<gix::worktree::cache::Statistics>,206 pub cache: Option<gix::worktree::stack::Statistics>,
207 }207 }
208 208
209 #[cfg(feature = "serde")]209 #[cfg(feature = "serde")]
gix-archive/tests/archive.rs+5−5
@@ -11,7 +11,7 @@ mod from_tree { · 10 unmodified lines
11 use gix_object::tree::EntryMode;11 use gix_object::tree::EntryMode;
12 use gix_odb::FindExt;12 use gix_odb::FindExt;
13 use gix_testtools::bstr::ByteSlice;13 use gix_testtools::bstr::ByteSlice;
14 use gix_worktree::cache::state::attributes::Source;14 use gix_worktree::stack::state::attributes::Source;
15 15
16 use crate::hex_to_id;16 use crate::hex_to_id;
17 17
@@ -284,7 +284,7 @@ mod from_tree { · 266 unmodified lines
284 Ok(())284 Ok(())
285 }285 }
286 286
287 fn basic() -> gix_testtools::Result<(PathBuf, gix_hash::ObjectId, gix_odb::HandleArc, gix_worktree::Cache)> {287 fn basic() -> gix_testtools::Result<(PathBuf, gix_hash::ObjectId, gix_odb::HandleArc, gix_worktree::Stack)> {
288 let dir = gix_testtools::scripted_fixture_read_only("basic.sh")?;288 let dir = gix_testtools::scripted_fixture_read_only("basic.sh")?;
289 289
290 let head = {290 let head = {
@@ -295,14 +295,14 @@ mod from_tree { · 4 unmodified lines
295 295
296 let mut collection = Default::default();296 let mut collection = Default::default();
297 let mut buf = Default::default();297 let mut buf = Default::default();
298 let attributes = gix_worktree::cache::state::Attributes::new(298 let attributes = gix_worktree::stack::state::Attributes::new(
299 gix_attributes::Search::new_globals(None::<PathBuf>, &mut buf, &mut collection)?,299 gix_attributes::Search::new_globals(None::<PathBuf>, &mut buf, &mut collection)?,
300 None,300 None,
301 Source::WorktreeThenIdMapping,301 Source::WorktreeThenIdMapping,
302 collection,302 collection,
303 );303 );
304 let state = gix_worktree::cache::State::AttributesStack(attributes);304 let state = gix_worktree::stack::State::AttributesStack(attributes);
305 let cache = gix_worktree::Cache::new(&dir, state, Case::Sensitive, Default::default(), Default::default());305 let cache = gix_worktree::Stack::new(&dir, state, Case::Sensitive, Default::default(), Default::default());
306 Ok((dir, head, odb.into_arc()?, cache))306 Ok((dir, head, odb.into_arc()?, cache))
307 }307 }
308 308
gix-diff/Cargo.toml+11−1
@@ -11,6 +11,9 @@ rust-version = "1.65" · 10 unmodified lines
11autotests = false11autotests = false
12 12
13[features]13[features]
14default = ["blob"]
15## Enable diffing of blobs using imara-diff.
16blob = ["dep:imara-diff"]
14## Data structures implement `serde::Serialize` and `serde::Deserialize`.17## Data structures implement `serde::Serialize` and `serde::Deserialize`.
15serde = ["dep:serde", "gix-hash/serde", "gix-object/serde"]18serde = ["dep:serde", "gix-hash/serde", "gix-object/serde"]
16## Make it possible to compile to the `wasm32-unknown-unknown` target.19## Make it possible to compile to the `wasm32-unknown-unknown` target.
@@ -23,6 +26,13 @@ doctest = false · 6 unmodified lines
23gix-hash = { version = "^0.11.4", path = "../gix-hash" }26gix-hash = { version = "^0.11.4", path = "../gix-hash" }
24gix-object = { version = "^0.34.0", path = "../gix-object" }27gix-object = { version = "^0.34.0", path = "../gix-object" }
25thiserror = "1.0.32"28thiserror = "1.0.32"
26imara-diff = "0.1.3"29imara-diff = { version = "0.1.3", optional = true }
27serde = { version = "1.0.114", optional = true, default-features = false, features = ["derive"]}30serde = { version = "1.0.114", optional = true, default-features = false, features = ["derive"]}
28getrandom = { version = "0.2.8", optional = true, default-features = false, features = ["js"] }31getrandom = { version = "0.2.8", optional = true, default-features = false, features = ["js"] }
32
33document-features = { version = "0.2.0", optional = true }
34
35[package.metadata.docs.rs]
36all-features = true
37features = ["document-features"]
38rustdoc-args = ["--cfg", "docsrs"]
gix-diff/src/lib.rs+7−0
@@ -1,4 +1,10 @@
1//! Algorithms for diffing various git object types and for generating patches, highly optimized for performance.1//! Algorithms for diffing various git object types and for generating patches, highly optimized for performance.
2//! ## Feature Flags
3#![cfg_attr(
4feature = "document-features",
5cfg_attr(doc, doc = ::document_features::document_features!())
6)]
7#![cfg_attr(docsrs, feature(doc_cfg, doc_auto_cfg))]
2#![deny(missing_docs, rust_2018_idioms)]8#![deny(missing_docs, rust_2018_idioms)]
3#![forbid(unsafe_code)]9#![forbid(unsafe_code)]
4 10
@@ -6,4 +12,5 @@ · 1 unmodified line
6pub mod tree;12pub mod tree;
7 13
8///14///
15#[cfg(feature = "blob")]
9pub mod blob;16pub mod blob;
gix-filter/tests/pipeline/mod.rs+8−8
@@ -17,22 +17,22 @@ fn default() -> crate::Result { · 16 unmodified lines
17 Ok(())17 Ok(())
18}18}
19 19
20fn attribute_cache(name: &str) -> gix_testtools::Result<gix_worktree::Cache> {20fn attribute_cache(name: &str) -> gix_testtools::Result<gix_worktree::Stack> {
21 let dir = gix_testtools::scripted_fixture_read_only("pipeline_repos.sh")?.join(name);21 let dir = gix_testtools::scripted_fixture_read_only("pipeline_repos.sh")?.join(name);
22 Ok(gix_worktree::Cache::new(22 Ok(gix_worktree::Stack::new(
23 dir,23 dir,
24 gix_worktree::cache::State::for_add(24 gix_worktree::stack::State::for_add(
25 gix_worktree::cache::state::Attributes::new(25 gix_worktree::stack::state::Attributes::new(
26 Default::default(),26 Default::default(),
27 None,27 None,
28 gix_worktree::cache::state::attributes::Source::WorktreeThenIdMapping,28 gix_worktree::stack::state::attributes::Source::WorktreeThenIdMapping,
29 Default::default(),29 Default::default(),
30 ),30 ),
31 gix_worktree::cache::state::Ignore::new(31 gix_worktree::stack::state::Ignore::new(
32 Default::default(),32 Default::default(),
33 Default::default(),33 Default::default(),
34 None,34 None,
35 gix_worktree::cache::state::ignore::Source::WorktreeThenIdMappingIfNotSkipped,35 gix_worktree::stack::state::ignore::Source::WorktreeThenIdMappingIfNotSkipped,
36 ),36 ),
37 ),37 ),
38 Case::Sensitive,38 Case::Sensitive,
@@ -49,7 +49,7 @@ fn pipeline( · 10 unmodified lines
49 gix_filter::pipeline::CrlfRoundTripCheck,49 gix_filter::pipeline::CrlfRoundTripCheck,
50 eol::Configuration,50 eol::Configuration,
51 ),51 ),
52) -> gix_testtools::Result<(gix_worktree::Cache, gix_filter::Pipeline)> {52) -> gix_testtools::Result<(gix_worktree::Stack, gix_filter::Pipeline)> {
53 let cache = attribute_cache(name)?;53 let cache = attribute_cache(name)?;
54 let (drivers, encodings_with_roundtrip_check, crlf_roundtrip_check, eol_config) = init();54 let (drivers, encodings_with_roundtrip_check, crlf_roundtrip_check, eol_config) = init();
55 let pipe = gix_filter::Pipeline::new(55 let pipe = gix_filter::Pipeline::new(
gix-status/CHANGELOG.mdrenamed from gix-worktree/CHANGELOG.md+0−0

File renamed without changes.

gix-status/Cargo.toml+37−0
@@ -0,0 +1,37 @@
1[package]
2name = "gix-status"
3version = "0.1.0"
4repository = "https://github.com/Byron/gitoxide"
5license = "MIT OR Apache-2.0"
6description = "A crate of the gitoxide project dealing with 'git status'-like functionality"
7authors = ["Sebastian Thiel <sebastian.thiel@icloud.com>", "Pascal Kuthe <pascal.kuthe@semimod.de>"]
8edition = "2021"
9include = ["src/**/*", "LICENSE-*", "CHANGELOG.md"]
10rust-version = "1.65"
11
12[lib]
13doctest = false
14
15[[test]]
16name = "multi-threaded"
17path = "tests/status-multi-threaded.rs"
18required-features = ["internal-testing-gix-features-parallel"]
19
20[features]
21internal-testing-gix-features-parallel = ["gix-features/parallel"]
22
23[dependencies]
24gix-index = { version = "^0.22.0", path = "../gix-index" }
25gix-fs = { version = "^0.4.1", path = "../gix-fs" }
26gix-hash = { version = "^0.11.4", path = "../gix-hash" }
27gix-object = { version = "^0.34.0", path = "../gix-object" }
28gix-path = { version = "^0.8.4", path = "../gix-path" }
29gix-features = { version = "^0.32.1", path = "../gix-features" }
30
31thiserror = "1.0.26"
32filetime = "0.2.15"
33bstr = { version = "1.3.0", default-features = false }
34
35[dev-dependencies]
36gix-testtools = { path = "../tests/tools" }
37
gix-status/LICENSE-APACHE+1−0
@@ -0,0 +1 @@
1../LICENSE-APACHE
gix-status/LICENSE-MIT+1−0
@@ -0,0 +1 @@
1../LICENSE-MIT
gix-status/src/index_as_worktree/content.rsrenamed from gix-worktree/src/status/content.rs+0−0

File renamed without changes.

gix-status/src/index_as_worktree/function.rsrenamed from gix-worktree/src/status/function.rs+3−3
@@ -5,13 +5,13 @@ use filetime::FileTime; · 4 unmodified lines
5use gix_features::parallel::{in_parallel_if, Reduce};5use gix_features::parallel::{in_parallel_if, Reduce};
6 6
7use crate::{7use crate::{
8 read,8 index_as_worktree::{
9 status::{
10 content,9 content,
11 content::CompareBlobs,10 content::CompareBlobs,
12 types::{Error, Options},11 types::{Error, Options},
13 Change, VisitEntry,12 Change, VisitEntry,
14 },13 },
14 read,
15};15};
16 16
17/// Calculates the changes that need to be applied to an `index` to match the state of the `worktree` and makes them17/// Calculates the changes that need to be applied to an `index` to match the state of the `worktree` and makes them
@@ -24,7 +24,7 @@ use crate::{ · 6 unmodified lines
24/// Note that this isn't technically quite what this function does as this also provides some additional information,24/// Note that this isn't technically quite what this function does as this also provides some additional information,
25/// like whether a file has conflicts, and files that were added with `git add` are shown as a special25/// like whether a file has conflicts, and files that were added with `git add` are shown as a special
26/// changes despite not technically requiring a change to the index since `git add` already added the file to the index.26/// changes despite not technically requiring a change to the index since `git add` already added the file to the index.
27pub fn status<'index, T, Find, E>(27pub fn index_as_worktree<'index, T, Find, E>(
28 index: &'index mut gix_index::State,28 index: &'index mut gix_index::State,
29 worktree: &Path,29 worktree: &Path,
30 collector: &mut impl VisitEntry<'index, ContentChange = T>,30 collector: &mut impl VisitEntry<'index, ContentChange = T>,
gix-status/src/index_as_worktree/mod.rsrenamed from gix-worktree/src/status/mod.rs+0−0

File renamed without changes.

gix-status/src/index_as_worktree/recorder.rsrenamed from gix-worktree/src/status/recorder.rs+1−1
@@ -1,7 +1,7 @@
1use bstr::BStr;1use bstr::BStr;
2use gix_index as index;2use gix_index as index;
3 3
4use crate::status::{Change, VisitEntry};4use crate::index_as_worktree::{Change, VisitEntry};
5 5
6/// Convenience implementation of [`VisitEntry`] that collects all non-trivial changes into a `Vec`.6/// Convenience implementation of [`VisitEntry`] that collects all non-trivial changes into a `Vec`.
7#[derive(Debug, Default)]7#[derive(Debug, Default)]
gix-status/src/index_as_worktree/types.rsrenamed from gix-worktree/src/status/types.rs+2−2
@@ -1,6 +1,6 @@
1use bstr::BStr;1use bstr::BStr;
2 2
3/// The error returned by [`status()`][crate::status()].3/// The error returned by [`status()`](crate::index_as_worktree()).
4#[derive(Debug, thiserror::Error)]4#[derive(Debug, thiserror::Error)]
5#[allow(missing_docs)]5#[allow(missing_docs)]
6pub enum Error {6pub enum Error {
@@ -40,7 +40,7 @@ pub enum Change<T = ()> { · 33 unmodified lines
40 /// Indicates that one of the stat changes was an executable bit change40 /// Indicates that one of the stat changes was an executable bit change
41 /// which is a significant change itself.41 /// which is a significant change itself.
42 executable_bit_changed: bool,42 executable_bit_changed: bool,
43 /// The output of the [`CompareBlobs`][crate::status::content::CompareBlobs] run on this entry.43 /// The output of the [`CompareBlobs`](crate::index_as_worktree::content::CompareBlobs) run on this entry.
44 /// If there is no content change and only the executable bit44 /// If there is no content change and only the executable bit
45 /// changed than this is `None`.45 /// changed than this is `None`.
46 content_change: Option<T>,46 content_change: Option<T>,
gix-status/src/lib.rs+15−0
@@ -0,0 +1,15 @@
1//! This crate includes the various diffs `git` can do between different representations
2//! of the repository state, like comparisons between…
3//!
4//! * index and working tree
5//! * index and tree
6//! * find untracked files
7//!
8//! While also being able to check check if the working tree is dirty, quickly.
9#![deny(missing_docs, rust_2018_idioms, unsafe_code)]
10
11///
12pub mod read;
13
14pub mod index_as_worktree;
15pub use index_as_worktree::function::index_as_worktree;
gix-status/src/read.rsrenamed from gix-worktree/src/read.rs+1−2
@@ -10,7 +10,6 @@ use std::{ · 9 unmodified lines
10};10};
11 11
12use gix_object::Blob;12use gix_object::Blob;
13use gix_path as path;
14 13
15// TODO: tests14// TODO: tests
16 15
@@ -49,7 +48,7 @@ pub fn data_to_buf_with_meta<'a>( · 32 unmodified lines
49 if is_symlink && capabilities.symlink {48 if is_symlink && capabilities.symlink {
50 // conversion to bstr can never fail because symlinks are only used49 // conversion to bstr can never fail because symlinks are only used
51 // on unix (by git) so no reason to use the try version here50 // on unix (by git) so no reason to use the try version here
52 let symlink_path = path::into_bstr(read_link(path)?);51 let symlink_path = gix_path::into_bstr(read_link(path)?);
53 buf.extend_from_slice(&symlink_path);52 buf.extend_from_slice(&symlink_path);
54 // TODO: there is no reason this should be a clone53 // TODO: there is no reason this should be a clone
55 // std isn't great about allowing users to avoid allocations but we could54 // std isn't great about allowing users to avoid allocations but we could
gix-status/tests/fixtures/generated-archives/.gitignore+2−0
@@ -0,0 +1,2 @@
1status_unchanged.tar.xz
2status_changed.tar.xz
gix-status/tests/fixtures/generated-archives/racy_git.tar.xz+3−0
@@ -0,0 +1,3 @@
1version https://git-lfs.github.com/spec/v1
2oid sha256:c78c306d8a19ce7f09a4cdf284e761d9c7766a3491bfb83751b9e6f6bc8fc1c9
3size 9812
gix-status/tests/fixtures/generated-archives/status_conflict.tar.xz+3−0
@@ -0,0 +1,3 @@
1version https://git-lfs.github.com/spec/v1
2oid sha256:b64431478ff4ee4613d2e1fe0766b4da8aeac8f4dee2b42726efb6d2e87bc830
3size 11012
gix-status/tests/fixtures/generated-archives/status_intent_to_add.tar.xz+3−0
@@ -0,0 +1,3 @@
1version https://git-lfs.github.com/spec/v1
2oid sha256:d8fa2e8085d464945eade89cfa9dadb89345c584b1d72a535d464859f02950a7
3size 9280
gix-status/tests/fixtures/generated-archives/status_removed.tar.xz+3−0
@@ -0,0 +1,3 @@
1version https://git-lfs.github.com/spec/v1
2oid sha256:cbc72bb3b08e421928d4402b49100a4ac144b4cdcc84ab70e6b721ec5ce4546c
3size 10568
gix-status/tests/fixtures/racy_git.shrenamed from gix-worktree/tests/fixtures/racy_git.sh+0−0

File renamed without changes.

gix-status/tests/fixtures/status_changed.shrenamed from gix-worktree/tests/fixtures/status_changed.sh+0−0

File renamed without changes.

gix-status/tests/fixtures/status_conflict.shrenamed from gix-worktree/tests/fixtures/status_conflict.sh+0−0

File renamed without changes.

gix-status/tests/fixtures/status_intent_to_add.shrenamed from gix-worktree/tests/fixtures/status_intent_to_add.sh+0−0

File renamed without changes.

gix-status/tests/fixtures/status_removed.shrenamed from gix-worktree/tests/fixtures/status_removed.sh+0−0

File renamed without changes.

gix-status/tests/fixtures/status_unchanged.shrenamed from gix-worktree/tests/fixtures/status_unchanged.sh+0−0

File renamed without changes.

gix-status/tests/status-multi-threaded.rs+4−0
@@ -0,0 +1,4 @@
1#[cfg(feature = "internal-testing-gix-features-parallel")]
2mod status;
3#[cfg(feature = "internal-testing-gix-features-parallel")]
4use status::*;
gix-status/tests/status-single-threaded.rs+4−0
@@ -0,0 +1,4 @@
1#[cfg(not(feature = "internal-testing-gix-features-parallel"))]
2mod status;
3#[cfg(not(feature = "internal-testing-gix-features-parallel"))]
4use status::*;
gix-status/tests/status/index_as_worktree.rsrenamed from gix-worktree/tests/worktree/status.rs+6−6
@@ -7,9 +7,9 @@ use bstr::BStr; · 6 unmodified lines
7use filetime::{set_file_mtime, FileTime};7use filetime::{set_file_mtime, FileTime};
8use gix_index as index;8use gix_index as index;
9use gix_index::Entry;9use gix_index::Entry;
10use gix_worktree::{10use gix_status::{
11 status,11 index_as_worktree,
12 status::{12 index_as_worktree::{
13 content::{CompareBlobs, FastEq, ReadDataOnce},13 content::{CompareBlobs, FastEq, ReadDataOnce},
14 Change, Options, Recorder,14 Change, Options, Recorder,
15 },15 },
@@ -33,7 +33,7 @@ fn fixture(name: &str, expected_status: &[(&BStr, Option<Change>, bool)]) { · 17 unmodified lines
33 let git_dir = worktree.join(".git");33 let git_dir = worktree.join(".git");
34 let mut index = gix_index::File::at(git_dir.join("index"), gix_hash::Kind::Sha1, Default::default()).unwrap();34 let mut index = gix_index::File::at(git_dir.join("index"), gix_hash::Kind::Sha1, Default::default()).unwrap();
35 let mut recorder = Recorder::default();35 let mut recorder = Recorder::default();
36 status(36 index_as_worktree(
37 &mut index,37 &mut index,
38 &worktree,38 &worktree,
39 &mut recorder,39 &mut recorder,
@@ -172,7 +172,7 @@ fn racy_git() { · 132 unmodified lines
172 172
173 let count = Arc::new(AtomicUsize::new(0));173 let count = Arc::new(AtomicUsize::new(0));
174 let counter = CountCalls(count.clone(), FastEq);174 let counter = CountCalls(count.clone(), FastEq);
175 status(175 index_as_worktree(
176 &mut index,176 &mut index,
177 worktree,177 worktree,
178 &mut recorder,178 &mut recorder,
@@ -193,7 +193,7 @@ fn racy_git() { · 14 unmodified lines
193 // and cause proper output.193 // and cause proper output.
194 index.set_timestamp(FileTime::from_unix_time(timestamp as i64, 0));194 index.set_timestamp(FileTime::from_unix_time(timestamp as i64, 0));
195 let mut recorder = Recorder::default();195 let mut recorder = Recorder::default();
196 status(196 index_as_worktree(
197 &mut index,197 &mut index,
198 worktree,198 worktree,
199 &mut recorder,199 &mut recorder,
gix-status/tests/status/mod.rs+7−0
@@ -0,0 +1,7 @@
1mod index_as_worktree;
2
3pub fn fixture_path(name: &str) -> std::path::PathBuf {
4 let dir = gix_testtools::scripted_fixture_read_only(std::path::Path::new(name).with_extension("sh"))
5 .expect("script works");
6 dir
7}
gix-worktree-state/Cargo.toml+44−0
@@ -0,0 +1,44 @@
1[package]
2name = "gix-worktree-state"
3version = "0.1.0"
4repository = "https://github.com/Byron/gitoxide"
5license = "MIT OR Apache-2.0"
6description = "A crate of the gitoxide project implementing setting the worktree to a particular state"
7authors = ["Sebastian Thiel <sebastian.thiel@icloud.com>"]
8edition = "2021"
9include = ["src/**/*", "LICENSE-*", "CHANGELOG.md"]
10rust-version = "1.65"
11
12[lib]
13doctest = false
14
15[[test]]
16name = "multi-threaded"
17path = "tests/state-multi-threaded.rs"
18required-features = ["internal-testing-gix-features-parallel"]
19
20[features]
21internal-testing-gix-features-parallel = ["gix-features/parallel"]
22
23[dependencies]
24gix-worktree = { version = "^0.24.0", path = "../gix-worktree" }
25gix-index = { version = "^0.22.0", path = "../gix-index" }
26gix-fs = { version = "^0.4.1", path = "../gix-fs" }
27gix-hash = { version = "^0.11.4", path = "../gix-hash" }
28gix-object = { version = "^0.34.0", path = "../gix-object" }
29gix-glob = { version = "^0.10.2", path = "../gix-glob" }
30gix-path = { version = "^0.8.4", path = "../gix-path" }
31gix-features = { version = "^0.32.1", path = "../gix-features" }
32gix-filter = { version = "^0.3.0", path = "../gix-filter" }
33
34io-close = "0.3.7"
35thiserror = "1.0.26"
36bstr = { version = "1.3.0", default-features = false }
37
38[dev-dependencies]
39gix-testtools = { path = "../tests/tools" }
40gix-odb = { path = "../gix-odb" }
41symlink = "0.1.0"
42once_cell = "1.18.0"
43
44walkdir = "2.3.2"
gix-worktree-state/LICENSE-APACHE+1−0
@@ -0,0 +1 @@
1../LICENSE-APACHE
gix-worktree-state/LICENSE-MIT+1−0
@@ -0,0 +1 @@
1../LICENSE-MIT
gix-worktree-state/src/checkout/chunk.rsrenamed from gix-worktree/src/checkout/chunk.rs+3−2
@@ -6,7 +6,8 @@ use std::{ · 5 unmodified lines
6use bstr::{BStr, BString};6use bstr::{BStr, BString};
7use gix_hash::oid;7use gix_hash::oid;
8 8
9use crate::{checkout, checkout::entry, Cache};9use crate::{checkout, checkout::entry};
10use gix_worktree::Stack;
10 11
11mod reduce {12mod reduce {
12 use std::marker::PhantomData;13 use std::marker::PhantomData;
@@ -91,7 +92,7 @@ pub struct Outcome<'a> { · 78 unmodified lines
91#[derive(Clone)]92#[derive(Clone)]
92pub struct Context<Find: Clone> {93pub struct Context<Find: Clone> {
93 pub find: Find,94 pub find: Find,
94 pub path_cache: Cache,95 pub path_cache: Stack,
95 pub filters: gix_filter::Pipeline,96 pub filters: gix_filter::Pipeline,
96 pub buf: Vec<u8>,97 pub buf: Vec<u8>,
97 pub options: Options,98 pub options: Options,
gix-worktree-state/src/checkout/entry.rsrenamed from gix-worktree/src/checkout/entry.rs+2−2
@@ -10,11 +10,11 @@ use gix_hash::oid; · 9 unmodified lines
10use gix_index::{entry::Stat, Entry};10use gix_index::{entry::Stat, Entry};
11use io_close::Close;11use io_close::Close;
12 12
13use crate::Cache;13use gix_worktree::Stack;
14 14
15pub struct Context<'a, Find> {15pub struct Context<'a, Find> {
16 pub find: &'a mut Find,16 pub find: &'a mut Find,
17 pub path_cache: &'a mut Cache,17 pub path_cache: &'a mut Stack,
18 pub filters: &'a mut gix_filter::Pipeline,18 pub filters: &'a mut gix_filter::Pipeline,
19 pub buf: &'a mut Vec<u8>,19 pub buf: &'a mut Vec<u8>,
20}20}
gix-worktree-state/src/checkout/function.rsrenamed from gix-worktree/src/checkout/function.rs+4−3
@@ -3,7 +3,8 @@ use std::sync::atomic::AtomicBool; · 2 unmodified lines
3use gix_features::{interrupt, parallel::in_parallel_with_finalize, progress::Progress};3use gix_features::{interrupt, parallel::in_parallel_with_finalize, progress::Progress};
4use gix_hash::oid;4use gix_hash::oid;
5 5
6use crate::{cache, checkout::chunk, Cache};6use crate::checkout::chunk;
7use gix_worktree::{stack, Stack};
7 8
8/// Checkout the entire `index` into `dir`, and resolve objects found in index entries with `find` to write their content to their9/// Checkout the entire `index` into `dir`, and resolve objects found in index entries with `find` to write their content to their
9/// respective path in `dir`.10/// respective path in `dir`.
@@ -65,12 +66,12 @@ where · 55 unmodified lines
65 None,66 None,
66 );67 );
67 68
68 let state = cache::State::for_checkout(options.overwrite_existing, std::mem::take(&mut options.attributes));69 let state = stack::State::for_checkout(options.overwrite_existing, std::mem::take(&mut options.attributes));
69 let attribute_files = state.id_mappings_from_index(index, paths, case);70 let attribute_files = state.id_mappings_from_index(index, paths, case);
70 let mut ctx = chunk::Context {71 let mut ctx = chunk::Context {
71 buf: Vec::new(),72 buf: Vec::new(),
72 options: (&options).into(),73 options: (&options).into(),
73 path_cache: Cache::new(dir, state, case, Vec::with_capacity(512), attribute_files),74 path_cache: Stack::new(dir, state, case, Vec::with_capacity(512), attribute_files),
74 filters: options.filters,75 filters: options.filters,
75 find,76 find,
76 };77 };
gix-worktree-state/src/checkout/mod.rsrenamed from gix-worktree/src/checkout/mod.rs+1−1
@@ -60,7 +60,7 @@ pub struct Options { · 59 unmodified lines
60 /// Control how stat comparisons are made when checking if a file is fresh.60 /// Control how stat comparisons are made when checking if a file is fresh.
61 pub stat_options: stat::Options,61 pub stat_options: stat::Options,
62 /// A stack of attributes to use with the filesystem cache to use as driver for filters.62 /// A stack of attributes to use with the filesystem cache to use as driver for filters.
63 pub attributes: crate::cache::state::Attributes,63 pub attributes: gix_worktree::stack::state::Attributes,
64 /// The filter pipeline to use for applying mandatory filters before writing to the worktree.64 /// The filter pipeline to use for applying mandatory filters before writing to the worktree.
65 pub filters: gix_filter::Pipeline,65 pub filters: gix_filter::Pipeline,
66 /// Control how long-running processes may use the 'delay' capability.66 /// Control how long-running processes may use the 'delay' capability.
gix-worktree-state/src/lib.rs+6−0
@@ -0,0 +1,6 @@
1//! A crate to help setting the worktree to a particular state.
2#![deny(missing_docs, rust_2018_idioms, unsafe_code)]
3
4///
5pub mod checkout;
6pub use checkout::function::checkout;
gix-worktree-state/tests/fixtures/generated-archives/.gitignore+5−0
@@ -0,0 +1,5 @@
1make_ignore_and_attributes_setup.tar.xz
2make_mixed_without_submodules.tar.xz
3make_mixed_without_submodules_and_symlinks.tar.xz
4make_attributes_baseline.tar.xz
5make_dangerous_symlink.tar.xz
gix-worktree-state/tests/fixtures/generated-archives/make_ignorecase_collisions.tar.xzrenamed from gix-worktree/tests/fixtures/generated-archives/make_ignorecase_collisions.tar.xz+0−0

File renamed without changes.

gix-worktree-state/tests/fixtures/make_dangerous_symlink.shrenamed from gix-worktree/tests/fixtures/make_dangerous_symlink.sh+0−0

File renamed without changes.

gix-worktree-state/tests/fixtures/make_ignorecase_collisions.shrenamed from gix-worktree/tests/fixtures/make_ignorecase_collisions.sh+0−0

File renamed without changes.

gix-worktree-state/tests/fixtures/make_mixed_without_submodules.shrenamed from gix-worktree/tests/fixtures/make_mixed_without_submodules.sh+0−0

File renamed without changes.

gix-worktree-state/tests/fixtures/make_mixed_without_submodules_and_symlinks.shrenamed from gix-worktree/tests/fixtures/make_mixed_without_submodules_and_symlinks.sh+0−0

File renamed without changes.

gix-worktree-state/tests/state-multi-threaded.rs+4−0
@@ -0,0 +1,4 @@
1#[cfg(feature = "internal-testing-gix-features-parallel")]
2mod state;
3#[cfg(feature = "internal-testing-gix-features-parallel")]
4use state::*;
gix-worktree-state/tests/state-single-threaded.rs+4−0
@@ -0,0 +1,4 @@
1#[cfg(not(feature = "internal-testing-gix-features-parallel"))]
2mod state;
3#[cfg(not(feature = "internal-testing-gix-features-parallel"))]
4use state::*;
gix-worktree-state/tests/state/checkout.rsrenamed from gix-worktree/tests/worktree/checkout.rs+10−10
@@ -10,9 +10,9 @@ use std::{ · 9 unmodified lines
10use gix_features::progress;10use gix_features::progress;
11use gix_object::bstr::ByteSlice;11use gix_object::bstr::ByteSlice;
12use gix_odb::FindExt;12use gix_odb::FindExt;
13use gix_worktree::checkout::Collision;13use gix_testtools::tempfile::TempDir;
14use gix_worktree_state::checkout::Collision;
14use once_cell::sync::Lazy;15use once_cell::sync::Lazy;
15use tempfile::TempDir;
16 16
17use crate::fixture_path;17use crate::fixture_path;
18 18
@@ -454,26 +454,26 @@ pub fn dir_structure<P: AsRef<std::path::Path>>(path: P) -> Vec<std::path::PathB · 435 unmodified lines
454}454}
455 455
456fn checkout_index_in_tmp_dir(456fn checkout_index_in_tmp_dir(
457 opts: gix_worktree::checkout::Options,457 opts: gix_worktree_state::checkout::Options,
458 name: &str,458 name: &str,
459) -> crate::Result<(PathBuf, TempDir, gix_index::File, gix_worktree::checkout::Outcome)> {459) -> crate::Result<(PathBuf, TempDir, gix_index::File, gix_worktree_state::checkout::Outcome)> {
460 checkout_index_in_tmp_dir_opts(opts, name, |_d| true, |_| Ok(()))460 checkout_index_in_tmp_dir_opts(opts, name, |_d| true, |_| Ok(()))
461}461}
462 462
463fn checkout_index_in_tmp_dir_opts(463fn checkout_index_in_tmp_dir_opts(
464 opts: gix_worktree::checkout::Options,464 opts: gix_worktree_state::checkout::Options,
465 name: &str,465 name: &str,
466 mut allow_return_object: impl FnMut(&gix_hash::oid) -> bool + Send + Clone,466 mut allow_return_object: impl FnMut(&gix_hash::oid) -> bool + Send + Clone,
467 prep_dest: impl Fn(&Path) -> std::io::Result<()>,467 prep_dest: impl Fn(&Path) -> std::io::Result<()>,
468) -> crate::Result<(PathBuf, TempDir, gix_index::File, gix_worktree::checkout::Outcome)> {468) -> crate::Result<(PathBuf, TempDir, gix_index::File, gix_worktree_state::checkout::Outcome)> {
469 let source_tree = fixture_path(name);469 let source_tree = fixture_path(name);
470 let git_dir = source_tree.join(".git");470 let git_dir = source_tree.join(".git");
471 let mut index = gix_index::File::at(git_dir.join("index"), gix_hash::Kind::Sha1, Default::default())?;471 let mut index = gix_index::File::at(git_dir.join("index"), gix_hash::Kind::Sha1, Default::default())?;
472 let odb = gix_odb::at(git_dir.join("objects"))?.into_inner().into_arc()?;472 let odb = gix_odb::at(git_dir.join("objects"))?.into_inner().into_arc()?;
473 let destination = tempfile::tempdir_in(std::env::current_dir()?)?;473 let destination = gix_testtools::tempfile::tempdir_in(std::env::current_dir()?)?;
474 prep_dest(destination.path()).expect("preparation must succeed");474 prep_dest(destination.path()).expect("preparation must succeed");
475 475
476 let outcome = gix_worktree::checkout(476 let outcome = gix_worktree_state::checkout(
477 &mut index,477 &mut index,
478 destination.path(),478 destination.path(),
479 move |oid, buf| {479 move |oid, buf| {
@@ -501,8 +501,8 @@ fn probe_gitoxide_dir() -> crate::Result<gix_fs::Capabilities> { · 21 unmodified lines
501 ))501 ))
502}502}
503 503
504fn opts_from_probe() -> gix_worktree::checkout::Options {504fn opts_from_probe() -> gix_worktree_state::checkout::Options {
505 gix_worktree::checkout::Options {505 gix_worktree_state::checkout::Options {
506 fs: probe_gitoxide_dir().unwrap(),506 fs: probe_gitoxide_dir().unwrap(),
507 destination_is_initially_empty: true,507 destination_is_initially_empty: true,
508 thread_limit: gix_features::parallel::num_threads(None).into(),508 thread_limit: gix_features::parallel::num_threads(None).into(),
gix-worktree-state/tests/state/mod.rs+10−0
@@ -0,0 +1,10 @@
1mod checkout;
2
3use std::path::{Path, PathBuf};
4
5pub type Result<T = ()> = std::result::Result<T, Box<dyn std::error::Error>>;
6
7pub fn fixture_path(name: &str) -> PathBuf {
8 let dir = gix_testtools::scripted_fixture_read_only(Path::new(name).with_extension("sh")).expect("script works");
9 dir
10}
gix-worktree-stream/tests/stream.rs+5−5
@@ -15,7 +15,7 @@ mod from_tree { · 14 unmodified lines
15 use gix_object::{bstr::ByteSlice, tree::EntryMode};15 use gix_object::{bstr::ByteSlice, tree::EntryMode};
16 use gix_odb::FindExt;16 use gix_odb::FindExt;
17 use gix_testtools::once_cell::sync::Lazy;17 use gix_testtools::once_cell::sync::Lazy;
18 use gix_worktree::cache::state::attributes::Source;18 use gix_worktree::stack::state::attributes::Source;
19 19
20 use crate::hex_to_id;20 use crate::hex_to_id;
21 21
@@ -231,7 +231,7 @@ mod from_tree { · 209 unmodified lines
231 Ok(())231 Ok(())
232 }232 }
233 233
234 fn basic() -> gix_testtools::Result<(PathBuf, gix_hash::ObjectId, gix_odb::HandleArc, gix_worktree::Cache)> {234 fn basic() -> gix_testtools::Result<(PathBuf, gix_hash::ObjectId, gix_odb::HandleArc, gix_worktree::Stack)> {
235 let dir = gix_testtools::scripted_fixture_read_only("basic.sh")?;235 let dir = gix_testtools::scripted_fixture_read_only("basic.sh")?;
236 236
237 let head = {237 let head = {
@@ -242,14 +242,14 @@ mod from_tree { · 4 unmodified lines
242 242
243 let mut collection = Default::default();243 let mut collection = Default::default();
244 let mut buf = Default::default();244 let mut buf = Default::default();
245 let attributes = gix_worktree::cache::state::Attributes::new(245 let attributes = gix_worktree::stack::state::Attributes::new(
246 gix_attributes::Search::new_globals(None::<PathBuf>, &mut buf, &mut collection)?,246 gix_attributes::Search::new_globals(None::<PathBuf>, &mut buf, &mut collection)?,
247 None,247 None,
248 Source::WorktreeThenIdMapping,248 Source::WorktreeThenIdMapping,
249 collection,249 collection,
250 );250 );
251 let state = gix_worktree::cache::State::AttributesStack(attributes);251 let state = gix_worktree::stack::State::AttributesStack(attributes);
252 let cache = gix_worktree::Cache::new(&dir, state, Case::Sensitive, Default::default(), Default::default());252 let cache = gix_worktree::Stack::new(&dir, state, Case::Sensitive, Default::default(), Default::default());
253 Ok((dir, head, odb.into_arc()?, cache))253 Ok((dir, head, odb.into_arc()?, cache))
254 }254 }
255 255
gix-worktree/Cargo.toml+1−9
@@ -3,7 +3,7 @@ name = "gix-worktree" · 2 unmodified lines
3version = "0.24.0"3version = "0.24.0"
4repository = "https://github.com/Byron/gitoxide"4repository = "https://github.com/Byron/gitoxide"
5license = "MIT OR Apache-2.0"5license = "MIT OR Apache-2.0"
6description = "A crate of the gitoxide project dedicated implementing everything around working trees and git excludes"6description = "A crate of the gitoxide project for shared worktree related types and utilities."
7authors = ["Sebastian Thiel <sebastian.thiel@icloud.com>"]7authors = ["Sebastian Thiel <sebastian.thiel@icloud.com>"]
8edition = "2021"8edition = "2021"
9include = ["src/**/*", "LICENSE-*", "CHANGELOG.md"]9include = ["src/**/*", "LICENSE-*", "CHANGELOG.md"]
@@ -33,25 +33,17 @@ gix-path = { version = "^0.8.4", path = "../gix-path" } · 23 unmodified lines
33gix-attributes = { version = "^0.16.0", path = "../gix-attributes" }33gix-attributes = { version = "^0.16.0", path = "../gix-attributes" }
34gix-ignore = { version = "^0.5.1", path = "../gix-ignore" }34gix-ignore = { version = "^0.5.1", path = "../gix-ignore" }
35gix-features = { version = "^0.32.1", path = "../gix-features" }35gix-features = { version = "^0.32.1", path = "../gix-features" }
36gix-filter = { version = "^0.3.0", path = "../gix-filter" }
37 36
38serde = { version = "1.0.114", optional = true, default-features = false, features = ["derive"]}37serde = { version = "1.0.114", optional = true, default-features = false, features = ["derive"]}
39 38
40thiserror = "1.0.26"
41filetime = "0.2.15"
42bstr = { version = "1.3.0", default-features = false }39bstr = { version = "1.3.0", default-features = false }
43 40
44document-features = { version = "0.2.0", optional = true }41document-features = { version = "0.2.0", optional = true }
45io-close = "0.3.7"
46 42
47[dev-dependencies]43[dev-dependencies]
48gix-testtools = { path = "../tests/tools" }44gix-testtools = { path = "../tests/tools" }
49gix-odb = { path = "../gix-odb" }45gix-odb = { path = "../gix-odb" }
50symlink = "0.1.0"46symlink = "0.1.0"
51once_cell = "1.18.0"
52
53walkdir = "2.3.2"
54tempfile = "3.2.0"
55 47
56[package.metadata.docs.rs]48[package.metadata.docs.rs]
57features = ["document-features", "serde"]49features = ["document-features", "serde"]
gix-worktree/src/lib.rs+5−14
@@ -1,4 +1,4 @@
1//! A crate with all index-centric functionality that is interacting with a worktree.1//! A crate with utility types for use by other crates that implement specifics.
2//!2//!
3//! Unless specified differently, all operations need an index file (e.g. `.git/index`) as driver.3//! Unless specified differently, all operations need an index file (e.g. `.git/index`) as driver.
4//!4//!
@@ -11,9 +11,6 @@ · 6 unmodified lines
11#![deny(missing_docs, rust_2018_idioms, unsafe_code)]11#![deny(missing_docs, rust_2018_idioms, unsafe_code)]
12use bstr::BString;12use bstr::BString;
13 13
14///
15pub mod read;
16
17/// A cache for efficiently executing operations on directories and files which are encountered in sorted order.14/// A cache for efficiently executing operations on directories and files which are encountered in sorted order.
18/// That way, these operations can be re-used for subsequent invocations in the same directory.15/// That way, these operations can be re-used for subsequent invocations in the same directory.
19///16///
@@ -35,26 +32,20 @@ pub mod read; · 15 unmodified lines
35///32///
36/// The caching is only useful if consecutive calls to create a directory are using a sorted list of entries.33/// The caching is only useful if consecutive calls to create a directory are using a sorted list of entries.
37#[derive(Clone)]34#[derive(Clone)]
38pub struct Cache {35pub struct Stack {
39 stack: gix_fs::Stack,36 stack: gix_fs::Stack,
40 /// tells us what to do as we change paths.37 /// tells us what to do as we change paths.
41 state: cache::State,38 state: stack::State,
42 /// A buffer used when reading attribute or ignore files or their respective objects from the object database.39 /// A buffer used when reading attribute or ignore files or their respective objects from the object database.
43 buf: Vec<u8>,40 buf: Vec<u8>,
44 /// If case folding should happen when looking up attributes or exclusions.41 /// If case folding should happen when looking up attributes or exclusions.
45 case: gix_glob::pattern::Case,42 case: gix_glob::pattern::Case,
46 /// A lookup table for object ids to read from in some situations when looking up attributes or exclusions.43 /// A lookup table for object ids to read from in some situations when looking up attributes or exclusions.
47 id_mappings: Vec<PathIdMapping>,44 id_mappings: Vec<PathIdMapping>,
48 statistics: cache::Statistics,45 statistics: stack::Statistics,
49}46}
50 47
51pub(crate) type PathIdMapping = (BString, gix_hash::ObjectId);48pub(crate) type PathIdMapping = (BString, gix_hash::ObjectId);
52 49
53///50///
54pub mod cache;51pub mod stack;
55///
56pub mod checkout;
57pub use checkout::function::checkout;
58
59pub mod status;
60pub use status::function::status;
gix-worktree/src/stack/delegate.rsrenamed from gix-worktree/src/cache/delegate.rs+1−1
@@ -1,6 +1,6 @@
1use bstr::{BStr, ByteSlice};1use bstr::{BStr, ByteSlice};
2 2
3use crate::{cache::State, PathIdMapping};3use crate::{stack::State, PathIdMapping};
4 4
5/// Various aggregate numbers related to the stack delegate itself.5/// Various aggregate numbers related to the stack delegate itself.
6#[derive(Default, Clone, Copy, Debug)]6#[derive(Default, Clone, Copy, Debug)]
gix-worktree/src/stack/mod.rsrenamed from gix-worktree/src/cache/mod.rs+10−10
@@ -4,10 +4,10 @@ use std::path::{Path, PathBuf}; · 3 unmodified lines
4use bstr::{BStr, ByteSlice};4use bstr::{BStr, ByteSlice};
5use gix_hash::oid;5use gix_hash::oid;
6 6
7use super::Cache;7use super::Stack;
8use crate::PathIdMapping;8use crate::PathIdMapping;
9 9
10/// Various aggregate numbers collected from when the corresponding [`Cache`] was instantiated.10/// Various aggregate numbers collected from when the corresponding [`Stack`] was instantiated.
11#[derive(Default, Clone, Copy, Debug)]11#[derive(Default, Clone, Copy, Debug)]
12#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]12#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
13pub struct Statistics {13pub struct Statistics {
@@ -45,12 +45,12 @@ pub enum State { · 31 unmodified lines
45 45
46#[must_use]46#[must_use]
47pub struct Platform<'a> {47pub struct Platform<'a> {
48 parent: &'a Cache,48 parent: &'a Stack,
49 is_dir: Option<bool>,49 is_dir: Option<bool>,
50}50}
51 51
52/// Initialization52/// Initialization
53impl Cache {53impl Stack {
54 /// Create a new instance with `worktree_root` being the base for all future paths we match.54 /// Create a new instance with `worktree_root` being the base for all future paths we match.
55 /// `state` defines the capabilities of the cache.55 /// `state` defines the capabilities of the cache.
56 /// The `case` configures attribute and exclusion case sensitivity at *query time*, which should match the case that56 /// The `case` configures attribute and exclusion case sensitivity at *query time*, which should match the case that
@@ -64,7 +64,7 @@ impl Cache { · 7 unmodified lines
64 id_mappings: Vec<PathIdMapping>,64 id_mappings: Vec<PathIdMapping>,
65 ) -> Self {65 ) -> Self {
66 let root = worktree_root.into();66 let root = worktree_root.into();
67 Cache {67 Stack {
68 stack: gix_fs::Stack::new(root),68 stack: gix_fs::Stack::new(root),
69 state,69 state,
70 case,70 case,
@@ -76,12 +76,12 @@ impl Cache { · 5 unmodified lines
76}76}
77 77
78/// Entry points for attribute query78/// Entry points for attribute query
79impl Cache {79impl Stack {
80 /// Append the `relative` path to the root directory of the cache and efficiently create leading directories, while assuring that no80 /// Append the `relative` path to the root directory of the cache and efficiently create leading directories, while assuring that no
81 /// symlinks are in that path.81 /// symlinks are in that path.
82 /// Unless `is_dir` is known with `Some(…)`, then `relative` points to a directory itself in which case the entire resulting82 /// Unless `is_dir` is known with `Some(…)`, then `relative` points to a directory itself in which case the entire resulting
83 /// path is created as directory. If it's not known it is assumed to be a file.83 /// path is created as directory. If it's not known it is assumed to be a file.
84 /// `find` maybe used to lookup objects from an [id mapping][crate::cache::State::id_mappings_from_index()], with mappnigs84 /// `find` maybe used to lookup objects from an [id mapping][crate::stack::State::id_mappings_from_index()], with mappnigs
85 ///85 ///
86 /// Provide access to cached information for that `relative` path via the returned platform.86 /// Provide access to cached information for that `relative` path via the returned platform.
87 pub fn at_path<Find, E>(87 pub fn at_path<Find, E>(
@@ -110,7 +110,7 @@ impl Cache { · 22 unmodified lines
110 110
111 /// Obtain a platform for lookups from a repo-`relative` path, typically obtained from an index entry. `is_dir` should reflect111 /// Obtain a platform for lookups from a repo-`relative` path, typically obtained from an index entry. `is_dir` should reflect
112 /// whether it's a directory or not, or left at `None` if unknown.112 /// whether it's a directory or not, or left at `None` if unknown.
113 /// `find` maybe used to lookup objects from an [id mapping][crate::cache::State::id_mappings_from_index()].113 /// `find` maybe used to lookup objects from an [id mapping][crate::stack::State::id_mappings_from_index()].
114 /// All effects are similar to [`at_path()`][Self::at_path()].114 /// All effects are similar to [`at_path()`][Self::at_path()].
115 ///115 ///
116 /// If `relative` ends with `/` and `is_dir` is `None`, it is automatically assumed to be a directory.116 /// If `relative` ends with `/` and `is_dir` is `None`, it is automatically assumed to be a directory.
@@ -140,7 +140,7 @@ impl Cache { · 23 unmodified lines
140}140}
141 141
142/// Mutation142/// Mutation
143impl Cache {143impl Stack {
144 /// Reset the statistics after returning them.144 /// Reset the statistics after returning them.
145 pub fn take_statistics(&mut self) -> Statistics {145 pub fn take_statistics(&mut self) -> Statistics {
146 std::mem::take(&mut self.statistics)146 std::mem::take(&mut self.statistics)
@@ -159,7 +159,7 @@ impl Cache { · 12 unmodified lines
159}159}
160 160
161/// Access161/// Access
162impl Cache {162impl Stack {
163 /// Return the statistics we gathered thus far.163 /// Return the statistics we gathered thus far.
164 pub fn statistics(&self) -> &Statistics {164 pub fn statistics(&self) -> &Statistics {
165 &self.statistics165 &self.statistics
gix-worktree/src/stack/platform.rsrenamed from gix-worktree/src/cache/platform.rs+1−1
@@ -2,7 +2,7 @@ use std::path::Path; · 1 unmodified line
2 2
3use bstr::ByteSlice;3use bstr::ByteSlice;
4 4
5use crate::cache::Platform;5use crate::stack::Platform;
6 6
7/// Access7/// Access
8impl<'a> Platform<'a> {8impl<'a> Platform<'a> {
gix-worktree/src/stack/state/attributes.rsrenamed from gix-worktree/src/cache/state/attributes.rs+5−5
@@ -4,8 +4,8 @@ use bstr::{BStr, ByteSlice}; · 3 unmodified lines
4use gix_glob::pattern::Case;4use gix_glob::pattern::Case;
5 5
6use crate::{6use crate::{
7 cache::state::{AttributeMatchGroup, Attributes},7 stack::state::{AttributeMatchGroup, Attributes},
8 Cache, PathIdMapping,8 PathIdMapping, Stack,
9};9};
10 10
11/// Various aggregate numbers related [`Attributes`].11/// Various aggregate numbers related [`Attributes`].
@@ -23,7 +23,7 @@ pub struct Statistics { · 11 unmodified lines
23/// Decide where to read `.gitattributes` files from.23/// Decide where to read `.gitattributes` files from.
24///24///
25/// To Retrieve attribute files from id mappings, see25/// To Retrieve attribute files from id mappings, see
26/// [State::id_mappings_from_index()][crate::cache::State::id_mappings_from_index()].26/// [State::id_mappings_from_index()][crate::stack::State::id_mappings_from_index()].
27///27///
28/// These mappings are typically produced from an index.28/// These mappings are typically produced from an index.
29/// If a tree should be the source, build an attribute list from a tree instead, or convert a tree to an index.29/// If a tree should be the source, build an attribute list from a tree instead, or convert a tree to an index.
@@ -200,7 +200,7 @@ impl Attributes { · 170 unmodified lines
200}200}
201 201
202/// Attribute matching specific methods202/// Attribute matching specific methods
203impl Cache {203impl Stack {
204 /// Creates a new container to store match outcomes for all attribute matches.204 /// Creates a new container to store match outcomes for all attribute matches.
205 ///205 ///
206 /// ### Panics206 /// ### Panics
@@ -230,7 +230,7 @@ impl Cache { · 23 unmodified lines
230 }230 }
231 231
232 /// Return the metadata collection that enables initializing attribute match outcomes as done in232 /// Return the metadata collection that enables initializing attribute match outcomes as done in
233 /// [`attribute_matches()`][Cache::attribute_matches()] or [`selected_attribute_matches()`][Cache::selected_attribute_matches()]233 /// [`attribute_matches()`][Stack::attribute_matches()] or [`selected_attribute_matches()`][Stack::selected_attribute_matches()]
234 ///234 ///
235 /// ### Panics235 /// ### Panics
236 ///236 ///
gix-worktree/src/stack/state/ignore.rsrenamed from gix-worktree/src/cache/state/ignore.rs+2−2
@@ -4,7 +4,7 @@ use bstr::{BStr, ByteSlice}; · 3 unmodified lines
4use gix_glob::pattern::Case;4use gix_glob::pattern::Case;
5 5
6use crate::{6use crate::{
7 cache::state::{Ignore, IgnoreMatchGroup},7 stack::state::{Ignore, IgnoreMatchGroup},
8 PathIdMapping,8 PathIdMapping,
9};9};
10 10
@@ -12,7 +12,7 @@ use crate::{ · 1 unmodified line
12#[derive(Default, Debug, Clone, Copy)]12#[derive(Default, Debug, Clone, Copy)]
13pub enum Source {13pub enum Source {
14 /// Retrieve ignore files from id mappings, see14 /// Retrieve ignore files from id mappings, see
15 /// [State::id_mappings_from_index()][crate::cache::State::id_mappings_from_index()].15 /// [State::id_mappings_from_index()][crate::stack::State::id_mappings_from_index()].
16 ///16 ///
17 /// These mappings are typically produced from an index.17 /// These mappings are typically produced from an index.
18 /// If a tree should be the source, build an attribute list from a tree instead, or convert a tree to an index.18 /// If a tree should be the source, build an attribute list from a tree instead, or convert a tree to an index.
gix-worktree/src/stack/state/mod.rsrenamed from gix-worktree/src/cache/state/mod.rs+1−1
@@ -3,7 +3,7 @@ use std::path::PathBuf; · 2 unmodified lines
3use bstr::{BString, ByteSlice};3use bstr::{BString, ByteSlice};
4use gix_glob::pattern::Case;4use gix_glob::pattern::Case;
5 5
6use crate::{cache::State, PathIdMapping};6use crate::{stack::State, PathIdMapping};
7 7
8type AttributeMatchGroup = gix_attributes::Search;8type AttributeMatchGroup = gix_attributes::Search;
9type IgnoreMatchGroup = gix_ignore::Search;9type IgnoreMatchGroup = gix_ignore::Search;
gix-worktree/src/untracked.rs+0−1
@@ -1 +0,0 @@
1// TODO: untracked file detection, needs fs::Cache
gix-worktree/tests/fixtures/generated-archives/.gitignore+0−5
@@ -1,7 +1,2 @@
1make_ignore_and_attributes_setup.tar.xz1make_ignore_and_attributes_setup.tar.xz
2make_mixed_without_submodules.tar.xz
3make_mixed_without_submodules_and_symlinks.tar.xz
4make_attributes_baseline.tar.xz2make_attributes_baseline.tar.xz
5make_dangerous_symlink.tar.xz
6status_unchanged.tar.xz
7status_changed.tar.xz
gix-worktree/tests/fixtures/generated-archives/make_special_exclude_case.tar.xz+2−2
@@ -1,3 +1,3 @@
1version https://git-lfs.github.com/spec/v11version https://git-lfs.github.com/spec/v1
2oid sha256:24f605623efc49819d1b30c52fe22da8f94f2d267e8030ec9bc3b9b845801f762oid sha256:1804dc740055b8a5afe65a2db14f29c8ae4691896e67342a8dcb11530fd448c6
3size 92203size 9240
gix-worktree/tests/fixtures/generated-archives/racy_git.tar.xz+0−3
@@ -1,3 +0,0 @@
1version https://git-lfs.github.com/spec/v1
2oid sha256:35b728a127f3b6170bac44469ff36d5ad0be2a4247a8926f1aaffb97b5973efc
3size 1596
gix-worktree/tests/fixtures/generated-archives/status_conflict.tar.xz+0−3
@@ -1,3 +0,0 @@
1version https://git-lfs.github.com/spec/v1
2oid sha256:cd6d32ab7a1e372d80a617926cac2463f6620baedf74642d78fe7f8c956fd031
3size 11036
gix-worktree/tests/fixtures/generated-archives/status_intent_to_add.tar.xz+0−3
@@ -1,3 +0,0 @@
1version https://git-lfs.github.com/spec/v1
2oid sha256:876670d74c01249d361aa73d83ab20d846db7c922a3ca825f778b5f9d746c401
3size 9304
gix-worktree/tests/fixtures/generated-archives/status_removed.tar.xz+0−3
@@ -1,3 +0,0 @@
1version https://git-lfs.github.com/spec/v1
2oid sha256:e5fe85a65e3689e9e60598130be60761dc4ea129e04d7d5501320f7ebad1eb2b
3size 10520
gix-worktree/tests/fixtures/make_ignore_setup.sh+0−18
@@ -1,18 +0,0 @@
1#!/bin/bash
2set -eu -o pipefail
3
4git init -q
5
6cat <<EOF >.git/info/exclude
7# a sample .git/info/exclude
8file-anywhere
9/file-from-top
10
11dir-anywhere/
12/dir-from-top
13
14subdir-anywhere/file
15subdir-anywhere/dir/
16EOF
17
18git commit --allow-empty -m "init"
gix-worktree/tests/worktree/mod.rs+2−10
@@ -1,17 +1,9 @@
1mod cache;1use gix_hash::ObjectId;
2mod checkout;
3mod status;
4 2
5use std::path::{Path, PathBuf};3mod stack;
6 4
7use gix_hash::ObjectId;
8pub type Result<T = ()> = std::result::Result<T, Box<dyn std::error::Error>>;5pub type Result<T = ()> = std::result::Result<T, Box<dyn std::error::Error>>;
9 6
10pub fn hex_to_id(hex: &str) -> ObjectId {7pub fn hex_to_id(hex: &str) -> ObjectId {
11 ObjectId::from_hex(hex.as_bytes()).expect("40 bytes hex")8 ObjectId::from_hex(hex.as_bytes()).expect("40 bytes hex")
12}9}
13
14pub fn fixture_path(name: &str) -> PathBuf {
15 let dir = gix_testtools::scripted_fixture_read_only(Path::new(name).with_extension("sh")).expect("script works");
16 dir
17}
gix-worktree/tests/worktree/stack/attributes.rsrenamed from gix-worktree/tests/worktree/cache/attributes.rs+4−4
@@ -1,7 +1,7 @@
1use bstr::ByteSlice;1use bstr::ByteSlice;
2use gix_attributes::search::Outcome;2use gix_attributes::search::Outcome;
3use gix_glob::pattern::Case;3use gix_glob::pattern::Case;
4use gix_worktree::cache::state;4use gix_worktree::stack::state;
5 5
6#[test]6#[test]
7fn baseline() -> crate::Result {7fn baseline() -> crate::Result {
@@ -19,17 +19,17 @@ fn baseline() -> crate::Result { · 11 unmodified lines
19 19
20 let mut buf = Vec::new();20 let mut buf = Vec::new();
21 let mut collection = gix_attributes::search::MetadataCollection::default();21 let mut collection = gix_attributes::search::MetadataCollection::default();
22 let state = gix_worktree::cache::State::for_checkout(22 let state = gix_worktree::stack::State::for_checkout(
23 false,23 false,
24 state::Attributes::new(24 state::Attributes::new(
25 gix_attributes::Search::new_globals([base.join("user.attributes")], &mut buf, &mut collection)?,25 gix_attributes::Search::new_globals([base.join("user.attributes")], &mut buf, &mut collection)?,
26 Some(git_dir.join("info").join("attributes")),26 Some(git_dir.join("info").join("attributes")),
27 gix_worktree::cache::state::attributes::Source::WorktreeThenIdMapping,27 gix_worktree::stack::state::attributes::Source::WorktreeThenIdMapping,
28 collection,28 collection,
29 ),29 ),
30 );30 );
31 31
32 let mut cache = gix_worktree::Cache::new(&base, state, case, buf, vec![]);32 let mut cache = gix_worktree::Stack::new(&base, state, case, buf, vec![]);
33 33
34 let mut actual = cache.attribute_matches();34 let mut actual = cache.attribute_matches();
35 let input = std::fs::read(base.join("baseline"))?;35 let input = std::fs::read(base.join("baseline"))?;
gix-worktree/tests/worktree/stack/create_directory.rsrenamed from gix-worktree/tests/worktree/cache/create_directory.rs+9−9
@@ -1,7 +1,7 @@
1use std::path::Path;1use std::path::Path;
2 2
3use gix_worktree::{cache, Cache};3use gix_testtools::tempfile::{tempdir, TempDir};
4use tempfile::{tempdir, TempDir};4use gix_worktree::{stack, Stack};
5 5
6#[allow(clippy::ptr_arg)]6#[allow(clippy::ptr_arg)]
7fn panic_on_find<'buf>(_oid: &gix_hash::oid, _buf: &'buf mut Vec<u8>) -> std::io::Result<gix_object::BlobRef<'buf>> {7fn panic_on_find<'buf>(_oid: &gix_hash::oid, _buf: &'buf mut Vec<u8>) -> std::io::Result<gix_object::BlobRef<'buf>> {
@@ -11,9 +11,9 @@ fn panic_on_find<'buf>(_oid: &gix_hash::oid, _buf: &'buf mut Vec<u8>) -> std::io · 3 unmodified lines
11#[test]11#[test]
12fn root_is_assumed_to_exist_and_files_in_root_do_not_create_directory() -> crate::Result {12fn root_is_assumed_to_exist_and_files_in_root_do_not_create_directory() -> crate::Result {
13 let dir = tempdir()?;13 let dir = tempdir()?;
14 let mut cache = Cache::new(14 let mut cache = Stack::new(
15 dir.path().join("non-existing-root"),15 dir.path().join("non-existing-root"),
16 cache::State::for_checkout(false, Default::default()),16 stack::State::for_checkout(false, Default::default()),
17 Default::default(),17 Default::default(),
18 Vec::new(),18 Vec::new(),
19 Default::default(),19 Default::default(),
@@ -68,7 +68,7 @@ fn symlinks_or_files_in_path_are_forbidden_or_unlinked_when_forced() -> crate::R · 48 unmodified lines
68 std::fs::write(tmp.path().join("file-in-dir"), [])?;68 std::fs::write(tmp.path().join("file-in-dir"), [])?;
69 69
70 for dirname in &["file-in-dir", "link-to-dir"] {70 for dirname in &["file-in-dir", "link-to-dir"] {
71 if let cache::State::CreateDirectoryAndAttributesStack {71 if let stack::State::CreateDirectoryAndAttributesStack {
72 unlink_on_collision, ..72 unlink_on_collision, ..
73 } = cache.state_mut()73 } = cache.state_mut()
74 {74 {
@@ -90,7 +90,7 @@ fn symlinks_or_files_in_path_are_forbidden_or_unlinked_when_forced() -> crate::R · 15 unmodified lines
90 );90 );
91 cache.take_statistics();91 cache.take_statistics();
92 for dirname in &["link-to-dir", "file-in-dir"] {92 for dirname in &["link-to-dir", "file-in-dir"] {
93 if let cache::State::CreateDirectoryAndAttributesStack {93 if let stack::State::CreateDirectoryAndAttributesStack {
94 unlink_on_collision, ..94 unlink_on_collision, ..
95 } = cache.state_mut()95 } = cache.state_mut()
96 {96 {
@@ -109,11 +109,11 @@ fn symlinks_or_files_in_path_are_forbidden_or_unlinked_when_forced() -> crate::R · 12 unmodified lines
109 Ok(())109 Ok(())
110}110}
111 111
112fn new_cache() -> (Cache, TempDir) {112fn new_cache() -> (Stack, TempDir) {
113 let dir = tempdir().unwrap();113 let dir = tempdir().unwrap();
114 let cache = Cache::new(114 let cache = Stack::new(
115 dir.path(),115 dir.path(),
116 cache::State::for_checkout(false, Default::default()),116 stack::State::for_checkout(false, Default::default()),
117 Default::default(),117 Default::default(),
118 Vec::new(),118 Vec::new(),
119 Default::default(),119 Default::default(),
gix-worktree/tests/worktree/stack/ignore.rsrenamed from gix-worktree/tests/worktree/cache/ignore.rs+7−7
@@ -1,7 +1,7 @@
1use bstr::{BStr, ByteSlice};1use bstr::{BStr, ByteSlice};
2use gix_glob::pattern::Case;2use gix_glob::pattern::Case;
3use gix_odb::FindExt;3use gix_odb::FindExt;
4use gix_worktree::{cache::state::ignore::Source, Cache};4use gix_worktree::{stack::state::ignore::Source, Stack};
5 5
6use crate::hex_to_id;6use crate::hex_to_id;
7 7
@@ -37,16 +37,16 @@ fn exclude_by_dir_is_handled_just_like_git() { · 29 unmodified lines
37 37
38 let mut buf = Vec::new();38 let mut buf = Vec::new();
39 let case = gix_glob::pattern::Case::Sensitive;39 let case = gix_glob::pattern::Case::Sensitive;
40 let state = gix_worktree::cache::State::for_add(40 let state = gix_worktree::stack::State::for_add(
41 Default::default(),41 Default::default(),
42 gix_worktree::cache::state::Ignore::new(42 gix_worktree::stack::state::Ignore::new(
43 Default::default(),43 Default::default(),
44 gix_ignore::Search::from_git_dir(&git_dir, None, &mut buf).unwrap(),44 gix_ignore::Search::from_git_dir(&git_dir, None, &mut buf).unwrap(),
45 None,45 None,
46 Source::WorktreeThenIdMappingIfNotSkipped,46 Source::WorktreeThenIdMappingIfNotSkipped,
47 ),47 ),
48 );48 );
49 let mut cache = Cache::new(&dir, state, case, buf, Default::default());49 let mut cache = Stack::new(&dir, state, case, buf, Default::default());
50 let baseline = std::fs::read(git_dir.parent().unwrap().join("git-check-ignore.baseline")).unwrap();50 let baseline = std::fs::read(git_dir.parent().unwrap().join("git-check-ignore.baseline")).unwrap();
51 let expectations = IgnoreExpectations {51 let expectations = IgnoreExpectations {
52 lines: baseline.lines(),52 lines: baseline.lines(),
@@ -95,9 +95,9 @@ fn check_against_baseline() -> crate::Result { · 42 unmodified lines
95 };95 };
96 let mut index = gix_index::File::at(git_dir.join("index"), gix_hash::Kind::Sha1, Default::default())?;96 let mut index = gix_index::File::at(git_dir.join("index"), gix_hash::Kind::Sha1, Default::default())?;
97 let odb = gix_odb::at(git_dir.join("objects"))?;97 let odb = gix_odb::at(git_dir.join("objects"))?;
98 let state = gix_worktree::cache::State::for_add(98 let state = gix_worktree::stack::State::for_add(
99 Default::default(),99 Default::default(),
100 gix_worktree::cache::state::Ignore::new(100 gix_worktree::stack::state::Ignore::new(
101 gix_ignore::Search::from_overrides(vec!["!force-include"]),101 gix_ignore::Search::from_overrides(vec!["!force-include"]),
102 gix_ignore::Search::from_git_dir(&git_dir, Some(user_exclude_path), &mut buf)?,102 gix_ignore::Search::from_git_dir(&git_dir, Some(user_exclude_path), &mut buf)?,
103 None,103 None,
@@ -113,7 +113,7 @@ fn check_against_baseline() -> crate::Result { · 9 unmodified lines
113 hex_to_id("5c7e0ed672d3d31d83a3df61f13cc8f7b22d5bfd")113 hex_to_id("5c7e0ed672d3d31d83a3df61f13cc8f7b22d5bfd")
114 )]114 )]
115 );115 );
116 let mut cache = Cache::new(&worktree_dir, state, case, buf, attribute_files_in_index);116 let mut cache = Stack::new(&worktree_dir, state, case, buf, attribute_files_in_index);
117 117
118 let baseline = std::fs::read(git_dir.parent().unwrap().join("git-check-ignore.baseline"))?;118 let baseline = std::fs::read(git_dir.parent().unwrap().join("git-check-ignore.baseline"))?;
119 let expectations = IgnoreExpectations {119 let expectations = IgnoreExpectations {
gix-worktree/tests/worktree/stack/mod.rsrenamed from gix-worktree/tests/worktree/cache/mod.rs+0−0

File renamed without changes.

gix/Cargo.toml+1−0
@@ -162,6 +162,7 @@ gix-credentials = { version = "^0.17.1", path = "../gix-credentials" } · 161 unmodified lines
162gix-prompt = { version = "^0.5.5", path = "../gix-prompt" }162gix-prompt = { version = "^0.5.5", path = "../gix-prompt" }
163gix-index = { version = "^0.22.0", path = "../gix-index" }163gix-index = { version = "^0.22.0", path = "../gix-index" }
164gix-worktree = { version = "^0.24.0", path = "../gix-worktree" }164gix-worktree = { version = "^0.24.0", path = "../gix-worktree" }
165gix-worktree-state = { version = "^0.1.0", path = "../gix-worktree-state" }
165gix-hashtable = { version = "^0.2.4", path = "../gix-hashtable" }166gix-hashtable = { version = "^0.2.4", path = "../gix-hashtable" }
166gix-commitgraph = { version = "^0.18.2", path = "../gix-commitgraph" }167gix-commitgraph = { version = "^0.18.2", path = "../gix-commitgraph" }
167gix-pathspec = { version = "^0.1.0", path = "../gix-pathspec" }168gix-pathspec = { version = "^0.1.0", path = "../gix-pathspec" }
gix/src/clone/checkout.rs+6−5
@@ -27,7 +27,8 @@ pub mod main_worktree { · 26 unmodified lines
27 CheckoutOptions(#[from] crate::config::checkout_options::Error),27 CheckoutOptions(#[from] crate::config::checkout_options::Error),
28 #[error(transparent)]28 #[error(transparent)]
29 IndexCheckout(29 IndexCheckout(
30 #[from] gix_worktree::checkout::Error<gix_odb::find::existing_object::Error<gix_odb::store::find::Error>>,30 #[from]
31 gix_worktree_state::checkout::Error<gix_odb::find::existing_object::Error<gix_odb::store::find::Error>>,
31 ),32 ),
32 #[error("Failed to reopen object database as Arc (only if thread-safety wasn't compiled in)")]33 #[error("Failed to reopen object database as Arc (only if thread-safety wasn't compiled in)")]
33 OpenArcOdb(#[from] std::io::Error),34 OpenArcOdb(#[from] std::io::Error),
@@ -68,7 +69,7 @@ pub mod main_worktree { · 34 unmodified lines
68 &mut self,69 &mut self,
69 mut progress: impl crate::Progress,70 mut progress: impl crate::Progress,
70 should_interrupt: &AtomicBool,71 should_interrupt: &AtomicBool,
71 ) -> Result<(Repository, gix_worktree::checkout::Outcome), Error> {72 ) -> Result<(Repository, gix_worktree_state::checkout::Outcome), Error> {
72 let _span = gix_trace::coarse!("gix::clone::PrepareCheckout::main_worktree()");73 let _span = gix_trace::coarse!("gix::clone::PrepareCheckout::main_worktree()");
73 let repo = self74 let repo = self
74 .repo75 .repo
@@ -82,7 +83,7 @@ pub mod main_worktree { · 7 unmodified lines
82 None => {83 None => {
83 return Ok((84 return Ok((
84 self.repo.take().expect("still present"),85 self.repo.take().expect("still present"),
85 gix_worktree::checkout::Outcome::default(),86 gix_worktree_state::checkout::Outcome::default(),
86 ))87 ))
87 }88 }
88 };89 };
@@ -95,7 +96,7 @@ pub mod main_worktree { · 6 unmodified lines
95 96
96 let mut opts = repo97 let mut opts = repo
97 .config98 .config
98 .checkout_options(repo, gix_worktree::cache::state::attributes::Source::IdMapping)?;99 .checkout_options(repo, gix_worktree::stack::state::attributes::Source::IdMapping)?;
99 opts.destination_is_initially_empty = true;100 opts.destination_is_initially_empty = true;
100 101
101 let mut files = progress.add_child_with_id("checkout", ProgressId::CheckoutFiles.into());102 let mut files = progress.add_child_with_id("checkout", ProgressId::CheckoutFiles.into());
@@ -105,7 +106,7 @@ pub mod main_worktree { · 3 unmodified lines
105 bytes.init(None, crate::progress::bytes());106 bytes.init(None, crate::progress::bytes());
106 107
107 let start = std::time::Instant::now();108 let start = std::time::Instant::now();
108 let outcome = gix_worktree::checkout(109 let outcome = gix_worktree_state::checkout(
109 &mut index,110 &mut index,
110 workdir,111 workdir,
111 {112 {
gix/src/config/cache/access.rs+9−9
@@ -160,8 +160,8 @@ impl Cache { · 159 unmodified lines
160 pub(crate) fn checkout_options(160 pub(crate) fn checkout_options(
161 &self,161 &self,
162 repo: &Repository,162 repo: &Repository,
163 attributes_source: gix_worktree::cache::state::attributes::Source,163 attributes_source: gix_worktree::stack::state::attributes::Source,
164 ) -> Result<gix_worktree::checkout::Options, checkout_options::Error> {164 ) -> Result<gix_worktree_state::checkout::Options, checkout_options::Error> {
165 let git_dir = repo.git_dir();165 let git_dir = repo.git_dir();
166 let thread_limit = self.apply_leniency(166 let thread_limit = self.apply_leniency(
167 self.resolved167 self.resolved
@@ -189,7 +189,7 @@ impl Cache { · 21 unmodified lines
189 } else {189 } else {
190 gix_filter::driver::apply::Delay::Forbid190 gix_filter::driver::apply::Delay::Forbid
191 };191 };
192 Ok(gix_worktree::checkout::Options {192 Ok(gix_worktree_state::checkout::Options {
193 filter_process_delay,193 filter_process_delay,
194 filters,194 filters,
195 attributes: self195 attributes: self
@@ -219,14 +219,14 @@ impl Cache { · 23 unmodified lines
219 &self,219 &self,
220 git_dir: &std::path::Path,220 git_dir: &std::path::Path,
221 overrides: Option<gix_ignore::Search>,221 overrides: Option<gix_ignore::Search>,
222 source: gix_worktree::cache::state::ignore::Source,222 source: gix_worktree::stack::state::ignore::Source,
223 buf: &mut Vec<u8>,223 buf: &mut Vec<u8>,
224 ) -> Result<gix_worktree::cache::state::Ignore, config::exclude_stack::Error> {224 ) -> Result<gix_worktree::stack::state::Ignore, config::exclude_stack::Error> {
225 let excludes_file = match self.excludes_file().transpose()? {225 let excludes_file = match self.excludes_file().transpose()? {
226 Some(user_path) => Some(user_path),226 Some(user_path) => Some(user_path),
227 None => self.xdg_config_path("ignore")?,227 None => self.xdg_config_path("ignore")?,
228 };228 };
229 Ok(gix_worktree::cache::state::Ignore::new(229 Ok(gix_worktree::stack::state::Ignore::new(
230 overrides.unwrap_or_default(),230 overrides.unwrap_or_default(),
231 gix_ignore::Search::from_git_dir(git_dir, excludes_file, buf)?,231 gix_ignore::Search::from_git_dir(git_dir, excludes_file, buf)?,
232 None,232 None,
@@ -237,9 +237,9 @@ impl Cache { · 4 unmodified lines
237 pub(crate) fn assemble_attribute_globals(237 pub(crate) fn assemble_attribute_globals(
238 &self,238 &self,
239 git_dir: &std::path::Path,239 git_dir: &std::path::Path,
240 source: gix_worktree::cache::state::attributes::Source,240 source: gix_worktree::stack::state::attributes::Source,
241 attributes: crate::open::permissions::Attributes,241 attributes: crate::open::permissions::Attributes,
242 ) -> Result<(gix_worktree::cache::state::Attributes, Vec<u8>), config::attribute_stack::Error> {242 ) -> Result<(gix_worktree::stack::state::Attributes, Vec<u8>), config::attribute_stack::Error> {
243 let configured_or_user_attributes = match self243 let configured_or_user_attributes = match self
244 .trusted_file_path("core", None, Core::ATTRIBUTES_FILE.name)244 .trusted_file_path("core", None, Core::ATTRIBUTES_FILE.name)
245 .transpose()?245 .transpose()?
@@ -265,7 +265,7 @@ impl Cache { · 19 unmodified lines
265 let info_attributes_path = git_dir.join("info").join("attributes");265 let info_attributes_path = git_dir.join("info").join("attributes");
266 let mut buf = Vec::new();266 let mut buf = Vec::new();
267 let mut collection = gix_attributes::search::MetadataCollection::default();267 let mut collection = gix_attributes::search::MetadataCollection::default();
268 let state = gix_worktree::cache::state::Attributes::new(268 let state = gix_worktree::stack::state::Attributes::new(
269 gix_attributes::Search::new_globals(attribute_files, &mut buf, &mut collection)?,269 gix_attributes::Search::new_globals(attribute_files, &mut buf, &mut collection)?,
270 Some(info_attributes_path),270 Some(info_attributes_path),
271 source,271 source,
gix/src/filter.rs+3−3
@@ -67,7 +67,7 @@ pub mod pipeline { · 66 unmodified lines
67#[derive(Clone)]67#[derive(Clone)]
68pub struct Pipeline<'repo> {68pub struct Pipeline<'repo> {
69 inner: gix_filter::Pipeline,69 inner: gix_filter::Pipeline,
70 cache: gix_worktree::Cache,70 cache: gix_worktree::Stack,
71 repo: &'repo Repository,71 repo: &'repo Repository,
72}72}
73 73
@@ -110,7 +110,7 @@ impl<'repo> Pipeline<'repo> { · 36 unmodified lines
110 110
111 /// Create a new instance by extracting all necessary information and configuration from a `repo` along with `cache` for accessing111 /// Create a new instance by extracting all necessary information and configuration from a `repo` along with `cache` for accessing
112 /// attributes. The `index` is used for some filters which may access it under very specific circumstances.112 /// attributes. The `index` is used for some filters which may access it under very specific circumstances.
113 pub fn new(repo: &'repo Repository, cache: gix_worktree::Cache) -> Result<Self, pipeline::options::Error> {113 pub fn new(repo: &'repo Repository, cache: gix_worktree::Stack) -> Result<Self, pipeline::options::Error> {
114 let pipeline = gix_filter::Pipeline::new(cache.attributes_collection(), Self::options(repo)?);114 let pipeline = gix_filter::Pipeline::new(cache.attributes_collection(), Self::options(repo)?);
115 Ok(Pipeline {115 Ok(Pipeline {
116 inner: pipeline,116 inner: pipeline,
@@ -120,7 +120,7 @@ impl<'repo> Pipeline<'repo> { · 3 unmodified lines
120 }120 }
121 121
122 /// Detach the repository and obtain the individual functional parts.122 /// Detach the repository and obtain the individual functional parts.
123 pub fn into_parts(self) -> (gix_filter::Pipeline, gix_worktree::Cache) {123 pub fn into_parts(self) -> (gix_filter::Pipeline, gix_worktree::Stack) {
124 (self.inner, self.cache)124 (self.inner, self.cache)
125 }125 }
126}126}
gix/src/pathspec.rs+4−4
@@ -43,7 +43,7 @@ impl<'repo> Pathspec<'repo> { · 42 unmodified lines
43 repo: &'repo Repository,43 repo: &'repo Repository,
44 patterns: impl IntoIterator<Item = impl AsRef<BStr>>,44 patterns: impl IntoIterator<Item = impl AsRef<BStr>>,
45 inherit_ignore_case: bool,45 inherit_ignore_case: bool,
46 make_attributes: impl FnOnce() -> Result<gix_worktree::Cache, Box<dyn std::error::Error + Send + Sync + 'static>>,46 make_attributes: impl FnOnce() -> Result<gix_worktree::Stack, Box<dyn std::error::Error + Send + Sync + 'static>>,
47 ) -> Result<Self, init::Error> {47 ) -> Result<Self, init::Error> {
48 let mut defaults = repo.pathspec_defaults()?;48 let mut defaults = repo.pathspec_defaults()?;
49 if inherit_ignore_case && repo.config.fs_capabilities()?.ignore_case {49 if inherit_ignore_case && repo.config.fs_capabilities()?.ignore_case {
@@ -67,9 +67,9 @@ impl<'repo> Pathspec<'repo> { · 17 unmodified lines
67 Ok(Self { repo, search, cache })67 Ok(Self { repo, search, cache })
68 }68 }
69 /// Turn ourselves into the functional parts for direct usage.69 /// Turn ourselves into the functional parts for direct usage.
70 /// Note that the [`cache`](gix_worktree::Cache) is only set if one of the [`search` patterns](Search)70 /// Note that the [`cache`](gix_worktree::Stack) is only set if one of the [`search` patterns](Search)
71 /// is specifying attributes to match for.71 /// is specifying attributes to match for.
72 pub fn into_parts(self) -> (Search, Option<gix_worktree::Cache>) {72 pub fn into_parts(self) -> (Search, Option<gix_worktree::Stack>) {
73 (self.search, self.cache)73 (self.search, self.cache)
74 }74 }
75}75}
@@ -77,7 +77,7 @@ impl<'repo> Pathspec<'repo> { · 1 unmodified line
77/// Access77/// Access
78impl<'repo> Pathspec<'repo> {78impl<'repo> Pathspec<'repo> {
79 /// Return the attributes cache which is used when matching attributes in pathspecs, or `None` if none of the pathspecs require that.79 /// Return the attributes cache which is used when matching attributes in pathspecs, or `None` if none of the pathspecs require that.
80 pub fn attributes(&self) -> Option<&gix_worktree::Cache> {80 pub fn attributes(&self) -> Option<&gix_worktree::Stack> {
81 self.cache.as_ref()81 self.cache.as_ref()
82 }82 }
83 83
gix/src/repository/attributes.rs+13−13
@@ -29,10 +29,10 @@ impl Repository { · 28 unmodified lines
29 pub fn attributes(29 pub fn attributes(
30 &self,30 &self,
31 index: &gix_index::State,31 index: &gix_index::State,
32 attributes_source: gix_worktree::cache::state::attributes::Source,32 attributes_source: gix_worktree::stack::state::attributes::Source,
33 ignore_source: gix_worktree::cache::state::ignore::Source,33 ignore_source: gix_worktree::stack::state::ignore::Source,
34 exclude_overrides: Option<gix_ignore::Search>,34 exclude_overrides: Option<gix_ignore::Search>,
35 ) -> Result<gix_worktree::Cache, Error> {35 ) -> Result<gix_worktree::Stack, Error> {
36 let case = if self.config.ignore_case {36 let case = if self.config.ignore_case {
37 gix_glob::pattern::Case::Fold37 gix_glob::pattern::Case::Fold
38 } else {38 } else {
@@ -46,9 +46,9 @@ impl Repository { · 7 unmodified lines
46 let ignore =46 let ignore =
47 self.config47 self.config
48 .assemble_exclude_globals(self.git_dir(), exclude_overrides, ignore_source, &mut buf)?;48 .assemble_exclude_globals(self.git_dir(), exclude_overrides, ignore_source, &mut buf)?;
49 let state = gix_worktree::cache::State::AttributesAndIgnoreStack { attributes, ignore };49 let state = gix_worktree::stack::State::AttributesAndIgnoreStack { attributes, ignore };
50 let attribute_list = state.id_mappings_from_index(index, index.path_backing(), case);50 let attribute_list = state.id_mappings_from_index(index, index.path_backing(), case);
51 Ok(gix_worktree::Cache::new(51 Ok(gix_worktree::Stack::new(
52 // this is alright as we don't cause mutation of that directory, it's virtual.52 // this is alright as we don't cause mutation of that directory, it's virtual.
53 self.work_dir().unwrap_or(self.git_dir()),53 self.work_dir().unwrap_or(self.git_dir()),
54 state,54 state,
@@ -62,8 +62,8 @@ impl Repository { · 7 unmodified lines
62 pub fn attributes_only(62 pub fn attributes_only(
63 &self,63 &self,
64 index: &gix_index::State,64 index: &gix_index::State,
65 attributes_source: gix_worktree::cache::state::attributes::Source,65 attributes_source: gix_worktree::stack::state::attributes::Source,
66 ) -> Result<gix_worktree::Cache, config::attribute_stack::Error> {66 ) -> Result<gix_worktree::Stack, config::attribute_stack::Error> {
67 let case = if self.config.ignore_case {67 let case = if self.config.ignore_case {
68 gix_glob::pattern::Case::Fold68 gix_glob::pattern::Case::Fold
69 } else {69 } else {
@@ -74,9 +74,9 @@ impl Repository { · 4 unmodified lines
74 attributes_source,74 attributes_source,
75 self.options.permissions.attributes,75 self.options.permissions.attributes,
76 )?;76 )?;
77 let state = gix_worktree::cache::State::AttributesStack(attributes);77 let state = gix_worktree::stack::State::AttributesStack(attributes);
78 let attribute_list = state.id_mappings_from_index(index, index.path_backing(), case);78 let attribute_list = state.id_mappings_from_index(index, index.path_backing(), case);
79 Ok(gix_worktree::Cache::new(79 Ok(gix_worktree::Stack::new(
80 // this is alright as we don't cause mutation of that directory, it's virtual.80 // this is alright as we don't cause mutation of that directory, it's virtual.
81 self.work_dir().unwrap_or(self.git_dir()),81 self.work_dir().unwrap_or(self.git_dir()),
82 state,82 state,
@@ -105,8 +105,8 @@ impl Repository { · 22 unmodified lines
105 &self,105 &self,
106 index: &gix_index::State,106 index: &gix_index::State,
107 overrides: Option<gix_ignore::Search>,107 overrides: Option<gix_ignore::Search>,
108 source: gix_worktree::cache::state::ignore::Source,108 source: gix_worktree::stack::state::ignore::Source,
109 ) -> Result<gix_worktree::Cache, config::exclude_stack::Error> {109 ) -> Result<gix_worktree::Stack, config::exclude_stack::Error> {
110 let case = if self.config.ignore_case {110 let case = if self.config.ignore_case {
111 gix_glob::pattern::Case::Fold111 gix_glob::pattern::Case::Fold
112 } else {112 } else {
@@ -116,9 +116,9 @@ impl Repository { · 3 unmodified lines
116 let ignore = self116 let ignore = self
117 .config117 .config
118 .assemble_exclude_globals(self.git_dir(), overrides, source, &mut buf)?;118 .assemble_exclude_globals(self.git_dir(), overrides, source, &mut buf)?;
119 let state = gix_worktree::cache::State::IgnoreStack(ignore);119 let state = gix_worktree::stack::State::IgnoreStack(ignore);
120 let attribute_list = state.id_mappings_from_index(index, index.path_backing(), case);120 let attribute_list = state.id_mappings_from_index(index, index.path_backing(), case);
121 Ok(gix_worktree::Cache::new(121 Ok(gix_worktree::Stack::new(
122 // this is alright as we don't cause mutation of that directory, it's virtual.122 // this is alright as we don't cause mutation of that directory, it's virtual.
123 self.work_dir().unwrap_or(self.git_dir()),123 self.work_dir().unwrap_or(self.git_dir()),
124 state,124 state,
gix/src/repository/filter.rs+2−2
@@ -49,13 +49,13 @@ impl Repository { · 48 unmodified lines
49 },49 },
50 Ok,50 Ok,
51 )?)?;51 )?)?;
52 let cache = self.attributes_only(&index, gix_worktree::cache::state::attributes::Source::IdMapping)?;52 let cache = self.attributes_only(&index, gix_worktree::stack::state::attributes::Source::IdMapping)?;
53 (cache, IndexPersistedOrInMemory::InMemory(index))53 (cache, IndexPersistedOrInMemory::InMemory(index))
54 } else {54 } else {
55 let index = self.index()?;55 let index = self.index()?;
56 let cache = self.attributes_only(56 let cache = self.attributes_only(
57 &index,57 &index,
58 gix_worktree::cache::state::attributes::Source::WorktreeThenIdMapping,58 gix_worktree::stack::state::attributes::Source::WorktreeThenIdMapping,
59 )?;59 )?;
60 (cache, IndexPersistedOrInMemory::Persisted(index))60 (cache, IndexPersistedOrInMemory::Persisted(index))
61 };61 };
gix/src/repository/pathspec.rs+1−1
@@ -17,7 +17,7 @@ impl Repository { · 16 unmodified lines
17 Pathspec::new(self, patterns, inherit_ignore_case, || {17 Pathspec::new(self, patterns, inherit_ignore_case, || {
18 self.attributes_only(18 self.attributes_only(
19 index,19 index,
20 gix_worktree::cache::state::attributes::Source::WorktreeThenIdMapping,20 gix_worktree::stack::state::attributes::Source::WorktreeThenIdMapping,
21 )21 )
22 .map_err(Into::into)22 .map_err(Into::into)
23 })23 })
gix/src/repository/worktree.rs+1−1
@@ -74,7 +74,7 @@ impl crate::Repository { · 73 unmodified lines
74 // TODO(perf): when loading a non-HEAD tree, we effectively traverse the tree twice. This is usually fast though, and sharing74 // TODO(perf): when loading a non-HEAD tree, we effectively traverse the tree twice. This is usually fast though, and sharing
75 // an object cache between the copies of the ODB handles isn't trivial and needs a lock.75 // an object cache between the copies of the ODB handles isn't trivial and needs a lock.
76 let index = self.index_from_tree(&id)?;76 let index = self.index_from_tree(&id)?;
77 let mut cache = self.attributes_only(&index, gix_worktree::cache::state::attributes::Source::IdMapping)?;77 let mut cache = self.attributes_only(&index, gix_worktree::stack::state::attributes::Source::IdMapping)?;
78 let pipeline =78 let pipeline =
79 gix_filter::Pipeline::new(cache.attributes_collection(), crate::filter::Pipeline::options(self)?);79 gix_filter::Pipeline::new(cache.attributes_collection(), crate::filter::Pipeline::options(self)?);
80 let objects = self.objects.clone().into_arc().expect("TBD error handling");80 let objects = self.objects.clone().into_arc().expect("TBD error handling");
gix/src/types.rs+1−1
@@ -202,7 +202,7 @@ pub struct Remote<'repo> { · 201 unmodified lines
202pub struct Pathspec<'repo> {202pub struct Pathspec<'repo> {
203 pub(crate) repo: &'repo Repository,203 pub(crate) repo: &'repo Repository,
204 /// The cache to power attribute access. It's only initialized if we have a pattern with attributes.204 /// The cache to power attribute access. It's only initialized if we have a pattern with attributes.
205 pub(crate) cache: Option<gix_worktree::Cache>,205 pub(crate) cache: Option<gix_worktree::Stack>,
206 /// The prepared search to use for checking matches.206 /// The prepared search to use for checking matches.
207 pub(crate) search: gix_pathspec::Search,207 pub(crate) search: gix_pathspec::Search,
208}208}
gix/src/worktree/mod.rs+8−7
@@ -3,6 +3,7 @@ use std::path::PathBuf; · 2 unmodified lines
3#[cfg(feature = "worktree-archive")]3#[cfg(feature = "worktree-archive")]
4pub use gix_archive as archive;4pub use gix_archive as archive;
5pub use gix_worktree::*;5pub use gix_worktree::*;
6pub use gix_worktree_state as state;
6#[cfg(feature = "worktree-stream")]7#[cfg(feature = "worktree-stream")]
7pub use gix_worktree_stream as stream;8pub use gix_worktree_stream as stream;
8 9
@@ -120,12 +121,12 @@ pub mod excludes { · 111 unmodified lines
120 ///121 ///
121 /// When only excludes are desired, this is the most efficient way to obtain them. Otherwise use122 /// When only excludes are desired, this is the most efficient way to obtain them. Otherwise use
122 /// [`Worktree::attributes()`][crate::Worktree::attributes()] for accessing both attributes and excludes.123 /// [`Worktree::attributes()`][crate::Worktree::attributes()] for accessing both attributes and excludes.
123 pub fn excludes(&self, overrides: Option<gix_ignore::Search>) -> Result<gix_worktree::Cache, Error> {124 pub fn excludes(&self, overrides: Option<gix_ignore::Search>) -> Result<gix_worktree::Stack, Error> {
124 let index = self.index()?;125 let index = self.index()?;
125 Ok(self.parent.excludes(126 Ok(self.parent.excludes(
126 &index,127 &index,
127 overrides,128 overrides,
128 gix_worktree::cache::state::ignore::Source::WorktreeThenIdMappingIfNotSkipped,129 gix_worktree::stack::state::ignore::Source::WorktreeThenIdMappingIfNotSkipped,
129 )?)130 )?)
130 }131 }
131 }132 }
@@ -150,23 +151,23 @@ pub mod attributes { · 18 unmodified lines
150 ///151 ///
151 /// * `$XDG_CONFIG_HOME/…/ignore|attributes` if `core.excludesFile|attributesFile` is *not* set, otherwise use the configured file.152 /// * `$XDG_CONFIG_HOME/…/ignore|attributes` if `core.excludesFile|attributesFile` is *not* set, otherwise use the configured file.
152 /// * `$GIT_DIR/info/exclude|attributes` if present.153 /// * `$GIT_DIR/info/exclude|attributes` if present.
153 pub fn attributes(&self, overrides: Option<gix_ignore::Search>) -> Result<gix_worktree::Cache, Error> {154 pub fn attributes(&self, overrides: Option<gix_ignore::Search>) -> Result<gix_worktree::Stack, Error> {
154 let index = self.index()?;155 let index = self.index()?;
155 Ok(self.parent.attributes(156 Ok(self.parent.attributes(
156 &index,157 &index,
157 gix_worktree::cache::state::attributes::Source::WorktreeThenIdMapping,158 gix_worktree::stack::state::attributes::Source::WorktreeThenIdMapping,
158 gix_worktree::cache::state::ignore::Source::WorktreeThenIdMappingIfNotSkipped,159 gix_worktree::stack::state::ignore::Source::WorktreeThenIdMappingIfNotSkipped,
159 overrides,160 overrides,
160 )?)161 )?)
161 }162 }
162 163
163 /// Like [attributes()][Self::attributes()], but without access to exclude/ignore information.164 /// Like [attributes()][Self::attributes()], but without access to exclude/ignore information.
164 pub fn attributes_only(&self) -> Result<gix_worktree::Cache, Error> {165 pub fn attributes_only(&self) -> Result<gix_worktree::Stack, Error> {
165 let index = self.index()?;166 let index = self.index()?;
166 self.parent167 self.parent
167 .attributes_only(168 .attributes_only(
168 &index,169 &index,
169 gix_worktree::cache::state::attributes::Source::WorktreeThenIdMapping,170 gix_worktree::stack::state::attributes::Source::WorktreeThenIdMapping,
170 )171 )
171 .map_err(|err| Error::CreateCache(err.into()))172 .map_err(|err| Error::CreateCache(err.into()))
172 }173 }
justfile+8−3
@@ -99,6 +99,7 @@ check: · 98 unmodified lines
99 cargo check -p gix-config-value99 cargo check -p gix-config-value
100 cargo check -p gix-config --all-features100 cargo check -p gix-config --all-features
101 cargo check -p gix-config101 cargo check -p gix-config
102 cargo check -p gix-diff --no-default-features
102 cargo check -p gix-transport103 cargo check -p gix-transport
103 cargo check -p gix-transport --features blocking-client104 cargo check -p gix-transport --features blocking-client
104 cargo check -p gix-transport --features async-client105 cargo check -p gix-transport --features async-client
@@ -134,14 +135,18 @@ unit-tests: · 29 unmodified lines
134 cargo test -p gix-archive --features tar135 cargo test -p gix-archive --features tar
135 cargo test -p gix-archive --features tar_gz136 cargo test -p gix-archive --features tar_gz
136 cargo test -p gix-archive --features zip137 cargo test -p gix-archive --features zip
137 cd gix-object; \138 cd gix-status; \
138 set -ex; \139 set -ex; \
139 cargo test; \140 cargo test; \
140 cargo test --features verbose-object-parsing-errors141 cargo test --features "internal-testing-gix-features-parallel"
141 cd gix-worktree; \142 cd gix-worktree-state; \
142 set -ex; \143 set -ex; \
143 cargo test; \144 cargo test; \
144 cargo test --features "internal-testing-gix-features-parallel"145 cargo test --features "internal-testing-gix-features-parallel"
146 cd gix-object; \
147 set -ex; \
148 cargo test; \
149 cargo test --features verbose-object-parsing-errors
145 cargo test -p gix-tempfile --features signals150 cargo test -p gix-tempfile --features signals
146 cargo test -p gix-tempfile151 cargo test -p gix-tempfile
147 cargo test -p gix-features152 cargo test -p gix-features