From cc66b4c93bea20220de9ebd4a0b3f686da1d0453 Mon Sep 17 00:00:00 2001 From: Karen Arutyunov Date: Wed, 7 Nov 2018 21:25:52 +0300 Subject: Add support for ssh:// git protocol --- bpkg/common.cli | 4 ++-- bpkg/fetch-git.cxx | 18 +++++++++++++++++- bpkg/repository-types.cli | 21 +++++++++++---------- tests/remote-git.testscript | 7 +++++++ tests/rep-fetch-git-refname.testscript | 1 + tests/rep-fetch-git.testscript | 2 ++ tests/rep-fetch.testscript | 8 ++++++++ 7 files changed, 48 insertions(+), 13 deletions(-) diff --git a/bpkg/common.cli b/bpkg/common.cli index a8c363e..646cb2b 100644 --- a/bpkg/common.cli +++ b/bpkg/common.cli @@ -140,8 +140,8 @@ namespace bpkg \cb{curl} and to the \cb{--timeout} option for \cb{wget} and \cb{fetch}. For \cb{git} over HTTP/HTTPS this semantics is achieved using the \cb{http.lowSpeedLimit}=\i{1} \cb{http.lowSpeedTime}=\i{sec} - configuration values (the \cb{git://} protocol currently does not - support timeouts). + configuration values (the \cb{git://} and \cb{ssh://} protocols + currently do not support timeouts). See \cb{--fetch} and \cb{--git} for more information on the fetch programs." diff --git a/bpkg/fetch-git.cxx b/bpkg/fetch-git.cxx index 2cf526d..c2e1b36 100644 --- a/bpkg/fetch-git.cxx +++ b/bpkg/fetch-git.cxx @@ -63,6 +63,21 @@ namespace bpkg warn << "--fetch-timeout is not supported by the git protocol"; break; } + case repository_protocol::ssh: + { + // The way to support timeout for the ssh protocol would be using the + // '-c core.sshCommand=...' git option (relying on ConnectTimeout and + // ServerAlive* options for OpenSSH). To do it cleanly, we would need + // to determine the ssh program path and kind (ssh, putty, plink, etc) + // that git will use to communicate with the repository server. And it + // looks like there is no easy way to do it (see the core.sshCommand + // and ssh.variant git configuration options for details). So we will + // not support the ssh protocol timeout for now. Note that the user + // can always specify the timeout in git or ssh configuration. + // + warn << "--fetch-timeout is not supported by the ssh protocol"; + break; + } case repository_protocol::file: return strings (); // Local communications. } @@ -401,7 +416,7 @@ namespace bpkg // // Protocols other than HTTP(S) are considered smart but without the // unadvertised refs (note that this is a pessimistic assumption for - // git://). + // git:// and ssh://). // // For HTTP(S) sense the protocol type by sending the first HTTP request of // the fetch operation handshake and analyzing the first line of the @@ -429,6 +444,7 @@ namespace bpkg switch (url.scheme) { case repository_protocol::git: + case repository_protocol::ssh: case repository_protocol::file: return capabilities::smart; case repository_protocol::http: case repository_protocol::https: break; // Ask the server (see below). diff --git a/bpkg/repository-types.cli b/bpkg/repository-types.cli index f0e07be..79c50f8 100644 --- a/bpkg/repository-types.cli +++ b/bpkg/repository-types.cli @@ -155,11 +155,11 @@ plus (\cb{+}) is treated as an inclusion filter. For example: .../foo.git#++x - include +x \ -Currently supported \cb{git} protocols are \cb{git://}, \cb{http://}, and -\cb{https://} for remote repositories and \cb{file://} for local -repositories. While \cb{bpkg} tries to minimize the amount of information -(history) fetched, it is not always possible for some protocols and/or server -configurations, as discussed next. +Currently supported \cb{git} protocols are \cb{git://}, \cb{ssh://} (but not +\c{scp} pseudo-URL syntax), \cb{http://}, and \cb{https://} for remote +repositories and \cb{file://} for local repositories. While \cb{bpkg} tries to +minimize the amount of information (history) fetched, it is not always +possible for some protocols and/or server configurations, as discussed next. A \cb{git} repository accessible via \cb{http(s)://} can use either \i{dumb} or \i{smart} protocol (refer to the \cb{git} documentation for details). The @@ -173,11 +173,12 @@ whether the server is configured to allow fetching unadvertised commits. For details, refer to the \cb{uploadpack.allowReachableSHA1InWant} and \cb{uploadpack.allowAnySHA1InWant} \cb{git} configuration values. -The \cb{git://} protocol is similar to smart \cb{http://} in that it supports -fetching minimal history for tags and branches and may or may not support this -for commit ids depending on the server configuration. Note, however, that -unlike for \cb{http(s)://}, for this protocol \cb{bpkg} does not try to sense -if fetching unadvertised commits is allowed and always assumes that it is not. +The \cb{git://} and \cb{ssh://} protocols are similar to smart \cb{http://} in +that they support fetching minimal history for tags and branches and may or +may not support this for commit ids depending on the server configuration. +Note, however, that unlike for \cb{http(s)://}, for these protocols \cb{bpkg} +does not try to sense if fetching unadvertised commits is allowed and always +assumes that it is not. Based on this information, to achieve optimal results the recommended protocol for remote repositories is smart \cb{https://}. Additionally, if you are diff --git a/tests/remote-git.testscript b/tests/remote-git.testscript index 595220d..a5d3e75 100644 --- a/tests/remote-git.testscript +++ b/tests/remote-git.testscript @@ -54,10 +54,17 @@ remote = $config.bpkg.test.remote mkdir -p $out_git else + # If $git_ssh is not true then testscripts must skip tests that use the ssh + # protocol. Otherwise, it is assumed that the password-less ssh + # authentication is arranged for git.build2.org. + # + git_ssh = $config.bpkg.test.git.ssh + rep_git_https_dumb = "https://build2.org/bpkg/git/$cmd" rep_git_https_smart = "https://git.build2.org/testing/bpkg/advonly/$cmd" rep_git_https_smart_unadv = "https://git.build2.org/testing/bpkg/unadv/$cmd" rep_git_git = "git://git.build2.org/testing/bpkg/unadv/$cmd" + rep_git_ssh = "ssh://git.build2.org/var/scm/testing/bpkg/unadv/$cmd" rep_git = $rep_git_https_dumb # Default remote repository URL. end diff --git a/tests/rep-fetch-git-refname.testscript b/tests/rep-fetch-git-refname.testscript index 88f1e2a..6bb9d57 100644 --- a/tests/rep-fetch-git-refname.testscript +++ b/tests/rep-fetch-git-refname.testscript @@ -65,6 +65,7 @@ if ($git_protocol == 'local' || \ $git_protocol == 'https-smart' || \ + $git_protocol == 'ssh' || \ $git_protocol == 'git') warn2 = "$warn_repo_hist for submodule 'doc/style/basic'$reason_unadv" elif ($git_protocol == 'https-dumb') diff --git a/tests/rep-fetch-git.testscript b/tests/rep-fetch-git.testscript index 3fe0287..8e9d957 100644 --- a/tests/rep-fetch-git.testscript +++ b/tests/rep-fetch-git.testscript @@ -29,6 +29,8 @@ elif ($git_protocol == 'https-smart-unadv') rep = "$rep_git_https_smart_unadv" elif ($git_protocol == 'git') rep = "$rep_git_git" +elif ($git_protocol == 'ssh') + rep = "$rep_git_ssh" else exit "unexpected git protocol '$git_protocol'" end diff --git a/tests/rep-fetch.testscript b/tests/rep-fetch.testscript index c1828a8..8320f70 100644 --- a/tests/rep-fetch.testscript +++ b/tests/rep-fetch.testscript @@ -732,6 +732,14 @@ else git_protocol = 'git' .include rep-fetch-git.testscript } + + : ssh + : + if ($git_ssh == true) + { + git_protocol = 'ssh' + .include rep-fetch-git.testscript + } } : strip-ext -- cgit v1.1