summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--azure-pipelines.yml2
-rw-r--r--azure-pipelines/nightly.yml2
-rw-r--r--cmake/Modules/FindGSSFramework.cmake28
-rw-r--r--cmake/Modules/SelectGSSAPI.cmake53
-rw-r--r--cmake/Modules/SelectHTTPSBackend.cmake2
-rw-r--r--fuzzers/corpora/patch_parse/edit-file.diff13
-rw-r--r--fuzzers/corpora/patch_parse/patch_fuzzer-patch.diff45
-rw-r--r--fuzzers/patch_parse_fuzzer.c38
-rw-r--r--include/git2/submodule.h19
-rw-r--r--src/CMakeLists.txt12
-rw-r--r--src/clone.c25
-rw-r--r--src/clone.h4
-rw-r--r--src/features.h.in4
-rw-r--r--src/patch_parse.c1
-rw-r--r--src/submodule.c59
-rw-r--r--src/transports/auth_negotiate.c6
-rw-r--r--src/transports/auth_negotiate.h2
-rw-r--r--src/util.c5
-rw-r--r--tests/clone/nonetwork.c54
-rw-r--r--tests/diff/parse.c10
-rw-r--r--tests/patch/patch_common.h10
-rw-r--r--tests/submodule/add.c66
22 files changed, 386 insertions, 74 deletions
diff --git a/azure-pipelines.yml b/azure-pipelines.yml
index 00cca7e14..d74b51449 100644
--- a/azure-pipelines.yml
+++ b/azure-pipelines.yml
@@ -79,7 +79,7 @@ jobs:
TMPDIR: $(Agent.TempDirectory)
PKG_CONFIG_PATH: /usr/local/opt/openssl/lib/pkgconfig
CMAKE_GENERATOR: Ninja
- CMAKE_OPTIONS: -DREGEX_BACKEND=regcomp_l -DDEPRECATE_HARD=ON -DUSE_LEAK_CHECKER=leaks
+ CMAKE_OPTIONS: -DREGEX_BACKEND=regcomp_l -DDEPRECATE_HARD=ON -DUSE_LEAK_CHECKER=leaks -DUSE_GSSAPI=ON
SKIP_SSH_TESTS: true
- job: windows_vs_amd64
diff --git a/azure-pipelines/nightly.yml b/azure-pipelines/nightly.yml
index b8d550f28..a193747b5 100644
--- a/azure-pipelines/nightly.yml
+++ b/azure-pipelines/nightly.yml
@@ -79,7 +79,7 @@ jobs:
TMPDIR: $(Agent.TempDirectory)
PKG_CONFIG_PATH: /usr/local/opt/openssl/lib/pkgconfig
CMAKE_GENERATOR: Ninja
- CMAKE_OPTIONS: -DREGEX_BACKEND=regcomp_l -DDEPRECATE_HARD=ON -DUSE_LEAK_CHECKER=leaks
+ CMAKE_OPTIONS: -DREGEX_BACKEND=regcomp_l -DDEPRECATE_HARD=ON -DUSE_LEAK_CHECKER=leaks -DUSE_GSSAPI=ON
RUN_INVASIVE_TESTS: true
SKIP_SSH_TESTS: true
diff --git a/cmake/Modules/FindGSSFramework.cmake b/cmake/Modules/FindGSSFramework.cmake
new file mode 100644
index 000000000..dcf724916
--- /dev/null
+++ b/cmake/Modules/FindGSSFramework.cmake
@@ -0,0 +1,28 @@
+# Find GSS.framework
+# This will define :
+#
+# GSSFRAMEWORK_FOUND
+# GSSFRAMEWORK_INCLUDE_DIR
+# GSSFRAMEWORK_LIBRARIES
+# GSSFRAMEWORK_LDFLAGS
+#
+
+FIND_PATH(GSSFRAMEWORK_INCLUDE_DIR NAMES GSS.h)
+FIND_LIBRARY(GSSFRAMEWORK_LIBRARIES NAMES GSS)
+IF (GSSFRAMEWORK_INCLUDE_DIR AND GSSFRAMEWORK_LIBRARIES)
+ IF (NOT CoreFoundation_FIND_QUIETLY)
+ MESSAGE(STATUS "Found GSS.framework ${GSSFRAMEWORK_LIBRARIES}")
+ ENDIF()
+ SET(GSSFRAMEWORK_FOUND TRUE)
+ SET(GSSFRAMEWORK_LDFLAGS "-framework GSS")
+ENDIF ()
+
+IF (GSS_FIND_REQUIRED AND NOT GSSFRAMEWORK_FOUND)
+ MESSAGE(FATAL_ERROR "CoreFoundation not found")
+ENDIF()
+
+MARK_AS_ADVANCED(
+ GSSFRAMEWORK_INCLUDE_DIR
+ GSSFRAMEWORK_LIBRARIES
+ GSSFRAMEWORK_LDFLAGS
+)
diff --git a/cmake/Modules/SelectGSSAPI.cmake b/cmake/Modules/SelectGSSAPI.cmake
new file mode 100644
index 000000000..41f837587
--- /dev/null
+++ b/cmake/Modules/SelectGSSAPI.cmake
@@ -0,0 +1,53 @@
+# Select the backend to use
+
+# We try to find any packages our backends might use
+
+FIND_PACKAGE(GSSAPI)
+IF (CMAKE_SYSTEM_NAME MATCHES "Darwin")
+ INCLUDE(FindGSSFramework)
+ENDIF()
+
+# Auto-select GSS backend
+IF (USE_GSSAPI STREQUAL ON)
+ IF (GSSFRAMEWORK_FOUND)
+ SET(GSS_BACKEND "GSS.framework")
+ ELSEIF(GSSAPI_FOUND)
+ SET(GSS_BACKEND "gssapi")
+ ELSE()
+ MESSAGE(FATAL_ERROR "Unable to autodetect a usable GSS backend."
+ "Please pass the backend name explicitly (-DUSE_GSS=backend)")
+ ENDIF()
+ELSEIF(USE_GSSAPI)
+ # Backend was explicitly set
+ SET(GSS_BACKEND ${USE_GSSAPI})
+ELSE()
+ SET(GSS_BACKEND NO)
+ENDIF()
+
+IF(GSS_BACKEND)
+ # Check that we can find what's required for the selected backend
+ IF (GSS_BACKEND STREQUAL "GSS.framework")
+ IF (NOT GSSFRAMEWORK_FOUND)
+ MESSAGE(FATAL_ERROR "Asked for GSS.framework backend, but it wasn't found")
+ ENDIF()
+
+ LIST(APPEND LIBGIT2_LIBS ${GSSFRAMEWORK_LIBRARIES})
+
+ SET(GIT_GSSFRAMEWORK 1)
+ ADD_FEATURE_INFO(SPNEGO GIT_GSSFRAMEWORK "SPNEGO authentication support (${GSS_BACKEND})")
+ ELSEIF (GSS_BACKEND STREQUAL "gssapi")
+ IF (NOT GSSAPI_FOUND)
+ MESSAGE(FATAL_ERROR "Asked for gssapi GSS backend, but it wasn't found")
+ ENDIF()
+
+ LIST(APPEND LIBGIT2_LIBS ${GSSAPI_LIBRARIES})
+
+ SET(GIT_GSSAPI 1)
+ ADD_FEATURE_INFO(SPNEGO GIT_GSSAPI "SPNEGO authentication support (${GSS_BACKEND})")
+ ELSE()
+ MESSAGE(FATAL_ERROR "Asked for backend ${GSS_BACKEND} but it wasn't found")
+ ENDIF()
+ELSE()
+ SET(GIT_GSSAPI 0)
+ ADD_FEATURE_INFO(SPNEGO NO "")
+ENDIF()
diff --git a/cmake/Modules/SelectHTTPSBackend.cmake b/cmake/Modules/SelectHTTPSBackend.cmake
index 81f3f8b58..c7f6b8f1d 100644
--- a/cmake/Modules/SelectHTTPSBackend.cmake
+++ b/cmake/Modules/SelectHTTPSBackend.cmake
@@ -49,7 +49,7 @@ IF(HTTPS_BACKEND)
SET(GIT_SECURE_TRANSPORT 1)
LIST(APPEND LIBGIT2_SYSTEM_INCLUDES ${SECURITY_INCLUDE_DIR})
- LIST(APPEND LIBGIT2_LIBS ${COREFOUNDATION_LIBRARIES} ${SECURITY_LIBRARIES})
+ LIST(APPEND LIBGIT2_LIBS ${COREFOUNDATION_LDFLAGS} ${SECURITY_LDFLAGS})
LIST(APPEND LIBGIT2_PC_LIBS ${COREFOUNDATION_LDFLAGS} ${SECURITY_LDFLAGS})
ELSEIF (HTTPS_BACKEND STREQUAL "OpenSSL")
IF (NOT OPENSSL_FOUND)
diff --git a/fuzzers/corpora/patch_parse/edit-file.diff b/fuzzers/corpora/patch_parse/edit-file.diff
new file mode 100644
index 000000000..d9e783a7f
--- /dev/null
+++ b/fuzzers/corpora/patch_parse/edit-file.diff
@@ -0,0 +1,13 @@
+diff --git a/fuzzers/patch_fuzzer.c b/fuzzers/patch_fuzzer.c
+index 76186b6fb..f7ce73ac8 100644
+--- a/fuzzers/patch_fuzzer.c
++++ b/fuzzers/patch_fuzzer.c
+@@ -32,7 +32,7 @@ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
+ git_patch* patch;
+ git_patch_options opts = {(uint32_t)data[0]};
+ int status = git_patch_from_buffer(&patch, (const char*)data+1, size-1, &opts);
+- if (status == 0 && patch) {
++ if (patch) {
+ git_patch_free(patch);
+ }
+ return 0;
diff --git a/fuzzers/corpora/patch_parse/patch_fuzzer-patch.diff b/fuzzers/corpora/patch_parse/patch_fuzzer-patch.diff
new file mode 100644
index 000000000..7c98d8ad4
--- /dev/null
+++ b/fuzzers/corpora/patch_parse/patch_fuzzer-patch.diff
@@ -0,0 +1,45 @@
+diff --git a/fuzzers/patch_fuzzer.c b/fuzzers/patch_fuzzer.c
+new file mode 100644
+index 000000000..76186b6fb
+--- /dev/null
++++ b/fuzzers/patch_fuzzer.c
+@@ -0,0 +1,39 @@
++/*
++ * libgit2 patch fuzzer target.
++ *
++ * Copyright (C) the libgit2 contributors. All rights reserved.
++ *
++ * This file is part of libgit2, distributed under the GNU GPL v2 with
++ * a Linking Exception. For full terms see the included COPYING file.
++ */
++
++#include "git2.h"
++#include "patch.h"
++#include "patch_parse.h"
++
++#define UNUSED(x) (void)(x)
++
++int LLVMFuzzerInitialize(int *argc, char ***argv)
++{
++ UNUSED(argc);
++ UNUSED(argv);
++
++ if (git_libgit2_init() < 0)
++ abort();
++
++ return 0;
++}
++
++int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
++{
++ if (size < 1) {
++ return 0;
++ }
++ git_patch* patch;
++ git_patch_options opts = {(uint32_t)data[0]};
++ int status = git_patch_from_buffer(&patch, (const char*)data+1, size-1, &opts);
++ if (status == 0 && patch) {
++ git_patch_free(patch);
++ }
++ return 0;
++}
diff --git a/fuzzers/patch_parse_fuzzer.c b/fuzzers/patch_parse_fuzzer.c
new file mode 100644
index 000000000..a9b02ad4d
--- /dev/null
+++ b/fuzzers/patch_parse_fuzzer.c
@@ -0,0 +1,38 @@
+/*
+ * libgit2 patch parser fuzzer target.
+ *
+ * Copyright (C) the libgit2 contributors. All rights reserved.
+ *
+ * This file is part of libgit2, distributed under the GNU GPL v2 with
+ * a Linking Exception. For full terms see the included COPYING file.
+ */
+
+#include "git2.h"
+#include "patch.h"
+#include "patch_parse.h"
+
+#define UNUSED(x) (void)(x)
+
+int LLVMFuzzerInitialize(int *argc, char ***argv)
+{
+ UNUSED(argc);
+ UNUSED(argv);
+
+ if (git_libgit2_init() < 0)
+ abort();
+
+ return 0;
+}
+
+int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
+{
+ if (size) {
+ git_patch *patch = NULL;
+ git_patch_options opts = GIT_PATCH_OPTIONS_INIT;
+ opts.prefix_len = (uint32_t)data[0];
+ git_patch_from_buffer(&patch, (const char *)data + 1, size - 1,
+ &opts);
+ git_patch_free(patch);
+ }
+ return 0;
+}
diff --git a/include/git2/submodule.h b/include/git2/submodule.h
index 62f250b2b..bedd76d6a 100644
--- a/include/git2/submodule.h
+++ b/include/git2/submodule.h
@@ -263,7 +263,8 @@ GIT_EXTERN(int) git_submodule_foreach(
* from the working directory to the new repo.
*
* To fully emulate "git submodule add" call this function, then open the
- * submodule repo and perform the clone step as needed. Lastly, call
+ * submodule repo and perform the clone step as needed (if you don't need
+ * anything custom see `git_submodule_add_clone()`). Lastly, call
* `git_submodule_add_finalize()` to wrap up adding the new submodule and
* .gitmodules to the index to be ready to commit.
*
@@ -286,6 +287,22 @@ GIT_EXTERN(int) git_submodule_add_setup(
int use_gitlink);
/**
+ * Perform the clone step for a newly created submodule.
+ *
+ * This performs the necessary `git_clone` to setup a newly-created submodule.
+ *
+ * @param out The newly created repository object. Optional.
+ * @param submodule The submodule currently waiting for its clone.
+ * @param opts The options to use.
+ *
+ * @return 0 on success, -1 on other errors (see git_clone).
+ */
+GIT_EXTERN(int) git_submodule_clone(
+ git_repository **out,
+ git_submodule *submodule,
+ const git_submodule_update_options *opts);
+
+/**
* Resolve the setup of a new git submodule.
*
* This should be called on a submodule once you have called add setup
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 9d2b0229d..0ca1e7374 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -233,15 +233,9 @@ IF (USE_NTLMCLIENT)
ENDIF()
ADD_FEATURE_INFO(ntlmclient GIT_NTLM "NTLM authentication support for Unix")
-# Optional external dependency: libgssapi
-IF (USE_GSSAPI)
- FIND_PACKAGE(GSSAPI)
-ENDIF()
-IF (GSSAPI_FOUND)
- SET(GIT_GSSAPI 1)
- LIST(APPEND LIBGIT2_LIBS ${GSSAPI_LIBRARIES})
-ENDIF()
-ADD_FEATURE_INFO(SPNEGO GIT_GSSAPI "SPNEGO authentication support")
+# Optional external dependency: GSSAPI
+
+INCLUDE(SelectGSSAPI)
# Optional external dependency: iconv
IF (USE_ICONV)
diff --git a/src/clone.c b/src/clone.c
index e0b43f149..e8972b482 100644
--- a/src/clone.c
+++ b/src/clone.c
@@ -382,11 +382,12 @@ done:
return is_local;
}
-int git_clone(
+static int git__clone(
git_repository **out,
const char *url,
const char *local_path,
- const git_clone_options *_options)
+ const git_clone_options *_options,
+ int use_existing)
{
int error = 0;
git_repository *repo = NULL;
@@ -403,7 +404,7 @@ int git_clone(
GIT_ERROR_CHECK_VERSION(&options, GIT_CLONE_OPTIONS_VERSION, "git_clone_options");
/* Only clone to a new directory or an empty directory */
- if (git_path_exists(local_path) && !git_path_is_empty_dir(local_path)) {
+ if (git_path_exists(local_path) && !use_existing && !git_path_is_empty_dir(local_path)) {
git_error_set(GIT_ERROR_INVALID,
"'%s' exists and is not an empty directory", local_path);
return GIT_EEXISTS;
@@ -455,6 +456,24 @@ int git_clone(
return error;
}
+int git_clone(
+ git_repository **out,
+ const char *url,
+ const char *local_path,
+ const git_clone_options *_options)
+{
+ return git__clone(out, url, local_path, _options, 0);
+}
+
+int git_clone__submodule(
+ git_repository **out,
+ const char *url,
+ const char *local_path,
+ const git_clone_options *_options)
+{
+ return git__clone(out, url, local_path, _options, 1);
+}
+
int git_clone_options_init(git_clone_options *opts, unsigned int version)
{
GIT_INIT_STRUCTURE_FROM_TEMPLATE(
diff --git a/src/clone.h b/src/clone.h
index 864b59029..7d73cabd5 100644
--- a/src/clone.h
+++ b/src/clone.h
@@ -11,6 +11,10 @@
#include "git2/clone.h"
+extern int git_clone__submodule(git_repository **out,
+ const char *url, const char *local_path,
+ const git_clone_options *_options);
+
extern int git_clone__should_clone_local(const char *url, git_clone_local_t local);
#endif
diff --git a/src/features.h.in b/src/features.h.in
index f2931cb11..e000de5e0 100644
--- a/src/features.h.in
+++ b/src/features.h.in
@@ -27,9 +27,9 @@
#cmakedefine GIT_NTLM 1
#cmakedefine GIT_GSSAPI 1
-#cmakedefine GIT_WINHTTP 1
-#cmakedefine GIT_NTLM 1
+#cmakedefine GIT_GSSFRAMEWORK 1
+#cmakedefine GIT_WINHTTP 1
#cmakedefine GIT_HTTPS 1
#cmakedefine GIT_OPENSSL 1
#cmakedefine GIT_SECURE_TRANSPORT 1
diff --git a/src/patch_parse.c b/src/patch_parse.c
index 51c4bb200..126918249 100644
--- a/src/patch_parse.c
+++ b/src/patch_parse.c
@@ -389,6 +389,7 @@ static const parse_header_transition transitions[] = {
{ "index " , STATE_DIFF, STATE_INDEX, parse_header_git_index },
{ "index " , STATE_END, STATE_INDEX, parse_header_git_index },
+ { "--- " , STATE_DIFF, STATE_PATH, parse_header_git_oldpath },
{ "--- " , STATE_INDEX, STATE_PATH, parse_header_git_oldpath },
{ "+++ " , STATE_PATH, STATE_END, parse_header_git_newpath },
{ "GIT binary patch" , STATE_INDEX, STATE_END, NULL },
diff --git a/src/submodule.c b/src/submodule.c
index cf89fc99b..d12dbcfee 100644
--- a/src/submodule.c
+++ b/src/submodule.c
@@ -23,6 +23,7 @@
#include "path.h"
#include "index.h"
#include "worktree.h"
+#include "clone.h"
#define GIT_MODULES_FILE ".gitmodules"
@@ -815,6 +816,64 @@ done:
return error;
}
+static int clone_return_origin(git_remote **out, git_repository *repo, const char *name, const char *url, void *payload)
+{
+ GIT_UNUSED(url);
+ GIT_UNUSED(payload);
+ return git_remote_lookup(out, repo, name);
+}
+
+static int clone_return_repo(git_repository **out, const char *path, int bare, void *payload)
+{
+ git_submodule *sm = payload;
+
+ GIT_UNUSED(path);
+ GIT_UNUSED(bare);
+ return git_submodule_open(out, sm);
+}
+
+int git_submodule_clone(git_repository **out, git_submodule *submodule, const git_submodule_update_options *given_opts)
+{
+ int error;
+ git_repository *clone;
+ git_buf rel_path = GIT_BUF_INIT;
+ git_submodule_update_options sub_opts = GIT_SUBMODULE_UPDATE_OPTIONS_INIT;
+ git_clone_options opts = GIT_CLONE_OPTIONS_INIT;
+
+ assert(submodule);
+
+ if (given_opts)
+ memcpy(&sub_opts, given_opts, sizeof(sub_opts));
+
+ GIT_ERROR_CHECK_VERSION(&sub_opts, GIT_SUBMODULE_UPDATE_OPTIONS_VERSION, "git_submodule_update_options");
+
+ memcpy(&opts.checkout_opts, &sub_opts.checkout_opts, sizeof(sub_opts.checkout_opts));
+ memcpy(&opts.fetch_opts, &sub_opts.fetch_opts, sizeof(sub_opts.fetch_opts));
+ opts.repository_cb = clone_return_repo;
+ opts.repository_cb_payload = submodule;
+ opts.remote_cb = clone_return_origin;
+ opts.remote_cb_payload = submodule;
+
+ git_buf_puts(&rel_path, git_repository_workdir(git_submodule_owner(submodule)));
+ git_buf_joinpath(&rel_path, git_buf_cstr(&rel_path), git_submodule_path(submodule));
+
+ GIT_ERROR_CHECK_ALLOC_BUF(&rel_path);
+
+ error = git_clone__submodule(&clone, git_submodule_url(submodule), git_buf_cstr(&rel_path), &opts);
+ if (error < 0)
+ goto cleanup;
+
+ if (!out)
+ git_repository_free(clone);
+ else
+ *out = clone;
+
+cleanup:
+ git_buf_dispose(&rel_path);
+
+ return error;
+}
+
int git_submodule_add_finalize(git_submodule *sm)
{
int error;
diff --git a/src/transports/auth_negotiate.c b/src/transports/auth_negotiate.c
index b7eb42581..26315433d 100644
--- a/src/transports/auth_negotiate.c
+++ b/src/transports/auth_negotiate.c
@@ -7,15 +7,19 @@
#include "auth_negotiate.h"
-#ifdef GIT_GSSAPI
+#if defined(GIT_GSSAPI) || defined(GIT_GSSFRAMEWORK)
#include "git2.h"
#include "buffer.h"
#include "auth.h"
#include "git2/sys/cred.h"
+#ifdef GIT_GSSFRAMEWORK
+#import <GSS/GSS.h>
+#elif defined(GIT_GSSAPI)
#include <gssapi.h>
#include <krb5.h>
+#endif
static gss_OID_desc negotiate_oid_spnego =
{ 6, (void *) "\x2b\x06\x01\x05\x05\x02" };
diff --git a/src/transports/auth_negotiate.h b/src/transports/auth_negotiate.h
index d3f2ba2a1..34aff295b 100644
--- a/src/transports/auth_negotiate.h
+++ b/src/transports/auth_negotiate.h
@@ -12,7 +12,7 @@
#include "git2.h"
#include "auth.h"
-#ifdef GIT_GSSAPI
+#if defined(GIT_GSSAPI) || defined(GIT_GSSFRAMEWORK)
extern int git_http_auth_negotiate(
git_http_auth_context **out,
diff --git a/src/util.c b/src/util.c
index fdd8e9afa..859e0a82b 100644
--- a/src/util.c
+++ b/src/util.c
@@ -719,6 +719,10 @@ static int GIT_STDLIB_CALL git__qsort_r_glue_cmp(
}
#endif
+
+#if !defined(HAVE_QSORT_R_BSD) && \
+ !defined(HAVE_QSORT_R_GNU) && \
+ !defined(HAVE_QSORT_S)
static void swap(uint8_t *a, uint8_t *b, size_t elsize)
{
char tmp[256];
@@ -744,6 +748,7 @@ static void insertsort(
for (j = i; j > base && cmp(j, j - elsize, payload) < 0; j -= elsize)
swap(j, j - elsize, elsize);
}
+#endif
void git__qsort_r(
void *els, size_t nel, size_t elsize, git__sort_r_cmp cmp, void *payload)
diff --git a/tests/clone/nonetwork.c b/tests/clone/nonetwork.c
index 2b8081f8a..7ca49085c 100644
--- a/tests/clone/nonetwork.c
+++ b/tests/clone/nonetwork.c
@@ -1,7 +1,6 @@
#include "clar_libgit2.h"
#include "git2/clone.h"
-#include "git2/sys/commit.h"
#include "../submodule/submodule_helpers.h"
#include "remote.h"
#include "futils.h"
@@ -352,56 +351,3 @@ void test_clone_nonetwork__clone_from_empty_sets_upstream(void)
git_repository_free(repo);
cl_fixture_cleanup("./repowithunborn");
}
-
-static int just_return_origin(git_remote **out, git_repository *repo, const char *name, const char *url, void *payload)
-{
- GIT_UNUSED(url); GIT_UNUSED(payload);
-
- return git_remote_lookup(out, repo, name);
-}
-
-static int just_return_repo(git_repository **out, const char *path, int bare, void *payload)
-{
- git_submodule *sm = payload;
-
- GIT_UNUSED(path); GIT_UNUSED(bare);
-
- return git_submodule_open(out, sm);
-}
-
-void test_clone_nonetwork__clone_submodule(void)
-{
- git_clone_options clone_opts = GIT_CLONE_OPTIONS_INIT;
- git_index *index;
- git_oid tree_id, commit_id;
- git_submodule *sm;
- git_signature *sig;
- git_repository *sm_repo;
-
- cl_git_pass(git_repository_init(&g_repo, "willaddsubmodule", false));
-
-
- /* Create the submodule structure, clone into it and finalize */
- cl_git_pass(git_submodule_add_setup(&sm, g_repo, cl_fixture("testrepo.git"), "testrepo", true));
-
- clone_opts.repository_cb = just_return_repo;
- clone_opts.repository_cb_payload = sm;
- clone_opts.remote_cb = just_return_origin;
- clone_opts.remote_cb_payload = sm;
- cl_git_pass(git_clone(&sm_repo, cl_fixture("testrepo.git"), "testrepo", &clone_opts));
- cl_git_pass(git_submodule_add_finalize(sm));
- git_repository_free(sm_repo);
- git_submodule_free(sm);
-
- cl_git_pass(git_repository_index(&index, g_repo));
- cl_git_pass(git_index_write_tree(&tree_id, index));
- git_index_free(index);
-
- cl_git_pass(git_signature_now(&sig, "Submoduler", "submoduler@local"));
- cl_git_pass(git_commit_create_from_ids(&commit_id, g_repo, "HEAD", sig, sig, NULL, "A submodule\n",
- &tree_id, 0, NULL));
-
- git_signature_free(sig);
-
- assert_submodule_exists(g_repo, "testrepo");
-}
diff --git a/tests/diff/parse.c b/tests/diff/parse.c
index 7d9f4b2e5..b004d1e23 100644
--- a/tests/diff/parse.c
+++ b/tests/diff/parse.c
@@ -98,6 +98,16 @@ void test_diff_parse__empty_file(void)
git_diff_free(diff);
}
+void test_diff_parse__no_extended_headers(void)
+{
+ const char *content = PATCH_NO_EXTENDED_HEADERS;
+ git_diff *diff;
+
+ cl_git_pass(git_diff_from_buffer(
+ &diff, content, strlen(content)));
+ git_diff_free(diff);
+}
+
void test_diff_parse__invalid_patches_fails(void)
{
test_parse_invalid_diff(PATCH_CORRUPT_MISSING_NEW_FILE);
diff --git a/tests/patch/patch_common.h b/tests/patch/patch_common.h
index 690e0a662..d730d142c 100644
--- a/tests/patch/patch_common.h
+++ b/tests/patch/patch_common.h
@@ -895,3 +895,13 @@
"+++ b/test-file\r\n" \
"@@ -0,0 +1 @@\r\n" \
"+a contents\r\n"
+
+#define PATCH_NO_EXTENDED_HEADERS \
+ "diff --git a/file b/file\n" \
+ "--- a/file\n" \
+ "+++ b/file\n" \
+ "@@ -1,3 +1,3 @@\n" \
+ " a\n" \
+ "-b\n" \
+ "+bb\n" \
+ " c\n"
diff --git a/tests/submodule/add.c b/tests/submodule/add.c
index b251b331e..f4d1e3b79 100644
--- a/tests/submodule/add.c
+++ b/tests/submodule/add.c
@@ -5,6 +5,7 @@
#include "config/config_helpers.h"
#include "futils.h"
#include "repository.h"
+#include "git2/sys/commit.h"
static git_repository *g_repo = NULL;
static const char *valid_blob_id = "fa49b077972391ad58037050f2a75f74e3671e92";
@@ -183,3 +184,68 @@ void test_submodule_add__file_exists_in_index(void)
git_submodule_free(sm);
git_buf_dispose(&name);
}
+
+void test_submodule_add__submodule_clone(void)
+{
+ git_oid tree_id, commit_id;
+ git_signature *sig;
+ git_submodule *sm;
+ git_index *index;
+
+ g_repo = cl_git_sandbox_init("empty_standard_repo");
+
+ /* Create the submodule structure, clone into it and finalize */
+ cl_git_pass(git_submodule_add_setup(&sm, g_repo, cl_fixture("testrepo.git"), "testrepo-add", true));
+ cl_git_pass(git_submodule_clone(NULL, sm, NULL));
+ cl_git_pass(git_submodule_add_finalize(sm));
+
+ /* Create the submodule commit */
+ cl_git_pass(git_repository_index(&index, g_repo));
+ cl_git_pass(git_index_write_tree(&tree_id, index));
+ cl_git_pass(git_signature_now(&sig, "Submoduler", "submoduler@local"));
+ cl_git_pass(git_commit_create_from_ids(&commit_id, g_repo, "HEAD", sig, sig, NULL, "A submodule\n",
+ &tree_id, 0, NULL));
+
+ assert_submodule_exists(g_repo, "testrepo-add");
+
+ git_signature_free(sig);
+ git_submodule_free(sm);
+ git_index_free(index);
+}
+
+void test_submodule_add__submodule_clone_into_nonempty_dir_succeeds(void)
+{
+ git_submodule *sm;
+
+ g_repo = cl_git_sandbox_init("empty_standard_repo");
+
+ cl_git_pass(p_mkdir("empty_standard_repo/sm", 0777));
+ cl_git_mkfile("empty_standard_repo/sm/foobar", "");
+
+ /* Create the submodule structure, clone into it and finalize */
+ cl_git_pass(git_submodule_add_setup(&sm, g_repo, cl_fixture("testrepo.git"), "sm", true));
+ cl_git_pass(git_submodule_clone(NULL, sm, NULL));
+ cl_git_pass(git_submodule_add_finalize(sm));
+
+ cl_assert(git_path_exists("empty_standard_repo/sm/foobar"));
+
+ assert_submodule_exists(g_repo, "sm");
+
+ git_submodule_free(sm);
+}
+
+void test_submodule_add__submodule_clone_twice_fails(void)
+{
+ git_submodule *sm;
+
+ g_repo = cl_git_sandbox_init("empty_standard_repo");
+
+ /* Create the submodule structure, clone into it and finalize */
+ cl_git_pass(git_submodule_add_setup(&sm, g_repo, cl_fixture("testrepo.git"), "sm", true));
+ cl_git_pass(git_submodule_clone(NULL, sm, NULL));
+ cl_git_pass(git_submodule_add_finalize(sm));
+
+ cl_git_fail(git_submodule_clone(NULL, sm, NULL));
+
+ git_submodule_free(sm);
+}