Skip to content

Commit 76c99f3

Browse files
committed
Merge branch 'gix-clone-improvements'
2 parents 41fc2bb + 6ba799c commit 76c99f3

File tree

3 files changed

+31
-7
lines changed
  • git-transport/src/client/blocking_io
  • gitoxide-core/src/repository
  • src/plumbing/options

3 files changed

+31
-7
lines changed

Diff for: git-transport/src/client/blocking_io/file.rs

+18-2
Original file line numberDiff line numberDiff line change
@@ -138,7 +138,23 @@ fn supervise_stderr(
138138
Some(err) => Err(err),
139139
None => match res {
140140
Ok(n) if n == wanted => Ok(n),
141-
Ok(n) => self.recv.recv().ok().map(Err).unwrap_or(Ok(n)),
141+
Ok(n) => {
142+
// TODO: fix this
143+
// When parsing refs this seems to happen legitimately
144+
// (even though we read packet lines only and should always know exactly how much to read)
145+
// Maybe this still happens in `read_exact()` as sometimes we just don't get enough bytes
146+
// despite knowing how many.
147+
// To prevent deadlock, we have to set a timeout which slows down legitimate parts of the protocol.
148+
// This code was specifically written to make the `cargo` test-suite pass, and we can reduce
149+
// the timeouts even more once there is a native ssh transport that is used by `cargo`, it will
150+
// be able to handle these properly.
151+
// Alternatively, one could implement something like `read2` to avoid blocking on stderr entirely.
152+
self.recv
153+
.recv_timeout(std::time::Duration::from_millis(5))
154+
.ok()
155+
.map(Err)
156+
.unwrap_or(Ok(n))
157+
}
142158
Err(err) => Err(self.recv.recv().ok().unwrap_or(err)),
143159
},
144160
}
@@ -153,7 +169,7 @@ fn supervise_stderr(
153169

154170
let (send, recv) = std::sync::mpsc::sync_channel(1);
155171
std::thread::Builder::new()
156-
.name("supervise ssh".into())
172+
.name("supervise ssh stderr".into())
157173
.stack_size(128 * 1024)
158174
.spawn(move || -> std::io::Result<()> {
159175
let mut process_stderr = std::io::stderr();

Diff for: gitoxide-core/src/repository/clone.rs

+12-4
Original file line numberDiff line numberDiff line change
@@ -12,16 +12,16 @@ pub const PROGRESS_RANGE: std::ops::RangeInclusive<u8> = 1..=3;
1212
pub(crate) mod function {
1313
use std::ffi::OsStr;
1414

15-
use anyhow::bail;
15+
use anyhow::{bail, Context};
1616
use git_repository as git;
1717
use git_repository::{bstr::BString, remote::fetch::Status, Progress};
1818

1919
use super::Options;
2020
use crate::{repository::fetch::function::print_updates, OutputFormat};
2121

2222
pub fn clone<P>(
23-
remote: impl AsRef<OsStr>,
24-
directory: impl AsRef<std::path::Path>,
23+
url: impl AsRef<OsStr>,
24+
directory: Option<impl Into<std::path::PathBuf>>,
2525
overrides: Vec<BString>,
2626
mut progress: P,
2727
mut out: impl std::io::Write,
@@ -41,8 +41,16 @@ pub(crate) mod function {
4141
bail!("JSON output isn't yet supported for fetching.");
4242
}
4343

44+
let url: git::Url = url.as_ref().try_into()?;
45+
let directory = directory.map(|dir| Ok(dir.into())).unwrap_or_else(|| {
46+
git::path::from_bstr(url.path.as_ref())
47+
.as_ref()
48+
.file_stem()
49+
.map(Into::into)
50+
.context("Filename extraction failed - path too short")
51+
})?;
4452
let mut prepare = git::clone::PrepareFetch::new(
45-
remote.as_ref(),
53+
url,
4654
directory,
4755
bare.then(|| git::create::Kind::Bare)
4856
.unwrap_or(git::create::Kind::WithWorktree),

Diff for: src/plumbing/options/mod.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -182,7 +182,7 @@ pub mod clone {
182182
pub remote: OsString,
183183

184184
/// The directory to initialize with the new repository and to which all data should be written.
185-
pub directory: PathBuf,
185+
pub directory: Option<PathBuf>,
186186
}
187187
}
188188

0 commit comments

Comments
 (0)