Skip to content

Commit

Permalink
fix(transport): fixes SSH clone from scp-like/relatives URLs
Browse files Browse the repository at this point in the history
    - Removes git-upload-pack extra parameters (rejected by both github and gitlab)
    - Removes the double user inclusion in URL
    - Properly handles relative paths in URL reconstruction on `connect()`
  • Loading branch information
noirbizarre committed Dec 23, 2022
1 parent 1058330 commit c62e5c7
Show file tree
Hide file tree
Showing 2 changed files with 23 additions and 11 deletions.
2 changes: 1 addition & 1 deletion git-transport/src/client/blocking_io/file.rs
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,7 @@ impl client::Transport for SpawnProcessOnDemand {
if self.ssh_program.is_some() {
cmd.arg(service.as_str());
}
cmd.arg("--strict").arg("--timeout=0").arg(self.path.to_os_str_lossy());
cmd.arg(self.path.to_os_str_lossy());

let mut child = cmd.spawn()?;
self.connection = Some(git::Connection::new_for_spawned_process(
Expand Down
32 changes: 22 additions & 10 deletions git-transport/src/client/blocking_io/ssh.rs
Original file line number Diff line number Diff line change
Expand Up @@ -56,16 +56,16 @@ pub fn connect(
_ => return Err(Error::UnsupportedSshCommand(ssh_cmd.into())),
};

let host = match user.as_ref() {
Some(user) => format!("{}@{}", user, host),
None => host.into(),
};

let path = git_url::expand_path::for_shell(path);
let url = git_url::Url::from_parts(
let url_parser = if path.to_string().starts_with('/') {
git_url::Url::from_parts
} else {
git_url::Url::from_parts_as_alternative_form
};
let url = url_parser(
git_url::Scheme::Ssh,
user.map(Into::into),
Some(host.clone()),
Some(host.to_string()),
port,
path.clone(),
)
Expand All @@ -82,7 +82,7 @@ pub fn connect(
None => blocking_io::file::SpawnProcessOnDemand::new_ssh(
url,
ssh_cmd.into(),
ssh_cmd_line.chain(Some(host.as_str())),
ssh_cmd_line.chain(Some(host)),
None::<(&str, String)>,
path,
desired_version,
Expand All @@ -92,18 +92,30 @@ pub fn connect(

#[cfg(test)]
mod tests {

use bstr::ByteSlice;

use crate::{client::blocking_io::ssh::connect, Protocol};

#[test]
fn connect_with_tilde_in_path() {
fn connect_path() {
for (url, expected) in &[
("ssh://host.xy/~/repo", "~/repo"),
("ssh://host.xy/~username/repo", "~username/repo"),
("user@host.xy:/username/repo", "/username/repo"),
("user@host.xy:username/repo", "username/repo"),
("user@host.xy:../username/repo", "../username/repo"),
("user@host.xy:~/repo", "~/repo"),
] {
let url = git_url::parse((*url).into()).expect("valid url");
let cmd = connect("host", url.path, Protocol::V1, None, None).expect("parse success");
let cmd = connect(
url.host().expect("all cases have a host"),
url.path.to_owned(),
Protocol::V1,
url.user(),
url.port,
)
.expect("parse success");
assert_eq!(
cmd.path,
expected.as_bytes().as_bstr(),
Expand Down

0 comments on commit c62e5c7

Please sign in to comment.