diff --git a/CMakeLists.txt b/CMakeLists.txt index 41dae831e..dfb9e24a6 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -29,6 +29,7 @@ option(BUILD_FUZZERS "Build the fuzz targets" # Feature enablement and backend selection set(USE_THREADS "" CACHE STRING "Use threads for parallel processing when possible. One of ON, OFF, or a specific provider: pthreads or win32. (Defaults to ON.)") set(USE_SSH "" CACHE STRING "Enables SSH support and optionally selects provider. One of ON, OFF, or a specific provider: libssh2 or exec. (Defaults to OFF.)") + set(USE_HTTP "" CACHE STRING "Enable HTTP transport support (covers both http:// and https:// remotes). One of ON or OFF. When OFF, HTTPS is also disabled. (Defaults to ON.)") set(USE_HTTPS "" CACHE STRING "Enable HTTPS support and optionally selects the provider. One of ON, OFF, or a specific provider: OpenSSL, OpenSSL-FIPS, OpenSSL-Dynamic, mbedTLS, SecureTransport, Schannel, or WinHTTP. (Defaults to ON.)") set(USE_SHA1 "" CACHE STRING "Selects SHA1 provider. One of builtin, HTTPS, or a specific provider. (Defaults to builtin.)") set(USE_SHA256 "" CACHE STRING "Selects SHA256 provider. One of Builtin, HTTPS, or a specific provider. (Defaults to HTTPS.)") diff --git a/cmake/SelectHTTP.cmake b/cmake/SelectHTTP.cmake new file mode 100644 index 000000000..55246af76 --- /dev/null +++ b/cmake/SelectHTTP.cmake @@ -0,0 +1,32 @@ +include(SanitizeInput) + +if(USE_HTTP STREQUAL "") + set(USE_HTTP ON) +endif() + +sanitizeinput(USE_HTTP) + +if(USE_HTTP STREQUAL ON) + set(GIT_HTTP 1) + add_feature_info(HTTP ON "HTTP transport support") +elseif(USE_HTTP STREQUAL OFF) + # Several features only have meaning over HTTP: HTTPS, NTLM and + # Negotiate auth. If the user did not request them explicitly, silently + # disable them to keep configurations consistent. If they were requested + # explicitly, error out: they cannot be built without the HTTP transport. + foreach(_dep USE_HTTPS USE_AUTH_NTLM USE_AUTH_NEGOTIATE) + if(${_dep} STREQUAL "") + set(${_dep} OFF) + else() + set(_dep_check "${${_dep}}") + sanitizeinput(_dep_check) + if(_dep_check) + message(FATAL_ERROR "${_dep}=${${_dep}} requires USE_HTTP=ON; this feature depends on the HTTP transport") + endif() + endif() + endforeach() + + add_feature_info(HTTP OFF "HTTP transport support is disabled") +else() + message(FATAL_ERROR "unknown HTTP option: ${USE_HTTP}") +endif() diff --git a/include/git2/common.h b/include/git2/common.h index 0be84fa77..20311b71a 100644 --- a/include/git2/common.h +++ b/include/git2/common.h @@ -173,7 +173,10 @@ typedef enum { GIT_FEATURE_SHA1 = (1 << 10), /** SHA256 object support */ - GIT_FEATURE_SHA256 = (1 << 11) + GIT_FEATURE_SHA256 = (1 << 11), + + /** HTTP remotes */ + GIT_FEATURE_HTTP = (1 << 12) } git_feature_t; /** diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 894fe95d0..318024d2f 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -38,6 +38,7 @@ add_feature_info("Debug open" GIT_DEBUG_STRICT_OPEN "strict path validation in o include(SelectThreads) include(SelectNsec) +include(SelectHTTP) include(SelectHTTPSBackend) include(SelectHashes) include(SelectHTTPParser) @@ -172,3 +173,4 @@ set(LIBGIT2_DEPENDENCY_INCLUDES ${LIBGIT2_DEPENDENCY_INCLUDES} PARENT_SCOPE) set(LIBGIT2_DEPENDENCY_OBJECTS ${LIBGIT2_DEPENDENCY_OBJECTS} PARENT_SCOPE) set(LIBGIT2_SYSTEM_INCLUDES ${LIBGIT2_SYSTEM_INCLUDES} PARENT_SCOPE) set(LIBGIT2_SYSTEM_LIBS ${LIBGIT2_SYSTEM_LIBS} PARENT_SCOPE) +set(GIT_HTTP ${GIT_HTTP} PARENT_SCOPE) diff --git a/src/libgit2/libgit2.c b/src/libgit2/libgit2.c index c1aae36a5..f26ab490a 100644 --- a/src/libgit2/libgit2.c +++ b/src/libgit2/libgit2.c @@ -86,6 +86,9 @@ int git_libgit2_features(void) #ifdef GIT_THREADS | GIT_FEATURE_THREADS #endif +#ifdef GIT_HTTP + | GIT_FEATURE_HTTP +#endif #ifdef GIT_HTTPS | GIT_FEATURE_HTTPS #endif @@ -127,6 +130,10 @@ const char *git_libgit2_feature_backend(git_feature_t feature) #endif break; + case GIT_FEATURE_HTTP: + /* HTTP has no backend selection; presence is reported via git_libgit2_features() */ + break; + case GIT_FEATURE_HTTPS: #if defined(GIT_HTTPS_OPENSSL) return "openssl"; diff --git a/src/libgit2/transport.c b/src/libgit2/transport.c index c31fca3a4..ce2c97d09 100644 --- a/src/libgit2/transport.c +++ b/src/libgit2/transport.c @@ -20,9 +20,12 @@ typedef struct transport_definition { void *param; } transport_definition; -static git_smart_subtransport_definition http_subtransport_definition = { git_smart_subtransport_http, 1, NULL }; static git_smart_subtransport_definition git_subtransport_definition = { git_smart_subtransport_git, 0, NULL }; +#ifdef GIT_HTTP +static git_smart_subtransport_definition http_subtransport_definition = { git_smart_subtransport_http, 1, NULL }; +#endif + #ifdef GIT_SSH static git_smart_subtransport_definition ssh_subtransport_definition = { git_smart_subtransport_ssh, 0, NULL }; #endif @@ -31,8 +34,10 @@ static transport_definition local_transport_definition = { "file://", git_transp static transport_definition transports[] = { { "git://", git_transport_smart, &git_subtransport_definition }, +#ifdef GIT_HTTP { "http://", git_transport_smart, &http_subtransport_definition }, { "https://", git_transport_smart, &http_subtransport_definition }, +#endif { "file://", git_transport_local, NULL }, #ifdef GIT_SSH diff --git a/src/libgit2/transports/http.c b/src/libgit2/transports/http.c index 923a825fa..406c624d8 100644 --- a/src/libgit2/transports/http.c +++ b/src/libgit2/transports/http.c @@ -6,14 +6,16 @@ */ #include "common.h" +#include "http.h" -#ifndef GIT_HTTPS_WINHTTP +bool git_http__expect_continue = false; + +#if defined(GIT_HTTP) && !defined(GIT_HTTPS_WINHTTP) #include "net.h" #include "remote.h" #include "smart.h" #include "auth.h" -#include "http.h" #include "auth_negotiate.h" #include "auth_ntlm.h" #include "trace.h" @@ -22,8 +24,6 @@ #include "httpclient.h" #include "git2/sys/credential.h" -bool git_http__expect_continue = false; - typedef enum { HTTP_STATE_NONE = 0, HTTP_STATE_SENDING_REQUEST, @@ -762,4 +762,18 @@ int git_smart_subtransport_http(git_smart_subtransport **out, git_transport *own return 0; } -#endif /* !GIT_HTTPS_WINHTTP */ +#elif !defined(GIT_HTTP) + +#include "git2/sys/transport.h" + +int git_smart_subtransport_http(git_smart_subtransport **out, git_transport *owner, void *param) +{ + GIT_UNUSED(out); + GIT_UNUSED(owner); + GIT_UNUSED(param); + + git_error_set(GIT_ERROR_INVALID, "cannot create HTTP transport; library was built without HTTP support"); + return -1; +} + +#endif /* GIT_HTTP && !GIT_HTTPS_WINHTTP */ diff --git a/src/libgit2/transports/httpclient.c b/src/libgit2/transports/httpclient.c index 86bae396e..a5138b31a 100644 --- a/src/libgit2/transports/httpclient.c +++ b/src/libgit2/transports/httpclient.c @@ -6,6 +6,9 @@ */ #include "common.h" + +#ifdef GIT_HTTP + #include "git2.h" #include "vector.h" @@ -1634,3 +1637,5 @@ void git_http_client_free(git_http_client *client) git_str_dispose(&client->read_buf); git__free(client); } + +#endif /* GIT_HTTP */ diff --git a/src/libgit2/transports/httpparser.c b/src/libgit2/transports/httpparser.c index 84833e617..84ad27342 100644 --- a/src/libgit2/transports/httpparser.c +++ b/src/libgit2/transports/httpparser.c @@ -9,6 +9,8 @@ #include +#ifdef GIT_HTTP + #if defined(GIT_HTTPPARSER_HTTPPARSER) #include "http_parser.h" @@ -126,3 +128,5 @@ size_t git_http_parser_execute( #else # error unknown http-parser #endif + +#endif /* GIT_HTTP */ diff --git a/src/libgit2/transports/winhttp.c b/src/libgit2/transports/winhttp.c index 7141c2846..119981f49 100644 --- a/src/libgit2/transports/winhttp.c +++ b/src/libgit2/transports/winhttp.c @@ -63,8 +63,6 @@ # define DWORD_MAX 0xffffffff #endif -bool git_http__expect_continue = false; - static const char *prefix_https = "https://"; static const char *upload_pack_service = "upload-pack"; static const char *upload_pack_ls_service_url = "/info/refs?service=git-upload-pack"; diff --git a/src/util/git2_features.h.in b/src/util/git2_features.h.in index a440561f8..e890670bb 100644 --- a/src/util/git2_features.h.in +++ b/src/util/git2_features.h.in @@ -53,6 +53,8 @@ #cmakedefine GIT_SSH_LIBSSH2 1 #cmakedefine GIT_SSH_LIBSSH2_MEMORY_CREDENTIALS 1 +#cmakedefine GIT_HTTP 1 + #cmakedefine GIT_HTTPS 1 #cmakedefine GIT_HTTPS_OPENSSL 1 #cmakedefine GIT_HTTPS_OPENSSL_DYNAMIC 1 diff --git a/tests/libgit2/CMakeLists.txt b/tests/libgit2/CMakeLists.txt index 0e44c30d0..ae5c484bf 100644 --- a/tests/libgit2/CMakeLists.txt +++ b/tests/libgit2/CMakeLists.txt @@ -72,12 +72,16 @@ endif() include(AddClarTest) add_clar_test(libgit2_tests offline -v -xonline) add_clar_test(libgit2_tests invasive -v -sfilter::stream::bigfile -sodb::largefiles -siterator::workdir::filesystem_gunk -srepo::init -srepo::init::at_filesystem_root -sonline::clone::connect_timeout_default) -add_clar_test(libgit2_tests online -v -sonline -xonline::customcert) -add_clar_test(libgit2_tests online_customcert -v -sonline::customcert) add_clar_test(libgit2_tests gitdaemon -v -sonline::push) add_clar_test(libgit2_tests gitdaemon_namespace -v -sonline::clone::namespace) add_clar_test(libgit2_tests gitdaemon_sha256 -v -sonline::clone::sha256) add_clar_test(libgit2_tests ssh -v -sonline::push -sonline::clone::ssh_cert -sonline::clone::ssh_with_paths -sonline::clone::path_whitespace_ssh -sonline::clone::ssh_auth_methods) -add_clar_test(libgit2_tests proxy -v -sonline::clone::proxy) -add_clar_test(libgit2_tests auth_clone -v -sonline::clone::cred) -add_clar_test(libgit2_tests auth_clone_and_push -v -sonline::clone::push -sonline::push) + +# HTTP-dependent online tests; only meaningful when the library is built with HTTP support. +if(GIT_HTTP) + add_clar_test(libgit2_tests online -v -sonline -xonline::customcert) + add_clar_test(libgit2_tests online_customcert -v -sonline::customcert) + add_clar_test(libgit2_tests proxy -v -sonline::clone::proxy) + add_clar_test(libgit2_tests auth_clone -v -sonline::clone::cred) + add_clar_test(libgit2_tests auth_clone_and_push -v -sonline::clone::push -sonline::push) +endif() diff --git a/tests/libgit2/core/features.c b/tests/libgit2/core/features.c index f8c6679c2..885362545 100644 --- a/tests/libgit2/core/features.c +++ b/tests/libgit2/core/features.c @@ -10,6 +10,12 @@ void test_core_features__basic(void) cl_assert((caps & GIT_FEATURE_THREADS) == 0); #endif +#ifdef GIT_HTTP + cl_assert((caps & GIT_FEATURE_HTTP) != 0); +#else + cl_assert((caps & GIT_FEATURE_HTTP) == 0); +#endif + #ifdef GIT_HTTPS cl_assert((caps & GIT_FEATURE_HTTPS) != 0); #endif @@ -53,6 +59,7 @@ void test_core_features__basic(void) * added that the backends test (below) is updated as well. */ cl_assert((caps & ~(GIT_FEATURE_THREADS | + GIT_FEATURE_HTTP | GIT_FEATURE_HTTPS | GIT_FEATURE_SSH | GIT_FEATURE_NSEC | @@ -70,6 +77,7 @@ void test_core_features__basic(void) void test_core_features__backends(void) { const char *threads = git_libgit2_feature_backend(GIT_FEATURE_THREADS); + const char *http = git_libgit2_feature_backend(GIT_FEATURE_HTTP); const char *https = git_libgit2_feature_backend(GIT_FEATURE_HTTPS); const char *ssh = git_libgit2_feature_backend(GIT_FEATURE_SSH); const char *nsec = git_libgit2_feature_backend(GIT_FEATURE_NSEC); @@ -92,6 +100,9 @@ void test_core_features__backends(void) cl_assert(threads == NULL); #endif + /* HTTP has no backend selection */ + cl_assert(http == NULL); + #if defined(GIT_HTTPS_OPENSSL) cl_assert_equal_s("openssl", https); #elif defined(GIT_HTTPS_OPENSSL_DYNAMIC)