Skip to content

Commit cc0f506

Browse files
committed
Merge branch 'various-fixes'
2 parents 531dd19 + a22621d commit cc0f506

File tree

20 files changed

+377
-266
lines changed

20 files changed

+377
-266
lines changed

Diff for: Cargo.lock

+170-202
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Diff for: Makefile

+1
Original file line numberDiff line numberDiff line change
@@ -170,6 +170,7 @@ unit-tests: ## run all unit tests
170170
&& cargo test --features blocking-network-client \
171171
&& cargo test --features regex
172172
cd gitoxide-core && cargo test --lib
173+
# cd gix && cargo test --features async-network-client-async-std \ not being run as it's flaky even locally
173174

174175
nextest: ## run tests with `cargo nextest` (all unit-tests, no doc-tests, faster)
175176
cargo nextest run --all

Diff for: crate-status.md

+3-1
Original file line numberDiff line numberDiff line change
@@ -638,11 +638,13 @@ See its [README.md](https://github.com/Byron/gitoxide/blob/main/gix-lock/README.
638638
- [ ] respect `branch.<name>.merge` in the returned remote.
639639
* **remotes**
640640
* [x] clone
641-
* [ ] shallow
641+
* [x] shallow
642642
* [ ] include-tags when shallow is used (needs separate fetch)
643643
* [ ] prune non-existing shallow commits
644644
* [ ] [bundles](https://git-scm.com/docs/git-bundle)
645645
* [x] fetch
646+
* [x] shallow (remains shallow, options to adjust shallow boundary)
647+
* [ ] a way to auto-explode small packs to avoid them to pile up
646648
* [ ] 'ref-in-want'
647649
* [ ] standard negotiation algorithms (right now we only have a 'naive' one)
648650
* [ ] push

Diff for: gix-packetline/src/read/async_io.rs

+7-3
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ use bstr::ByteSlice;
44
use futures_io::AsyncRead;
55
use futures_lite::AsyncReadExt;
66

7+
use crate::read::ProgressAction;
78
use crate::{
89
decode,
910
read::{ExhaustiveOutcome, WithSidebands},
@@ -150,7 +151,8 @@ where
150151
/// Same as [`as_read_with_sidebands(…)`][StreamingPeekableIter::as_read_with_sidebands()], but for channels without side band support.
151152
///
152153
/// Due to the preconfigured function type this method can be called without 'turbofish'.
153-
pub fn as_read(&mut self) -> WithSidebands<'_, T, fn(bool, &[u8])> {
154+
#[allow(clippy::type_complexity)]
155+
pub fn as_read(&mut self) -> WithSidebands<'_, T, fn(bool, &[u8]) -> ProgressAction> {
154156
WithSidebands::new(self)
155157
}
156158

@@ -161,7 +163,7 @@ where
161163
/// being true in case the `text` is to be interpreted as error.
162164
///
163165
/// _Please note_ that side bands need to be negotiated with the server.
164-
pub fn as_read_with_sidebands<F: FnMut(bool, &[u8]) + Unpin>(
166+
pub fn as_read_with_sidebands<F: FnMut(bool, &[u8]) -> ProgressAction + Unpin>(
165167
&mut self,
166168
handle_progress: F,
167169
) -> WithSidebands<'_, T, F> {
@@ -172,7 +174,9 @@ where
172174
///
173175
/// The type parameter `F` needs to be configured for this method to be callable using the 'turbofish' operator.
174176
/// Use [`as_read()`][StreamingPeekableIter::as_read()].
175-
pub fn as_read_without_sidebands<F: FnMut(bool, &[u8]) + Unpin>(&mut self) -> WithSidebands<'_, T, F> {
177+
pub fn as_read_without_sidebands<F: FnMut(bool, &[u8]) -> ProgressAction + Unpin>(
178+
&mut self,
179+
) -> WithSidebands<'_, T, F> {
176180
WithSidebands::without_progress_handler(self)
177181
}
178182
}

Diff for: gix-packetline/src/read/blocking_io.rs

+8-3
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ use std::io;
22

33
use bstr::ByteSlice;
44

5+
use crate::read::ProgressAction;
56
use crate::{
67
decode,
78
read::{ExhaustiveOutcome, WithSidebands},
@@ -146,22 +147,26 @@ where
146147
/// being true in case the `text` is to be interpreted as error.
147148
///
148149
/// _Please note_ that side bands need to be negotiated with the server.
149-
pub fn as_read_with_sidebands<F: FnMut(bool, &[u8])>(&mut self, handle_progress: F) -> WithSidebands<'_, T, F> {
150+
pub fn as_read_with_sidebands<F: FnMut(bool, &[u8]) -> ProgressAction>(
151+
&mut self,
152+
handle_progress: F,
153+
) -> WithSidebands<'_, T, F> {
150154
WithSidebands::with_progress_handler(self, handle_progress)
151155
}
152156

153157
/// Same as [`as_read_with_sidebands(…)`][StreamingPeekableIter::as_read_with_sidebands()], but for channels without side band support.
154158
///
155159
/// The type parameter `F` needs to be configured for this method to be callable using the 'turbofish' operator.
156160
/// Use [`as_read()`][StreamingPeekableIter::as_read()].
157-
pub fn as_read_without_sidebands<F: FnMut(bool, &[u8])>(&mut self) -> WithSidebands<'_, T, F> {
161+
pub fn as_read_without_sidebands<F: FnMut(bool, &[u8]) -> ProgressAction>(&mut self) -> WithSidebands<'_, T, F> {
158162
WithSidebands::without_progress_handler(self)
159163
}
160164

