Skip to content

Commit 3c49400

Browse files
committed
Merge branch 'fetch-pack'
2 parents a0dd96b + ef9fa98 commit 3c49400

File tree

103 files changed

+3156
-1174
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

103 files changed

+3156
-1174
lines changed

Cargo.lock

Lines changed: 41 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,10 @@ env_logger = { version = "0.9.0", default-features = false }
9292
crosstermion = { version = "0.10.1", optional = true, default-features = false }
9393
futures-lite = { version = "1.12.0", optional = true, default-features = false, features = ["std"] }
9494

95+
# for progress
96+
owo-colors = "3.5.0"
97+
tabled = { version = "0.8.0", default-features = false }
98+
9599
document-features = { version = "0.2.0", optional = true }
96100

97101
[profile.dev.package]

DEVELOPMENT.md

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,21 @@
1818
* We `thiserror` generally.
1919
* Adhere to the [stability guide](https://github.com/Byron/gitoxide/blob/main/STABILITY.md)
2020

21+
## Configuration and overrides
22+
23+
As a general rule, respect and implement all applicable [git-config](https://git-scm.com/docs/git-config) by default, but allow the
24+
caller to set overrides. How overrides work depends on the goals of the particular API so it can be done on the main call path,
25+
forcing a choice, or more typically, as a side-lane where overrides can be done on demand.
26+
27+
Note that it should be possible to obtain the current configuration for modification by the user for selective overrides, either
28+
by calling methods or by obtaining a data structure that can be set as a whole using a `get -> modify -> set` cycle.
29+
30+
Note that without any of that, one should document that with `config_snapshot_mut()` any of the relevant configuration can be
31+
changed in memory before invoking a method in order to affect it.
32+
33+
Parameters which are not available in git or specific to `gitoxide` or the needs of the caller can be passed as parameters or via
34+
`Options` or `Context` structures as needed.
35+
2136
## General
2237

2338
* **async**

README.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,9 @@ Please see _'Development Status'_ for a listing of all crates and their capabili
2727
* Based on the [git-hours] algorithm.
2828
* See the [discussion][git-hours-discussion] for some performance data.
2929
* **the `gix` program** _(plumbing)_ - lower level commands for use in automation
30+
* **progress** - provide an overview of what works and what doesn't from the perspective of the git configuration.
31+
This is likely to change a lot over time depending on actual needs, but maybe useful for you to see
32+
if particular git-configuration is picked up and where it deviates.
3033
* **config** - list the complete git configuration in human-readable form and optionally filter sections by name.
3134
* **exclude**
3235
* [x] **query** - check if path specs are excluded via gits exclusion rules like `.gitignore`.

etc/check-package-size.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,6 @@ echo "in root: gitoxide CLI"
5757
(enter git-odb && indent cargo diet -n --package-size-limit 120KB)
5858
(enter git-protocol && indent cargo diet -n --package-size-limit 50KB)
5959
(enter git-packetline && indent cargo diet -n --package-size-limit 35KB)
60-
(enter git-repository && indent cargo diet -n --package-size-limit 175KB)
60+
(enter git-repository && indent cargo diet -n --package-size-limit 185KB)
6161
(enter git-transport && indent cargo diet -n --package-size-limit 55KB)
6262
(enter gitoxide-core && indent cargo diet -n --package-size-limit 90KB)

git-config/tests/file/init/from_paths/includes/conditional/onbranch.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -285,6 +285,7 @@ value = branch-override-by-include
285285
deref: false,
286286
}),
287287
git_repository::lock::acquire::Fail::Immediately,
288+
git_repository::lock::acquire::Fail::Immediately,
288289
)?
289290
.commit(repo.committer_or_default())?;
290291

git-pack/src/bundle/write/error.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,9 @@ use std::io;
22

33
use git_tempfile::handle::Writable;
44

