diff options
-rw-r--r-- | CMakeLists.txt | 8 | ||||
-rw-r--r-- | src/CMakeLists.txt | 2 | ||||
-rw-r--r-- | src/checkout.c | 7 | ||||
-rw-r--r-- | src/fetchhead.c | 2 | ||||
-rw-r--r-- | src/fileops.c | 10 | ||||
-rw-r--r-- | src/fileops.h | 5 | ||||
-rw-r--r-- | src/indexer.c | 10 | ||||
-rw-r--r-- | src/pack.c | 17 | ||||
-rw-r--r-- | src/patch_parse.c | 50 | ||||
-rw-r--r-- | src/remote.c | 17 | ||||
-rw-r--r-- | src/streams/openssl.c | 29 | ||||
-rw-r--r-- | tests/fetchhead/nonetwork.c | 88 | ||||
-rw-r--r-- | tests/merge/workdir/submodules.c | 36 | ||||
-rw-r--r-- | tests/pack/indexer.c | 61 | ||||
-rw-r--r-- | tests/patch/parse.c | 6 | ||||
-rw-r--r-- | tests/patch/patch_common.h | 10 | ||||
-rw-r--r-- | tests/resources/merge-resolve/.gitted/objects/50/c5dc8cdfe40c688eb0a0e23be54dd57cae2e78 | 2 | ||||
-rw-r--r-- | tests/resources/merge-resolve/.gitted/objects/7a/a825857f87aea74ddf13d954568aa30dfcdeb4 | bin | 0 -> 117 bytes | |||
-rw-r--r-- | tests/resources/merge-resolve/.gitted/refs/heads/delete-submodule | 1 |
19 files changed, 313 insertions, 48 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index 549f34ad8..bedf85819 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -43,7 +43,6 @@ OPTION( ENABLE_TRACE "Enables tracing support" OFF ) OPTION( LIBGIT2_FILENAME "Name of the produced binary" OFF ) OPTION( USE_SHA1DC "Use SHA-1 with collision detection" OFF ) -OPTION( USE_ICONV "Link with and use iconv library" OFF ) OPTION( USE_SSH "Link with libssh to enable SSH support" ON ) OPTION( USE_HTTPS "Enable HTTPS support. Can be set to a specific backend" ON ) OPTION( USE_GSSAPI "Link with libgssapi for SPNEGO auth" OFF ) @@ -52,10 +51,15 @@ OPTION( CURL "Use curl for HTTP if available" ON) OPTION( USE_EXT_HTTP_PARSER "Use system HTTP_Parser if available" ON) OPTION( DEBUG_POOL "Enable debug pool allocator" OFF ) OPTION( ENABLE_WERROR "Enable compilation with -Werror" OFF ) +OPTION( USE_BUNDLED_ZLIB "Use the bundled version of zlib" OFF ) + IF (UNIX AND NOT APPLE) OPTION( ENABLE_REPRODUCIBLE_BUILDS "Enable reproducible builds" OFF ) ENDIF() -OPTION( USE_BUNDLED_ZLIB "Use the bundled version of zlib" OFF ) + +IF (APPLE) + OPTION( USE_ICONV "Link with and use iconv library" ON ) +ENDIF() IF(MSVC) # This option is only available when building with MSVC. By default, libgit2 diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index e456ab725..2c82d1f59 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -310,7 +310,7 @@ ENDIF() ADD_FEATURE_INFO(SPNEGO GIT_GSSAPI "SPNEGO authentication support") # Optional external dependency: iconv -IF (USE_ICONV OR CMAKE_SYSTEM_NAME MATCHES "Darwin") +IF (USE_ICONV) FIND_PACKAGE(Iconv) ENDIF() IF (ICONV_FOUND) diff --git a/src/checkout.c b/src/checkout.c index caed6cdf1..528fbdf92 100644 --- a/src/checkout.c +++ b/src/checkout.c @@ -2022,8 +2022,11 @@ static int checkout_write_entry( (error = checkout_safe_for_update_only(data, fullpath->ptr, side->mode)) <= 0) return error; - return checkout_write_content(data, - &side->id, fullpath->ptr, hint_path, side->mode, &st); + if (!S_ISGITLINK(side->mode)) + return checkout_write_content(data, + &side->id, fullpath->ptr, hint_path, side->mode, &st); + + return 0; } static int checkout_write_entries( diff --git a/src/fetchhead.c b/src/fetchhead.c index ac25723d3..e55e7c85b 100644 --- a/src/fetchhead.c +++ b/src/fetchhead.c @@ -118,7 +118,7 @@ int git_fetchhead_write(git_repository *repo, git_vector *fetchhead_refs) if (git_buf_joinpath(&path, repo->gitdir, GIT_FETCH_HEAD_FILE) < 0) return -1; - if (git_filebuf_open(&file, path.ptr, GIT_FILEBUF_FORCE, GIT_REFS_FILE_MODE) < 0) { + if (git_filebuf_open(&file, path.ptr, GIT_FILEBUF_APPEND, GIT_REFS_FILE_MODE) < 0) { git_buf_free(&path); return -1; } diff --git a/src/fileops.c b/src/fileops.c index ad3f67e2b..58988c2d2 100644 --- a/src/fileops.c +++ b/src/fileops.c @@ -102,6 +102,16 @@ int git_futils_open_ro(const char *path) return fd; } +int git_futils_truncate(const char *path, int mode) +{ + int fd = p_open(path, O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC, mode); + if (fd < 0) + return git_path_set_error(errno, path, "open"); + + close(fd); + return 0; +} + git_off_t git_futils_filesize(git_file fd) { struct stat sb; diff --git a/src/fileops.h b/src/fileops.h index fd5441243..57b9d173e 100644 --- a/src/fileops.h +++ b/src/fileops.h @@ -248,6 +248,11 @@ extern int git_futils_cp_r( extern int git_futils_open_ro(const char *path); /** + * Truncate a file, creating it if it doesn't exist. + */ +extern int git_futils_truncate(const char *path, int mode); + +/** * Get the filesize in bytes of a file */ extern git_off_t git_futils_filesize(git_file fd); diff --git a/src/indexer.c b/src/indexer.c index 7eec0d612..a5e842272 100644 --- a/src/indexer.c +++ b/src/indexer.c @@ -844,6 +844,7 @@ static int fix_thin_pack(git_indexer *idx, git_transfer_progress *stats) static int resolve_deltas(git_indexer *idx, git_transfer_progress *stats) { unsigned int i; + int error; struct delta_info *delta; int progressed = 0, non_null = 0, progress_cb_result; @@ -858,8 +859,13 @@ static int resolve_deltas(git_indexer *idx, git_transfer_progress *stats) non_null = 1; idx->off = delta->delta_off; - if (git_packfile_unpack(&obj, idx->pack, &idx->off) < 0) - continue; + if ((error = git_packfile_unpack(&obj, idx->pack, &idx->off)) < 0) { + if (error == GIT_PASSTHROUGH) { + /* We have not seen the base object, we'll try again later. */ + continue; + } + return -1; + } if (hash_and_save(idx, &obj, delta->delta_off) < 0) continue; diff --git a/src/pack.c b/src/pack.c index 7fd95c905..9ed3ec1af 100644 --- a/src/pack.c +++ b/src/pack.c @@ -716,8 +716,11 @@ int git_packfile_unpack( error = packfile_unpack_compressed(&delta, p, &w_curs, &curpos, elem->size, elem->type); git_mwindow_close(&w_curs); - if (error < 0) + if (error < 0) { + /* We have transferred ownership of the data to the cache. */ + obj->data = NULL; break; + } /* the current object becomes the new base, on which we apply the delta */ base = *obj; @@ -934,19 +937,19 @@ git_off_t get_delta_base( if (type == GIT_OBJ_OFS_DELTA) { unsigned used = 0; unsigned char c = base_info[used++]; - base_offset = c & 127; + size_t unsigned_base_offset = c & 127; while (c & 128) { if (left <= used) return GIT_EBUFS; - base_offset += 1; - if (!base_offset || MSB(base_offset, 7)) + unsigned_base_offset += 1; + if (!unsigned_base_offset || MSB(unsigned_base_offset, 7)) return 0; /* overflow */ c = base_info[used++]; - base_offset = (base_offset << 7) + (c & 127); + unsigned_base_offset = (unsigned_base_offset << 7) + (c & 127); } - base_offset = delta_obj_offset - base_offset; - if (base_offset <= 0 || base_offset >= delta_obj_offset) + if (unsigned_base_offset == 0 || (size_t)delta_obj_offset <= unsigned_base_offset) return 0; /* out of bound */ + base_offset = delta_obj_offset - unsigned_base_offset; *curpos += used; } else if (type == GIT_OBJ_REF_DELTA) { /* If we have the cooperative cache, search in it first */ diff --git a/src/patch_parse.c b/src/patch_parse.c index 48afcc1ed..27c01e96f 100644 --- a/src/patch_parse.c +++ b/src/patch_parse.c @@ -53,11 +53,9 @@ static int header_path_len(git_patch_parse_ctx *ctx) return len; } -static int parse_header_path_buf(git_buf *path, git_patch_parse_ctx *ctx) +static int parse_header_path_buf(git_buf *path, git_patch_parse_ctx *ctx, size_t path_len) { - int path_len, error = 0; - - path_len = header_path_len(ctx); + int error; if ((error = git_buf_put(path, ctx->parse_ctx.line, path_len)) < 0) goto done; @@ -81,7 +79,7 @@ done: static int parse_header_path(char **out, git_patch_parse_ctx *ctx) { git_buf path = GIT_BUF_INIT; - int error = parse_header_path_buf(&path, ctx); + int error = parse_header_path_buf(&path, ctx, header_path_len(ctx)); *out = git_buf_detach(&path); @@ -91,13 +89,33 @@ static int parse_header_path(char **out, git_patch_parse_ctx *ctx) static int parse_header_git_oldpath( git_patch_parsed *patch, git_patch_parse_ctx *ctx) { - return parse_header_path(&patch->old_path, ctx); + git_buf old_path = GIT_BUF_INIT; + int error; + + if ((error = parse_header_path_buf(&old_path, ctx, ctx->parse_ctx.line_len - 1)) < 0) + goto out; + + patch->old_path = git_buf_detach(&old_path); + +out: + git_buf_free(&old_path); + return error; } static int parse_header_git_newpath( git_patch_parsed *patch, git_patch_parse_ctx *ctx) { - return parse_header_path(&patch->new_path, ctx); + git_buf new_path = GIT_BUF_INIT; + int error; + + if ((error = parse_header_path_buf(&new_path, ctx, ctx->parse_ctx.line_len - 1)) < 0) + goto out; + + patch->new_path = git_buf_detach(&new_path); + +out: + git_buf_free(&new_path); + return error; } static int parse_header_mode(uint16_t *mode, git_patch_parse_ctx *ctx) @@ -213,7 +231,7 @@ static int parse_header_rename( { git_buf path = GIT_BUF_INIT; - if (parse_header_path_buf(&path, ctx) < 0) + if (parse_header_path_buf(&path, ctx, header_path_len(ctx)) < 0) return -1; /* Note: the `rename from` and `rename to` lines include the literal @@ -303,6 +321,22 @@ static int parse_header_start(git_patch_parsed *patch, git_patch_parse_ctx *ctx) return git_parse_err("corrupt new path in git diff header at line %"PRIuZ, ctx->parse_ctx.line_num); + /* + * We cannot expect to be able to always parse paths correctly at this + * point. Due to the possibility of unquoted names, whitespaces in + * filenames and custom prefixes we have to allow that, though, and just + * proceeed here. We then hope for the "---" and "+++" lines to fix that + * for us. + */ + if (!git_parse_ctx_contains(&ctx->parse_ctx, "\n", 1)) { + git_parse_advance_chars(&ctx->parse_ctx, ctx->parse_ctx.line_len - 1); + + git__free(patch->header_old_path); + patch->header_old_path = NULL; + git__free(patch->header_new_path); + patch->header_new_path = NULL; + } + return 0; } diff --git a/src/remote.c b/src/remote.c index 303911760..4d675af82 100644 --- a/src/remote.c +++ b/src/remote.c @@ -1541,6 +1541,20 @@ cleanup: return error; } +static int truncate_fetch_head(const char *gitdir) +{ + git_buf path = GIT_BUF_INIT; + int error; + + if ((error = git_buf_joinpath(&path, gitdir, GIT_FETCH_HEAD_FILE)) < 0) + return error; + + error = git_futils_truncate(path.ptr, GIT_REFS_FILE_MODE); + git_buf_free(&path); + + return error; +} + int git_remote_update_tips( git_remote *remote, const git_remote_callbacks *callbacks, @@ -1571,6 +1585,9 @@ int git_remote_update_tips( else tagopt = download_tags; + if ((error = truncate_fetch_head(git_repository_path(remote->repo))) < 0) + goto out; + if (tagopt == GIT_REMOTE_DOWNLOAD_TAGS_ALL) { if ((error = update_tips_for_spec(remote, callbacks, update_fetchhead, tagopt, &tagspec, &refs, reflog_message)) < 0) goto out; diff --git a/src/streams/openssl.c b/src/streams/openssl.c index 2b246002f..9d566074c 100644 --- a/src/streams/openssl.c +++ b/src/streams/openssl.c @@ -332,7 +332,7 @@ static int check_host_name(const char *name, const char *host) static int verify_server_cert(SSL *ssl, const char *host) { - X509 *cert; + X509 *cert = NULL; X509_NAME *peer_name; ASN1_STRING *str; unsigned char *peer_cn = NULL; @@ -341,7 +341,7 @@ static int verify_server_cert(SSL *ssl, const char *host) struct in6_addr addr6; struct in_addr addr4; void *addr; - int i = -1,j; + int i = -1, j, error = 0; if (SSL_get_verify_result(ssl) != X509_V_OK) { giterr_set(GITERR_SSL, "the SSL certificate is invalid"); @@ -362,8 +362,9 @@ static int verify_server_cert(SSL *ssl, const char *host) cert = SSL_get_peer_certificate(ssl); if (!cert) { + error = -1; giterr_set(GITERR_SSL, "the server did not provide a certificate"); - return -1; + goto cleanup; } /* Check the alternative names */ @@ -401,8 +402,9 @@ static int verify_server_cert(SSL *ssl, const char *host) if (matched == 0) goto cert_fail_name; - if (matched == 1) - return 0; + if (matched == 1) { + goto cleanup; + } /* If no alternative names are available, check the common name */ peer_name = X509_get_subject_name(cert); @@ -444,18 +446,21 @@ static int verify_server_cert(SSL *ssl, const char *host) if (check_host_name((char *)peer_cn, host) < 0) goto cert_fail_name; - OPENSSL_free(peer_cn); + goto cleanup; - return 0; +cert_fail_name: + error = GIT_ECERTIFICATE; + giterr_set(GITERR_SSL, "hostname does not match certificate"); + goto cleanup; on_error: - OPENSSL_free(peer_cn); - return ssl_set_error(ssl, 0); + error = ssl_set_error(ssl, 0); + goto cleanup; -cert_fail_name: +cleanup: + X509_free(cert); OPENSSL_free(peer_cn); - giterr_set(GITERR_SSL, "hostname does not match certificate"); - return GIT_ECERTIFICATE; + return error; } typedef struct { diff --git a/tests/fetchhead/nonetwork.c b/tests/fetchhead/nonetwork.c index ea4b70e4a..4dabb577e 100644 --- a/tests/fetchhead/nonetwork.c +++ b/tests/fetchhead/nonetwork.c @@ -353,20 +353,25 @@ void test_fetchhead_nonetwork__quote_in_branch_name(void) } static bool found_master; -static bool find_master_called; +static bool found_haacked; +static bool find_master_haacked_called; -int find_master(const char *ref_name, const char *remote_url, const git_oid *oid, unsigned int is_merge, void *payload) +int find_master_haacked(const char *ref_name, const char *remote_url, const git_oid *oid, unsigned int is_merge, void *payload) { GIT_UNUSED(remote_url); GIT_UNUSED(oid); GIT_UNUSED(payload); - find_master_called = true; + find_master_haacked_called = true; if (!strcmp("refs/heads/master", ref_name)) { cl_assert(is_merge); found_master = true; } + if (!strcmp("refs/heads/haacked", ref_name)) { + cl_assert(is_merge); + found_haacked = true; + } return 0; } @@ -375,10 +380,12 @@ void test_fetchhead_nonetwork__create_when_refpecs_given(void) { git_remote *remote; git_buf path = GIT_BUF_INIT; - char *refspec = "refs/heads/master"; + char *refspec1 = "refs/heads/master"; + char *refspec2 = "refs/heads/haacked"; + char *refspecs[] = { refspec1, refspec2 }; git_strarray specs = { - &refspec, - 1, + refspecs, + 2, }; cl_set_cleanup(&cleanup_repository, "./test1"); @@ -391,9 +398,74 @@ void test_fetchhead_nonetwork__create_when_refpecs_given(void) cl_git_pass(git_remote_fetch(remote, &specs, NULL, NULL)); cl_assert(git_path_exists(path.ptr)); - cl_git_pass(git_repository_fetchhead_foreach(g_repo, find_master, NULL)); - cl_assert(find_master_called); + cl_git_pass(git_repository_fetchhead_foreach(g_repo, find_master_haacked, NULL)); + cl_assert(find_master_haacked_called); cl_assert(found_master); + cl_assert(found_haacked); + + git_remote_free(remote); + git_buf_free(&path); +} + +static bool count_refs_called; +struct prefix_count { + const char *prefix; + int count; + int expected; +}; + +int count_refs(const char *ref_name, const char *remote_url, const git_oid *oid, unsigned int is_merge, void *payload) +{ + int i; + struct prefix_count *prefix_counts = (struct prefix_count *) payload; + + GIT_UNUSED(remote_url); + GIT_UNUSED(oid); + GIT_UNUSED(is_merge); + + count_refs_called = true; + + for (i = 0; prefix_counts[i].prefix; i++) { + if (!git__prefixcmp(ref_name, prefix_counts[i].prefix)) + prefix_counts[i].count++; + } + + return 0; +} + +void test_fetchhead_nonetwork__create_with_multiple_refspecs(void) +{ + git_remote *remote; + git_buf path = GIT_BUF_INIT; + + cl_set_cleanup(&cleanup_repository, "./test1"); + cl_git_pass(git_repository_init(&g_repo, "./test1", 0)); + + cl_git_pass(git_remote_create(&remote, g_repo, "origin", cl_fixture("testrepo.git"))); + git_remote_free(remote); + cl_git_pass(git_remote_add_fetch(g_repo, "origin", "+refs/notes/*:refs/origin/notes/*")); + /* Pick up the new refspec */ + cl_git_pass(git_remote_lookup(&remote, g_repo, "origin")); + + cl_git_pass(git_buf_joinpath(&path, git_repository_path(g_repo), "FETCH_HEAD")); + cl_assert(!git_path_exists(path.ptr)); + cl_git_pass(git_remote_fetch(remote, NULL, NULL, NULL)); + cl_assert(git_path_exists(path.ptr)); + + { + int i; + struct prefix_count prefix_counts[] = { + {"refs/notes/", 0, 1}, + {"refs/heads/", 0, 12}, + {"refs/tags/", 0, 7}, + {NULL, 0, 0}, + }; + + cl_git_pass(git_repository_fetchhead_foreach(g_repo, count_refs, &prefix_counts)); + cl_assert(count_refs_called); + for (i = 0; prefix_counts[i].prefix; i++) + cl_assert_equal_i(prefix_counts[i].expected, prefix_counts[i].count); + } git_remote_free(remote); git_buf_free(&path); diff --git a/tests/merge/workdir/submodules.c b/tests/merge/workdir/submodules.c index 7c18c2ffb..c4cc188a8 100644 --- a/tests/merge/workdir/submodules.c +++ b/tests/merge/workdir/submodules.c @@ -12,6 +12,7 @@ static git_repository *repo; #define SUBMODULE_MAIN_BRANCH "submodules" #define SUBMODULE_OTHER_BRANCH "submodules-branch" #define SUBMODULE_OTHER2_BRANCH "submodules-branch2" +#define SUBMODULE_DELETE_BRANCH "delete-submodule" #define TEST_INDEX_PATH TEST_REPO_PATH "/.git/index" @@ -93,3 +94,38 @@ void test_merge_workdir_submodules__take_changed(void) git_reference_free(their_ref); git_reference_free(our_ref); } + + +void test_merge_workdir_submodules__update_delete_conflict(void) +{ + git_reference *our_ref, *their_ref; + git_commit *our_commit; + git_annotated_commit *their_head; + git_index *index; + + struct merge_index_entry merge_index_entries[] = { + { 0100644, "e69de29bb2d1d6434b8b29ae775ad8c2e48c5391", 0, ".gitmodules" }, + { 0100644, "5887a5e516c53bd58efb0f02ec6aa031b6fe9ad7", 0, "file1.txt" }, + { 0100644, "4218670ab81cc219a9f94befb5c5dad90ec52648", 0, "file2.txt" }, + { 0160000, "d3d806a4bef96889117fd7ebac0e3cb5ec152932", 1, "submodule"}, + { 0160000, "297aa6cd028b3336c7802c7a6f49143da4e1602d", 3, "submodule" }, + }; + + cl_git_pass(git_reference_lookup(&our_ref, repo, "refs/heads/" SUBMODULE_DELETE_BRANCH)); + cl_git_pass(git_commit_lookup(&our_commit, repo, git_reference_target(our_ref))); + cl_git_pass(git_reset(repo, (git_object *)our_commit, GIT_RESET_HARD, NULL)); + + cl_git_pass(git_reference_lookup(&their_ref, repo, "refs/heads/" SUBMODULE_MAIN_BRANCH)); + cl_git_pass(git_annotated_commit_from_ref(&their_head, repo, their_ref)); + + cl_git_pass(git_merge(repo, (const git_annotated_commit **)&their_head, 1, NULL, NULL)); + + cl_git_pass(git_repository_index(&index, repo)); + cl_assert(merge_test_index(index, merge_index_entries, 5)); + + git_index_free(index); + git_annotated_commit_free(their_head); + git_commit_free(our_commit); + git_reference_free(their_ref); + git_reference_free(our_ref); +} diff --git a/tests/pack/indexer.c b/tests/pack/indexer.c index 4d2d9f60e..f3c2204bd 100644 --- a/tests/pack/indexer.c +++ b/tests/pack/indexer.c @@ -41,6 +41,29 @@ static const unsigned char thin_pack[] = { static const unsigned int thin_pack_len = 78; /* + * Packfile with one object. It references an object which is not in the + * packfile and has a corrupt length (states the deltified stream is 1 byte + * long, where it is actually 6). + */ +static const unsigned char corrupt_thin_pack[] = { + 0x50, 0x41, 0x43, 0x4b, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, + 0x71, 0xe6, 0x8f, 0xe8, 0x12, 0x9b, 0x54, 0x6b, 0x10, 0x1a, 0xee, 0x95, + 0x10, 0xc5, 0x32, 0x8e, 0x7f, 0x21, 0xca, 0x1d, 0x18, 0x78, 0x9c, 0x63, + 0x62, 0x66, 0x4e, 0xcb, 0xcf, 0x07, 0x00, 0x02, 0xac, 0x01, 0x4d, 0x07, + 0x67, 0x03, 0xc5, 0x40, 0x99, 0x49, 0xb1, 0x3b, 0x7d, 0xae, 0x9b, 0x0e, + 0xdd, 0xde, 0xc6, 0x76, 0x43, 0x24, 0x64 +}; +static const unsigned int corrupt_thin_pack_len = 67; + +/* + * Packfile with a missing trailer. + */ +static const unsigned char missing_trailer_pack[] = { + 0x50, 0x41, 0x43, 0x4b, 0x00, 0x00, 0x00, 0x03, 0x00, 0x50, 0xf4, 0x3b, +}; +static const unsigned int missing_trailer_pack_len = 12; + +/* * Packfile that causes the packfile stream to open in a way in which it leaks * the stream reader. */ @@ -71,14 +94,14 @@ void test_pack_indexer__out_of_order(void) git_indexer_free(idx); } -void test_pack_indexer__leaky(void) +void test_pack_indexer__missing_trailer(void) { git_indexer *idx = 0; git_transfer_progress stats = { 0 }; cl_git_pass(git_indexer_new(&idx, ".", 0, NULL, NULL, NULL)); cl_git_pass(git_indexer_append( - idx, leaky_pack, leaky_pack_len, &stats)); + idx, missing_trailer_pack, missing_trailer_pack_len, &stats)); cl_git_fail(git_indexer_commit(idx, &stats)); cl_assert(giterr_last() != NULL); @@ -87,15 +110,14 @@ void test_pack_indexer__leaky(void) git_indexer_free(idx); } -void test_pack_indexer__missing_trailer(void) +void test_pack_indexer__leaky(void) { git_indexer *idx = 0; git_transfer_progress stats = { 0 }; cl_git_pass(git_indexer_new(&idx, ".", 0, NULL, NULL, NULL)); - /* Truncate a valid packfile */ cl_git_pass(git_indexer_append( - idx, out_of_order_pack, out_of_order_pack_len - 20, &stats)); + idx, leaky_pack, leaky_pack_len, &stats)); cl_git_fail(git_indexer_commit(idx, &stats)); cl_assert(giterr_last() != NULL); @@ -170,6 +192,35 @@ void test_pack_indexer__fix_thin(void) } } +void test_pack_indexer__corrupt_length(void) +{ + git_indexer *idx = NULL; + git_transfer_progress stats = { 0 }; + git_repository *repo; + git_odb *odb; + git_oid id, should_id; + + cl_git_pass(git_repository_init(&repo, "thin.git", true)); + cl_git_pass(git_repository_odb(&odb, repo)); + + /* Store the missing base into your ODB so the indexer can fix the pack */ + cl_git_pass(git_odb_write(&id, odb, base_obj, base_obj_len, GIT_OBJ_BLOB)); + git_oid_fromstr(&should_id, "e68fe8129b546b101aee9510c5328e7f21ca1d18"); + cl_assert_equal_oid(&should_id, &id); + + cl_git_pass(git_indexer_new(&idx, ".", 0, odb, NULL, NULL)); + cl_git_pass(git_indexer_append( + idx, corrupt_thin_pack, corrupt_thin_pack_len, &stats)); + cl_git_fail(git_indexer_commit(idx, &stats)); + + cl_assert(giterr_last() != NULL); + cl_assert_equal_i(giterr_last()->klass, GITERR_ZLIB); + + git_indexer_free(idx); + git_odb_free(odb); + git_repository_free(repo); +} + static int find_tmp_file_recurs(void *opaque, git_buf *path) { int error = 0; diff --git a/tests/patch/parse.c b/tests/patch/parse.c index 8350ac2dd..a40ad7b23 100644 --- a/tests/patch/parse.c +++ b/tests/patch/parse.c @@ -102,3 +102,9 @@ void test_patch_parse__invalid_patches_fails(void) strlen(PATCH_CORRUPT_MISSING_HUNK_HEADER), NULL)); } +void test_patch_parse__files_with_whitespaces_succeeds(void) +{ + git_patch *patch; + cl_git_pass(git_patch_from_buffer(&patch, PATCH_NAME_WHITESPACE, strlen(PATCH_NAME_WHITESPACE), NULL)); + git_patch_free(patch); +} diff --git a/tests/patch/patch_common.h b/tests/patch/patch_common.h index a20ebd617..e838e6089 100644 --- a/tests/patch/patch_common.h +++ b/tests/patch/patch_common.h @@ -575,6 +575,16 @@ "+added line with no nl\n" \ "\\ No newline at end of file\n" +#define PATCH_NAME_WHITESPACE \ + "diff --git a/file with spaces.txt b/file with spaces.txt\n" \ + "index 9432026..83759c0 100644\n" \ + "--- a/file with spaces.txt\n" \ + "+++ b/file with spaces.txt\n" \ + "@@ -0,3 +0,2 @@\n" \ + " and this\n" \ + "-is additional context\n" \ + " below it!\n" \ + #define PATCH_CORRUPT_GIT_HEADER \ "diff --git a/file.txt\n" \ "index 9432026..0f39b9a 100644\n" \ diff --git a/tests/resources/merge-resolve/.gitted/objects/50/c5dc8cdfe40c688eb0a0e23be54dd57cae2e78 b/tests/resources/merge-resolve/.gitted/objects/50/c5dc8cdfe40c688eb0a0e23be54dd57cae2e78 new file mode 100644 index 000000000..c04baa14b --- /dev/null +++ b/tests/resources/merge-resolve/.gitted/objects/50/c5dc8cdfe40c688eb0a0e23be54dd57cae2e78 @@ -0,0 +1,2 @@ +x] +0})Jv">x/I6ZhIӞ*aeZC`F6;KLO).y8N^ }a'Ѱ S*gpmHp_sh/O>.PiF?,kJZGoJT
\ No newline at end of file diff --git a/tests/resources/merge-resolve/.gitted/objects/7a/a825857f87aea74ddf13d954568aa30dfcdeb4 b/tests/resources/merge-resolve/.gitted/objects/7a/a825857f87aea74ddf13d954568aa30dfcdeb4 Binary files differnew file mode 100644 index 000000000..b9c06303b --- /dev/null +++ b/tests/resources/merge-resolve/.gitted/objects/7a/a825857f87aea74ddf13d954568aa30dfcdeb4 diff --git a/tests/resources/merge-resolve/.gitted/refs/heads/delete-submodule b/tests/resources/merge-resolve/.gitted/refs/heads/delete-submodule new file mode 100644 index 000000000..1951316d5 --- /dev/null +++ b/tests/resources/merge-resolve/.gitted/refs/heads/delete-submodule @@ -0,0 +1 @@ +50c5dc8cdfe40c688eb0a0e23be54dd57cae2e78 |