Skip to content

Commit d7f62b4

Browse files
committed
fix: support keepalive packets. (#450)
Keepalive packets are side-band only empty datalines that should just be ignored. This is now happening, allowing longer git operations to work as they will send keepalive packets every 5 seconds, and previously we would choke on it. Note that empty datalines are never send otherwise, making it a previously unused marker that can safely be skipped.
1 parent e616174 commit d7f62b4

File tree

6 files changed

+49
-26
lines changed

6 files changed

+49
-26
lines changed

git-packetline/src/read/sidebands/async_io.rs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -238,7 +238,12 @@ where
238238
.map_err(|err| io::Error::new(io::ErrorKind::Other, err))?;
239239
const ENCODED_BAND: usize = 1;
240240
match band {
241-
BandRef::Data(d) => break (U16_HEX_BYTES + ENCODED_BAND, d.len()),
241+
BandRef::Data(d) => {
242+
if d.is_empty() {
243+
continue;
244+
}
245+
break (U16_HEX_BYTES + ENCODED_BAND, d.len());
246+
}
242247
BandRef::Progress(d) => {
243248
let text = TextRef::from(d).0;
244249
handle_progress(false, text);

git-packetline/src/read/sidebands/blocking_io.rs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,12 @@ where
113113
.map_err(|err| io::Error::new(io::ErrorKind::Other, err))?;
114114
const ENCODED_BAND: usize = 1;
115115
match band {
116-
BandRef::Data(d) => break (U16_HEX_BYTES + ENCODED_BAND, d.len()),
116+
BandRef::Data(d) => {
117+
if d.is_empty() {
118+
continue;
119+
}
120+
break (U16_HEX_BYTES + ENCODED_BAND, d.len());
121+
}
117122
BandRef::Progress(d) => {
118123
let text = TextRef::from(d).0;
119124
handle_progress(false, text);

git-protocol/tests/fetch/response.rs

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -124,14 +124,21 @@ mod v2 {
124124

125125
#[maybe_async::test(feature = "blocking-client", async(feature = "async-client", async_std::test))]
126126
async fn clone() -> crate::Result {
127-
let mut provider = mock_reader("v2/clone-only.response");
128-
let mut reader = provider.as_read_without_sidebands();
129-
let r = fetch::Response::from_line_reader(Protocol::V2, &mut reader).await?;
130-
assert!(r.acknowledgements().is_empty(), "it should go straight to the packfile");
131-
assert!(r.has_pack());
132-
let mut buf = Vec::new();
133-
let bytes_read = reader.read_to_end(&mut buf).await?;
134-
assert_eq!(bytes_read, 1089, "should be able to read the whole pack");
127+
for keepalive in [false, true] {
128+
let fixture = format!(
129+
"v2/clone-only{}.response",
130+
keepalive.then(|| "-with-keepalive").unwrap_or_default()
131+
);
132+
let mut provider = mock_reader(&fixture);
133+
let mut reader = provider.as_read_without_sidebands();
134+
let r = fetch::Response::from_line_reader(Protocol::V2, &mut reader).await?;
135+
assert!(r.acknowledgements().is_empty(), "it should go straight to the packfile");
136+
assert!(r.has_pack());
137+
reader.set_progress_handler(Some(Box::new(|_is_err, _text| ())));
138+
let mut buf = Vec::new();
139+
let bytes_read = reader.read_to_end(&mut buf).await?;
140+
assert_eq!(bytes_read, 876, "should be able to read the whole pack");
141+
}
135142
Ok(())
136143
}
137144

git-protocol/tests/fetch/v1.rs

Lines changed: 22 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -7,22 +7,28 @@ use crate::fetch::{helper_unused, oid, transport, CloneDelegate, LsRemoteDelegat
77

88
#[maybe_async::test(feature = "blocking-client", async(feature = "async-client", async_std::test))]
99
async fn clone() -> crate::Result {
10-
let out = Vec::new();
11-
let mut dlg = CloneDelegate::default();
12-
git_protocol::fetch(
13-
transport(
14-
out,
15-
"v1/clone.response",
16-
Protocol::V1,
17-
git_transport::client::git::ConnectMode::Daemon,
18-
),
19-
&mut dlg,
20-
helper_unused,
21-
progress::Discard,
22-
FetchConnection::TerminateOnSuccessfulCompletion,
23-
)
24-
.await?;
25-
assert_eq!(dlg.pack_bytes, 876, "It be able to read pack bytes");
10+
for with_keepalive in [false, true] {
11+
let out = Vec::new();
12+
let mut dlg = CloneDelegate::default();
13+
let fixture = format!(
14+
"v1/clone{}.response",
15+
with_keepalive.then(|| "-with-keepalive").unwrap_or_default()
16+
);
17+
git_protocol::fetch(
18+
transport(
19+
out,
20+
&fixture,
21+
Protocol::V1,
22+
git_transport::client::git::ConnectMode::Daemon,
23+
),
24+
&mut dlg,
25+
helper_unused,
26+
progress::Discard,
27+
FetchConnection::TerminateOnSuccessfulCompletion,
28+
)
29+
.await?;
30+
assert_eq!(dlg.pack_bytes, 876, "{}: It be able to read pack bytes", fixture);
31+
}
2632
Ok(())
2733
}
2834

Binary file not shown.
Binary file not shown.

0 commit comments

Comments
 (0)