5+
/// The error returned by [`Bundle::write_to_directory()`][crate::Bundle::write_to_directory()]
56
#[derive(thiserror::Error, Debug)]
7+
#[allow(missing_docs)]
68
pub enum Error {
79
#[error("An IO error occurred when reading the pack or creating a temporary file")]
810
Io(#[from] io::Error),

git-pack/src/bundle/write/mod.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ use git_tempfile::{handle::Writable, AutoRemove, ContainingDirectory};
1010
use crate::data;
1111

1212
mod error;
13-
use error::Error;
13+
pub use error::Error;
1414

1515
mod types;
1616
use types::{LockWriter, PassThrough};
@@ -228,7 +228,7 @@ impl crate::Bundle {
228228
Options {
229229
thread_limit,
230230
iteration_mode: _,
231-
index_kind,
231+
index_version: index_kind,
232232
object_hash,
233233
}: Options,
234234
data_file: Arc<parking_lot::Mutex<git_tempfile::Handle<Writable>>>,

git-pack/src/bundle/write/types.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ pub struct Options {
1111
/// Determine how much processing to spend on protecting against corruption or recovering from errors.
1212
pub iteration_mode: crate::data::input::Mode,
1313
/// The version of pack index to write, should be [`crate::index::Version::default()`]
14-
pub index_kind: crate::index::Version,
14+
pub index_version: crate::index::Version,
1515
/// The kind of hash to use when writing the bundle.
1616
pub object_hash: git_hash::Kind,
1717
}
@@ -22,7 +22,7 @@ impl Default for Options {
2222
Options {
2323
thread_limit: None,
2424
iteration_mode: crate::data::input::Mode::Verify,
25-
index_kind: Default::default(),
25+
index_version: Default::default(),
2626
object_hash: Default::default(),
2727
}
2828
}

git-pack/src/index/write/error.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ pub enum Error {
1414
IteratorInvariantNoRefDelta,
1515
#[error("The iterator failed to set a trailing hash over all prior pack entries in the last provided entry")]
1616
IteratorInvariantTrailer,
17-
#[error("Did not encounter a single base")]
17+
#[error("Did not encounter a single base - refusing to write empty pack.")]
1818
IteratorInvariantBasesPresent,
1919
#[error("Only u32::MAX objects can be stored in a pack, found {0}")]
2020
IteratorInvariantTooManyObjects(usize),

git-pack/src/index/write/mod.rs

Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ pub(crate) struct TreeEntry {
1818
#[cfg_attr(feature = "serde1", derive(serde::Serialize, serde::Deserialize))]
1919
pub struct Outcome {
2020
/// The version of the verified index
21-
pub index_kind: crate::index::Version,
21+
pub index_version: crate::index::Version,
2222
/// The verified checksum of the verified index
2323
pub index_hash: git_hash::ObjectId,
2424

@@ -171,7 +171,7 @@ impl crate::index::File {
171171
modify_base(data, entry, bytes, kind.hash());
172172
Ok::<_, Error>(())
173173
},
174-
crate::cache::delta::traverse::Options {
174+
traverse::Options {
175175
object_progress: root_progress.add_child("Resolving"),
176176
size_progress: root_progress.add_child("Decoding"),
177177
thread_limit,
@@ -207,20 +207,15 @@ impl crate::index::File {
207207
progress::MessageLevel::Success,
208208
);
209209
Ok(Outcome {
210-
index_kind: kind,
210+
index_version: kind,
211211
index_hash,
212212
data_hash: pack_hash,
213213
num_objects,
214214
})
215215
}
216216
}
217217

218-
fn modify_base(
219-
entry: &mut crate::index::write::TreeEntry,
220-
pack_entry: &crate::data::Entry,
221-
decompressed: &[u8],
222-
hash: git_hash::Kind,
223-
) {
218+
fn modify_base(entry: &mut TreeEntry, pack_entry: &crate::data::Entry, decompressed: &[u8], hash: git_hash::Kind) {
224219
fn compute_hash(kind: git_object::Kind, bytes: &[u8], object_hash: git_hash::Kind) -> git_hash::ObjectId {
225220
let mut hasher = git_features::hash::hasher(object_hash);
226221
hasher.update(&git_object::encode::loose_header(kind, bytes.len()));

git-pack/tests/pack/bundle.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,7 @@ mod write_to_directory {
9090
fn expected_outcome() -> Result<pack::bundle::write::Outcome, Box<dyn std::error::Error>> {
9191
Ok(pack::bundle::write::Outcome {
9292
index: pack::index::write::Outcome {
93-
index_kind: pack::index::Version::V2,
93+
index_version: pack::index::Version::V2,
9494
index_hash: git_hash::ObjectId::from_hex(b"544a7204a55f6e9cacccf8f6e191ea8f83575de3")?,
9595
data_hash: git_hash::ObjectId::from_hex(b"0f3ea84cd1bba10c2a03d736a460635082833e59")?,
9696
num_objects: 42,
@@ -156,7 +156,7 @@ mod write_to_directory {
156156
pack::bundle::write::Options {
157157
thread_limit: None,
158158
iteration_mode: pack::data::input::Mode::Verify,
159-
index_kind: pack::index::Version::V2,
159+
index_version: pack::index::Version::V2,
160160
object_hash: git_hash::Kind::Sha1,
161161
},
162162
)

git-pack/tests/pack/data/output/count_and_entries.rs

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -321,6 +321,21 @@ fn traversals() -> crate::Result {
321321
Ok(())
322322
}
323323

324+
#[test]
325+
fn empty_pack_is_not_allowed() {
326+
assert_eq!(
327+
write_and_verify(
328+
db(DbKind::DeterministicGeneratedContent).unwrap(),
329+
vec![],
330+
hex_to_id("029d08823bd8a8eab510ad6ac75c823cfd3ed31e"),
331+
None,
332+
)
333+
.unwrap_err()
334+
.to_string(),
335+
"Did not encounter a single base - refusing to write empty pack."
336+
);
337+
}
338+
324339
fn write_and_verify(
325340
db: git_odb::HandleArc,
326341
entries: Vec<output::Entry>,

git-pack/tests/pack/index.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -205,7 +205,7 @@ mod version {
205205
outcome.num_objects, num_objects,
206206
"it wrote the entire iterator worth of entries"
207207
);
208-
assert_eq!(outcome.index_kind, desired_kind);
208+
assert_eq!(outcome.index_version, desired_kind);
209209
assert_eq!(
210210
outcome.index_hash,
211211
git_hash::ObjectId::from(&expected[end_of_pack_hash..end_of_index_hash])

git-protocol/src/fetch/arguments/blocking_io.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,8 @@ use git_transport::{client, client::TransportV2Ext};
55
use crate::fetch::{Arguments, Command};
66

77
impl Arguments {
8-
pub(crate) fn send<'a, T: client::Transport + 'a>(
8+
/// Send fetch arguments to the server, and indicate this is the end of negotiations only if `add_done_argument` is present.
9+
pub fn send<'a, T: client::Transport + 'a>(
910
&mut self,
1011
transport: &'a mut T,
1112
add_done_argument: bool,

git-protocol/src/fetch/arguments/mod.rs

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ use std::fmt;
33
use bstr::{BStr, BString, ByteVec};
44

55
/// The arguments passed to a server command.
6+
#[derive(Debug)]
67
pub struct Arguments {
78
/// The active features/capabilities of the fetch invocation
89
#[cfg(any(feature = "async-client", feature = "blocking-client"))]
@@ -24,6 +25,13 @@ pub struct Arguments {
2425
}
2526

2627
impl Arguments {
28+
/// Return true if there is no argument at all.
29+
///
30+
/// This can happen if callers assure that they won't add 'wants' if their 'have' is the same, i.e. if the remote has nothing
31+
/// new for them.
32+
pub fn is_empty(&self) -> bool {
33+
self.args.is_empty()
34+
}
2735
/// Return true if ref filters is supported.
2836
pub fn can_use_filter(&self) -> bool {
2937
self.filter
@@ -125,8 +133,10 @@ impl Arguments {
125133
fn prefixed(&mut self, prefix: &str, value: impl fmt::Display) {
126134
self.args.push(format!("{}{}", prefix, value).into());
127135
}
136+
/// Create a new instance to help setting up arguments to send to the server as part of a `fetch` operation
137+
/// for which `features` are the available and configured features to use.
128138
#[cfg(any(feature = "async-client", feature = "blocking-client"))]
129-
pub(crate) fn new(version: git_transport::Protocol, features: Vec<crate::fetch::command::Feature>) -> Self {
139+
pub fn new(version: git_transport::Protocol, features: Vec<crate::fetch::command::Feature>) -> Self {
130140
use crate::fetch::Command;
131141
let has = |name: &str| features.iter().any(|f| f.0 == name);
132142
let filter = has("filter");

git-protocol/src/fetch/command.rs

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -50,9 +50,12 @@ mod with_io {
5050
"filter ", // filter-spec
5151
// ref-in-want feature
5252
"want-ref ", // ref path
53+
// sideband-all feature
5354
"sideband-all",
5455
// packfile-uris feature
5556
"packfile-uris ", // protocols
57+
// wait-for-done feature
58+
"wait-for-done",
5659
],
5760
}
5861
}
@@ -79,9 +82,14 @@ mod with_io {
7982
"no-done",
8083
"filter",
8184
],
82-
git_transport::Protocol::V2 => {
83-
&["shallow", "filter", "ref-in-want", "sideband-all", "packfile-uris"]
84-
}
85+
git_transport::Protocol::V2 => &[
86+
"shallow",
87+
"filter",
88+
"ref-in-want",
89+
"sideband-all",
90+
"packfile-uris",
91+
"wait-for-done",
92+
],
8593
},
8694
}
8795
}
@@ -104,7 +112,9 @@ mod with_io {
104112
}
105113
}
106114

107-
pub(crate) fn default_features(
115+
/// Turns on all modern features for V1 and all supported features for V2, returning them as a vector of features.
116+
/// Note that this is the basis for any fetch operation as these features fulfil basic requirements and reasonably up-to-date servers.
117+
pub fn default_features(
108118
&self,
109119
version: git_transport::Protocol,
110120
server_capabilities: &Capabilities,

git-protocol/src/fetch/handshake.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ use git_transport::client::Capabilities;
33
use crate::fetch::Ref;
44

55
/// The result of the [`handshake()`][super::handshake()] function.
6-
#[derive(Debug, Clone)]
6+
#[derive(Default, Debug, Clone)]
77
#[cfg_attr(feature = "serde1", derive(serde::Serialize, serde::Deserialize))]
88
pub struct Outcome {
99
/// The protocol version the server responded with. It might have downgraded the desired version.

git-protocol/src/fetch/refs/function.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,13 +10,13 @@ use super::Error;
1010
use crate::fetch::{indicate_end_of_interaction, refs::from_v2_refs, Command, LsRefsAction, Ref};
1111

1212
/// Invoke an ls-refs command on `transport` (assuming `protocol_version` 2 or panic), which requires a prior handshake that yielded
13-
/// server `capabilities`. `prepare_ls_refs(arguments, features)` can be used to alter the _ls-refs_. `progress` is used to provide feedback.
13+
/// server `capabilities`. `prepare_ls_refs(capabilities, arguments, features)` can be used to alter the _ls-refs_. `progress` is used to provide feedback.
1414
#[maybe_async]
1515
pub async fn refs(
1616
mut transport: impl Transport,
1717
protocol_version: Protocol,
1818
capabilities: &Capabilities,
19-
mut prepare_ls_refs: impl FnMut(
19+
prepare_ls_refs: impl FnOnce(
2020
&Capabilities,
2121
&mut Vec<BString>,
2222
&mut Vec<(&str, Option<&str>)>,

0 commit comments

Comments
 (0)