161165
/// Same as [`as_read_with_sidebands(…)`][StreamingPeekableIter::as_read_with_sidebands()], but for channels without side band support.
162166
///
163167
/// Due to the preconfigured function type this method can be called without 'turbofish'.
164-
pub fn as_read(&mut self) -> WithSidebands<'_, T, fn(bool, &[u8])> {
168+
#[allow(clippy::type_complexity)]
169+
pub fn as_read(&mut self) -> WithSidebands<'_, T, fn(bool, &[u8]) -> ProgressAction> {
165170
WithSidebands::new(self)
166171
}
167172
}

Diff for: gix-packetline/src/read/mod.rs

+9
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,15 @@
22
use crate::MAX_LINE_LEN;
33
use crate::{PacketLineRef, StreamingPeekableIter, U16_HEX_BYTES};
44

5+
/// Allow the read-progress handler to determine how to continue.
6+
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
7+
pub enum ProgressAction {
8+
/// Continue reading the next progress if available.
9+
Continue,
10+
/// Abort all IO even if more would be available, claiming the operation was interrupted.
11+
Interrupt,
12+
}
13+
514
#[cfg(any(feature = "blocking-io", feature = "async-io"))]
615
type ExhaustiveOutcome<'a> = (
716
bool, // is_done

Diff for: gix-packetline/src/read/sidebands/async_io.rs

+25-8
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ use std::{
77
use futures_io::{AsyncBufRead, AsyncRead};
88
use futures_lite::ready;
99

10+
use crate::read::ProgressAction;
1011
use crate::{decode, BandRef, PacketLineRef, StreamingPeekableIter, TextRef, U16_HEX_BYTES};
1112

1213
type ReadLineResult<'a> = Option<std::io::Result<Result<PacketLineRef<'a>, decode::Error>>>;
@@ -37,7 +38,7 @@ where
3738
}
3839
}
3940

40-
impl<'a, T> WithSidebands<'a, T, fn(bool, &[u8])>
41+
impl<'a, T> WithSidebands<'a, T, fn(bool, &[u8]) -> ProgressAction>
4142
where
4243
T: AsyncRead,
4344
{
@@ -93,7 +94,7 @@ mod tests {
9394
impl<'a, T, F> WithSidebands<'a, T, F>
9495
where
9596
T: AsyncRead + Unpin,
96-
F: FnMut(bool, &[u8]) + Unpin,
97+
F: FnMut(bool, &[u8]) -> ProgressAction + Unpin,
9798
{
9899
/// Create a new instance with the given `parent` provider and the `handle_progress` function.
99100
///
@@ -201,7 +202,7 @@ pub struct ReadDataLineFuture<'a, 'b, T: AsyncRead, F> {
201202
impl<'a, 'b, T, F> Future for ReadDataLineFuture<'a, 'b, T, F>
202203
where
203204
T: AsyncRead + Unpin,
204-
F: FnMut(bool, &[u8]) + Unpin,
205+
F: FnMut(bool, &[u8]) -> ProgressAction + Unpin,
205206
{
206207
type Output = std::io::Result<usize>;
207208

@@ -228,7 +229,7 @@ pub struct ReadLineFuture<'a, 'b, T: AsyncRead, F> {
228229
impl<'a, 'b, T, F> Future for ReadLineFuture<'a, 'b, T, F>
229230
where
230231
T: AsyncRead + Unpin,
231-
F: FnMut(bool, &[u8]) + Unpin,
232+
F: FnMut(bool, &[u8]) -> ProgressAction + Unpin,
232233
{
233234
type Output = std::io::Result<usize>;
234235

@@ -251,7 +252,7 @@ where
251252
impl<'a, T, F> AsyncBufRead for WithSidebands<'a, T, F>
252253
where
253254
T: AsyncRead + Unpin,
254-
F: FnMut(bool, &[u8]) + Unpin,
255+
F: FnMut(bool, &[u8]) -> ProgressAction + Unpin,
255256
{
256257
fn poll_fill_buf(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<std::io::Result<&[u8]>> {
257258
use std::io;
@@ -310,11 +311,27 @@ where
310311
}
311312
BandRef::Progress(d) => {
312313
let text = TextRef::from(d).0;
313-
handle_progress(false, text);
314+
match handle_progress(false, text) {
315+
ProgressAction::Continue => {}
316+
ProgressAction::Interrupt => {
317+
return Poll::Ready(Err(io::Error::new(
318+
std::io::ErrorKind::Other,
319+
"interrupted by user",
320+
)))
321+
}
322+
};
314323
}
315324
BandRef::Error(d) => {
316325
let text = TextRef::from(d).0;
317-
handle_progress(true, text);
326+
match handle_progress(true, text) {
327+
ProgressAction::Continue => {}
328+
ProgressAction::Interrupt => {
329+
return Poll::Ready(Err(io::Error::new(
330+
io::ErrorKind::Other,
331+
"interrupted by user",
332+
)))
333+
}
334+
};
318335
}
319336
};
320337
}
@@ -353,7 +370,7 @@ where
353370
impl<'a, T, F> AsyncRead for WithSidebands<'a, T, F>
354371
where
355372
T: AsyncRead + Unpin,
356-
F: FnMut(bool, &[u8]) + Unpin,
373+
F: FnMut(bool, &[u8]) -> ProgressAction + Unpin,
357374
{
358375
fn poll_read(mut self: Pin<&mut Self>, cx: &mut Context<'_>, buf: &mut [u8]) -> Poll<std::io::Result<usize>> {
359376
let nread = {

Diff for: gix-packetline/src/read/sidebands/blocking_io.rs

+23-6
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
use std::{io, io::BufRead};
22

3+
use crate::read::ProgressAction;
34
use crate::{BandRef, PacketLineRef, StreamingPeekableIter, TextRef, U16_HEX_BYTES};
45

56
/// An implementor of [`BufRead`][io::BufRead] yielding packet lines on each call to [`read_line()`][io::BufRead::read_line()].
@@ -24,7 +25,7 @@ where
2425
}
2526
}
2627

27-
impl<'a, T> WithSidebands<'a, T, fn(bool, &[u8])>
28+
impl<'a, T> WithSidebands<'a, T, fn(bool, &[u8]) -> ProgressAction>
2829
where
2930
T: io::Read,
3031
{
@@ -42,7 +43,7 @@ where
4243
impl<'a, T, F> WithSidebands<'a, T, F>
4344
where
4445
T: io::Read,
45-
F: FnMut(bool, &[u8]),
46+
F: FnMut(bool, &[u8]) -> ProgressAction,
4647
{
4748
/// Create a new instance with the given `parent` provider and the `handle_progress` function.
4849
///
@@ -130,7 +131,7 @@ where
130131
impl<'a, T, F> BufRead for WithSidebands<'a, T, F>
131132
where
132133
T: io::Read,
133-
F: FnMut(bool, &[u8]),
134+
F: FnMut(bool, &[u8]) -> ProgressAction,
134135
{
135136
fn fill_buf(&mut self) -> io::Result<&[u8]> {
136137
if self.pos >= self.cap {
@@ -154,11 +155,27 @@ where
154155
}
155156
BandRef::Progress(d) => {
156157
let text = TextRef::from(d).0;
157-
handle_progress(false, text);
158+
match handle_progress(false, text) {
159+
ProgressAction::Continue => {}
160+
ProgressAction::Interrupt => {
161+
return Err(std::io::Error::new(
162+
std::io::ErrorKind::Other,
163+
"interrupted by user",
164+
))
165+
}
166+
};
158167
}
159168
BandRef::Error(d) => {
160169
let text = TextRef::from(d).0;
161-
handle_progress(true, text);
170+
match handle_progress(true, text) {
171+
ProgressAction::Continue => {}
172+
ProgressAction::Interrupt => {
173+
return Err(std::io::Error::new(
174+
std::io::ErrorKind::Other,
175+
"interrupted by user",
176+
))
177+
}
178+
};
162179
}
163180
};
164181
}
@@ -189,7 +206,7 @@ where
189206
impl<'a, T, F> io::Read for WithSidebands<'a, T, F>
190207
where
191208
T: io::Read,
192-
F: FnMut(bool, &[u8]),
209+
F: FnMut(bool, &[u8]) -> ProgressAction,
193210
{
194211
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
195212
let nread = {

Diff for: gix-packetline/tests/read/sideband.rs

+5-3
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ use bstr::{BString, ByteSlice};
55
#[cfg(all(not(feature = "blocking-io"), feature = "async-io"))]
66
use futures_lite::io::AsyncReadExt;
77
use gix_odb::pack;
8+
use gix_packetline::read::ProgressAction;
89
use gix_packetline::PacketLineRef;
910

1011
use crate::read::streaming_peek_iter::fixture_bytes;
@@ -51,9 +52,10 @@ async fn read_pack_with_progress_extraction() -> crate::Result {
5152
b"NAK".as_bstr()
5253
);
5354
let mut seen_texts = Vec::<BString>::new();
54-
let mut do_nothing = |is_err: bool, data: &[u8]| {
55+
let mut do_nothing = |is_err: bool, data: &[u8]| -> ProgressAction {
5556
assert!(!is_err);
5657
seen_texts.push(data.as_bstr().into());
58+
ProgressAction::Continue
5759
};
5860
let pack_read = rd.as_read_with_sidebands(&mut do_nothing);
5961
#[cfg(all(not(feature = "blocking-io"), feature = "async-io"))]
@@ -132,7 +134,7 @@ async fn read_line_trait_method_reads_one_packet_line_at_a_time() -> crate::Resu
132134

133135
drop(r);
134136

135-
let mut r = rd.as_read_with_sidebands(|_, _| ());
137+
let mut r = rd.as_read_with_sidebands(|_, _| ProgressAction::Continue);
136138
out.clear();
137139
r.read_line_to_string(&mut out).await?;
138140
assert_eq!(out, "&");
@@ -174,7 +176,7 @@ async fn readline_reads_one_packet_line_at_a_time() -> crate::Result {
174176

175177
drop(r);
176178

177-
let mut r = rd.as_read_with_sidebands(|_, _| ());
179+
let mut r = rd.as_read_with_sidebands(|_, _| ProgressAction::Continue);
178180
let line = r.read_data_line().await.unwrap()??.as_bstr().unwrap();
179181
assert_eq!(
180182
line.as_bstr(),

Diff for: gix-protocol/src/fetch_fn.rs

+4-1
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,8 @@ impl Default for FetchConnection {
4949
/// _Note_ that depending on the `delegate`, the actual action performed can be `ls-refs`, `clone` or `fetch`.
5050
#[allow(clippy::result_large_err)]
5151
#[maybe_async]
52+
// TODO: remove this without losing test coverage - we have the same but better in `gix` and it's
53+
// not really worth it to maintain the delegates here.
5254
pub async fn fetch<F, D, T, P>(
5355
mut transport: T,
5456
mut delegate: D,
@@ -162,7 +164,8 @@ where
162164
reader.set_progress_handler(Some(Box::new({
163165
let mut remote_progress = progress.add_child("remote");
164166
move |is_err: bool, data: &[u8]| {
165-
crate::RemoteProgress::translate_to_progress(is_err, data, &mut remote_progress)
167+
crate::RemoteProgress::translate_to_progress(is_err, data, &mut remote_progress);
168+
gix_transport::packetline::read::ProgressAction::Continue
166169
}
167170
}) as gix_transport::client::HandleProgress));
168171
}

Diff for: gix-protocol/tests/fetch/response.rs

+7-2
Original file line numberDiff line numberDiff line change
@@ -193,6 +193,7 @@ mod v2 {
193193

194194
#[cfg(feature = "async-client")]
195195
use futures_lite::io::AsyncReadExt;
196+
use gix_packetline::read::ProgressAction;
196197
use gix_protocol::fetch::{
197198
self,
198199
response::{Acknowledgement, ShallowUpdate},
@@ -213,7 +214,9 @@ mod v2 {
213214
let r = fetch::Response::from_line_reader(Protocol::V2, &mut reader).await?;
214215
assert!(r.acknowledgements().is_empty(), "it should go straight to the packfile");
215216
assert!(r.has_pack());
216-
reader.set_progress_handler(Some(Box::new(|_is_err, _text| ())));
217+
reader.set_progress_handler(Some(Box::new(|_is_err, _text| {
218+
gix_transport::packetline::read::ProgressAction::Continue
219+
})));
217220
let mut buf = Vec::new();
218221
let bytes_read = reader.read_to_end(&mut buf).await?;
219222
assert_eq!(bytes_read, 876, "should be able to read the whole pack");
@@ -295,6 +298,7 @@ mod v2 {
295298
let mut buf = Vec::new();
296299
reader.set_progress_handler(Some(Box::new(|is_err: bool, _data: &[u8]| {
297300
assert!(!is_err, "fixture does not have an error");
301+
ProgressAction::Continue
298302
}) as gix_transport::client::HandleProgress));
299303
let bytes_read = reader.read_to_end(&mut buf).await?;
300304
assert_eq!(bytes_read, 1643, "should be able to read the whole pack");
@@ -346,7 +350,8 @@ mod v2 {
346350
assert!(r.has_pack());
347351
let mut buf = Vec::new();
348352
reader.set_progress_handler(Some(Box::new(|a: bool, b: &[u8]| {
349-
gix_protocol::RemoteProgress::translate_to_progress(a, b, &mut gix_features::progress::Discard)
353+
gix_protocol::RemoteProgress::translate_to_progress(a, b, &mut gix_features::progress::Discard);
354+
ProgressAction::Continue
350355
}) as gix_transport::client::HandleProgress));
351356
let bytes_read = reader.read_to_end(&mut buf).await?;
352357
assert_eq!(bytes_read, 5360, "should be able to read the whole pack");

0 commit comments

Comments
 (0)