diff --git a/.gitattributes b/.gitattributes index f90540b55b1..176a458f94e 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1,2 +1 @@ -*.c eol=lf -*.h eol=lf +* text=auto diff --git a/CHANGELOG.md b/CHANGELOG.md index 99e3759029f..a8e3e18ac07 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -57,6 +57,18 @@ support for HTTPS connections insead of OpenSSL. for understanding whether a side of the diff exists in the presence of a conflict. +* The constructor for a write-stream into the odb now takes + `git_off_t` instead of `size_t` for the size of the blob, which + allows putting large files into the odb on 32-bit systems. + +* The remote's push and pull URLs now honor the url.$URL.insteadOf + configuration. This allows modifying URL prefixes to a custom + value via gitconfig. + +* `git_diff_foreach`, `git_diff_blobs`, `git_diff_blob_to_buffer`, + and `git_diff_buffers` now accept a new binary callback of type + `git_diff_binary_cb` that includes the binary diff information. + ### API additions * The `git_merge_options` gained a `file_flags` member. @@ -94,6 +106,10 @@ support for HTTPS connections insead of OpenSSL. * The enum `git_fetch_prune_t` has been added, letting you specify the pruning behaviour for a fetch. +* A push operation will notify the caller of what updates it indends + to perform on the remote, which provides similar information to + git's pre-push hook. + * `git_stash_apply()` can now apply a stashed state from the stash list, placing the data into the working directory and index. @@ -117,6 +133,13 @@ support for HTTPS connections insead of OpenSSL. a given index entry has a non-zero stage entry, indicating that it is one side of a conflict. +* It is now possible to pass a keypair via a buffer instead of a + path. For this, `GIT_CREDTYPE_SSH_MEMORY` and + `git_cred_ssh_key_memory_new()` have been added. + +* `git_filter_list_contains` will indicate whether a particular + filter will be run in the given filter list. + ### API removals * `git_remote_save()` and `git_remote_clear_refspecs()` have been @@ -180,11 +203,11 @@ support for HTTPS connections insead of OpenSSL. if it is called immediately after creating a rebase session but before you have applied the first patch. -* `git_rebase_options` now contains an optional pointer to - `git_checkout_options` that will be used for functions that modify - the working directory, namely `git_checkout_init`, `git_checkout_next` - and `git_checkout_abort`. As a result, `git_rebase_open` now also - takes a `git_rebase_options` and only the `git_rebase_init` and +* `git_rebase_options` now contains a `git_checkout_options` struct + that will be used for functions that modify the working directory, + namely `git_checkout_init`, `git_checkout_next` and + `git_checkout_abort`. As a result, `git_rebase_open` now also takes + a `git_rebase_options` and only the `git_rebase_init` and `git_rebase_open` functions take a `git_rebase_options`, where they will persist the options to subsequent `git_rebase` calls. @@ -192,6 +215,9 @@ support for HTTPS connections insead of OpenSSL. `fetch_opts` field instead of remote callbacks in `remote_callbacks`. +* The remote callbacks has gained a new member `push_negotiation` + which gets called before sending the update commands to the server. + * The following functions now longer act on a remote instance but change the repository's configuration. Their signatures have changed accordingly: @@ -229,6 +255,9 @@ support for HTTPS connections insead of OpenSSL. index. Specifically, time and file size are 32 bits intead of 64, as these values are truncated. +* `GIT_EMERGECONFLICT` is now `GIT_ECONFLICT`, which more accurately + describes the nature of the error. + v0.22 ------ diff --git a/CMakeLists.txt b/CMakeLists.txt index 181d30127d6..c3c7a154398 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -270,6 +270,11 @@ IF (LIBSSH2_FOUND) LINK_DIRECTORIES(${LIBSSH2_LIBRARY_DIRS}) SET(LIBGIT2_PC_REQUIRES "${LIBGIT2_PC_REQUIRES} libssh2") SET(SSH_LIBRARIES ${LIBSSH2_LIBRARIES}) + + CHECK_LIBRARY_EXISTS(${LIBSSH2_LIBRARIES} libssh2_userauth_publickey_frommemory "" HAVE_LIBSSH2_MEMORY_CREDENTIALS) + IF (HAVE_LIBSSH2_MEMORY_CREDENTIALS) + ADD_DEFINITIONS(-DGIT_SSH_MEMORY_CREDENTIALS) + ENDIF() ELSE() MESSAGE(STATUS "LIBSSH2 not found. Set CMAKE_PREFIX_PATH if it is installed outside of the default search path.") ENDIF() diff --git a/README.md b/README.md index 4d9cd2d1ee3..4ee1fdc2ad1 100644 --- a/README.md +++ b/README.md @@ -201,7 +201,7 @@ Here are the bindings to libgit2 that are currently available: * Objective-C * objective-git * OCaml - * libgit2-ocaml + * ocaml-libgit2 * Parrot Virtual Machine * parrot-libgit2 * Perl diff --git a/appveyor.yml b/appveyor.yml index 9df687ffd53..166fa56b1e1 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -2,6 +2,7 @@ version: '{build}' branches: only: - master + - /^maint.*/ environment: GITTEST_INVASIVE_FS_STRUCTURE: 1 GITTEST_INVASIVE_FS_SIZE: 1 diff --git a/deps/winhttp/winhttp.def b/deps/winhttp/winhttp.def index 1b2d3f0eb44..eecce59c3ad 100644 --- a/deps/winhttp/winhttp.def +++ b/deps/winhttp/winhttp.def @@ -1,29 +1,29 @@ -LIBRARY WINHTTP -EXPORTS -WinHttpAddRequestHeaders@16 -WinHttpCheckPlatform@0 -WinHttpCloseHandle@4 -WinHttpConnect@16 -WinHttpCrackUrl@16 -WinHttpCreateUrl@16 -WinHttpDetectAutoProxyConfigUrl@8 -WinHttpGetDefaultProxyConfiguration@4 -WinHttpGetIEProxyConfigForCurrentUser@4 -WinHttpGetProxyForUrl@16 -WinHttpOpen@20 -WinHttpOpenRequest@28 -WinHttpQueryAuthSchemes@16 -WinHttpQueryDataAvailable@8 -WinHttpQueryHeaders@24 -WinHttpQueryOption@16 -WinHttpReadData@16 -WinHttpReceiveResponse@8 -WinHttpSendRequest@28 -WinHttpSetCredentials@24 -WinHttpSetDefaultProxyConfiguration@4 -WinHttpSetOption@16 -WinHttpSetStatusCallback@16 -WinHttpSetTimeouts@20 -WinHttpTimeFromSystemTime@8 -WinHttpTimeToSystemTime@8 -WinHttpWriteData@16 +LIBRARY WINHTTP +EXPORTS +WinHttpAddRequestHeaders@16 +WinHttpCheckPlatform@0 +WinHttpCloseHandle@4 +WinHttpConnect@16 +WinHttpCrackUrl@16 +WinHttpCreateUrl@16 +WinHttpDetectAutoProxyConfigUrl@8 +WinHttpGetDefaultProxyConfiguration@4 +WinHttpGetIEProxyConfigForCurrentUser@4 +WinHttpGetProxyForUrl@16 +WinHttpOpen@20 +WinHttpOpenRequest@28 +WinHttpQueryAuthSchemes@16 +WinHttpQueryDataAvailable@8 +WinHttpQueryHeaders@24 +WinHttpQueryOption@16 +WinHttpReadData@16 +WinHttpReceiveResponse@8 +WinHttpSendRequest@28 +WinHttpSetCredentials@24 +WinHttpSetDefaultProxyConfiguration@4 +WinHttpSetOption@16 +WinHttpSetStatusCallback@16 +WinHttpSetTimeouts@20 +WinHttpTimeFromSystemTime@8 +WinHttpTimeToSystemTime@8 +WinHttpWriteData@16 diff --git a/examples/describe.c b/examples/describe.c index f7b4b1c200d..4cdf61f75ca 100644 --- a/examples/describe.c +++ b/examples/describe.c @@ -135,6 +135,8 @@ static void parse_options(describe_options *opts, int argc, char **argv) } else if (match_int_arg((int *)&opts->format_options.abbreviated_size, &args, "--abbrev", 0)) { } else if (match_int_arg((int *)&opts->describe_options.max_candidates_tags, &args, "--candidates", 0)) { } else if (match_str_arg(&opts->describe_options.pattern, &args, "--match")) { + } else { + print_usage(); } } diff --git a/include/git2.h b/include/git2.h index a1e78376f43..ac4a63160f8 100644 --- a/include/git2.h +++ b/include/git2.h @@ -57,6 +57,7 @@ #include "git2/submodule.h" #include "git2/tag.h" #include "git2/transport.h" +#include "git2/transaction.h" #include "git2/tree.h" #include "git2/types.h" #include "git2/version.h" diff --git a/include/git2/cred_helpers.h b/include/git2/cred_helpers.h index 1d8809211ce..840c2253696 100644 --- a/include/git2/cred_helpers.h +++ b/include/git2/cred_helpers.h @@ -22,8 +22,8 @@ GIT_BEGIN_DECL * Payload for git_cred_stock_userpass_plaintext. */ typedef struct git_cred_userpass_payload { - char *username; - char *password; + const char *username; + const char *password; } git_cred_userpass_payload; diff --git a/include/git2/diff.h b/include/git2/diff.h index c0d42e30ee0..0ecdc1bed87 100644 --- a/include/git2/diff.h +++ b/include/git2/diff.h @@ -425,6 +425,53 @@ typedef int (*git_diff_file_cb)( float progress, void *payload); +/** + * When producing a binary diff, the binary data returned will be + * either the deflated full ("literal") contents of the file, or + * the deflated binary delta between the two sides (whichever is + * smaller). + */ +typedef enum { + /** There is no binary delta. */ + GIT_DIFF_BINARY_NONE, + + /** The binary data is the literal contents of the file. */ + GIT_DIFF_BINARY_LITERAL, + + /** The binary data is the delta from one side to the other. */ + GIT_DIFF_BINARY_DELTA, +} git_diff_binary_t; + +/** The contents of one of the files in a binary diff. */ +typedef struct { + /** The type of binary data for this file. */ + git_diff_binary_t type; + + /** The binary data, deflated. */ + const char *data; + + /** The length of the binary data. */ + size_t datalen; + + /** The length of the binary data after inflation. */ + size_t inflatedlen; +} git_diff_binary_file; + +/** Structure describing the binary contents of a diff. */ +typedef struct { + git_diff_binary_file old_file; /**< The contents of the old file. */ + git_diff_binary_file new_file; /**< The contents of the new file. */ +} git_diff_binary; + +/** +* When iterating over a diff, callback that will be made for +* binary content within the diff. +*/ +typedef int(*git_diff_binary_cb)( + const git_diff_delta *delta, + const git_diff_binary *binary, + void *payload); + /** * Structure describing a hunk of a diff. */ @@ -897,6 +944,7 @@ GIT_EXTERN(int) git_diff_is_sorted_icase(const git_diff *diff); * * @param diff A git_diff generated by one of the above functions. * @param file_cb Callback function to make per file in the diff. + * @param binary_cb Optional callback to make for binary files. * @param hunk_cb Optional callback to make per hunk of text diff. This * callback is called to describe a range of lines in the * diff. It will not be issued for binary files. @@ -909,6 +957,7 @@ GIT_EXTERN(int) git_diff_is_sorted_icase(const git_diff *diff); GIT_EXTERN(int) git_diff_foreach( git_diff *diff, git_diff_file_cb file_cb, + git_diff_binary_cb binary_cb, git_diff_hunk_cb hunk_cb, git_diff_line_cb line_cb, void *payload); @@ -984,6 +1033,7 @@ GIT_EXTERN(int) git_diff_print( * @param new_as_path Treat new blob as if it had this filename; can be NULL * @param options Options for diff, or NULL for default options * @param file_cb Callback for "file"; made once if there is a diff; can be NULL + * @param binary_cb Callback for binary files; can be NULL * @param hunk_cb Callback for each hunk in diff; can be NULL * @param line_cb Callback for each line in diff; can be NULL * @param payload Payload passed to each callback function @@ -996,6 +1046,7 @@ GIT_EXTERN(int) git_diff_blobs( const char *new_as_path, const git_diff_options *options, git_diff_file_cb file_cb, + git_diff_binary_cb binary_cb, git_diff_hunk_cb hunk_cb, git_diff_line_cb line_cb, void *payload); @@ -1019,6 +1070,7 @@ GIT_EXTERN(int) git_diff_blobs( * @param buffer_as_path Treat buffer as if it had this filename; can be NULL * @param options Options for diff, or NULL for default options * @param file_cb Callback for "file"; made once if there is a diff; can be NULL + * @param binary_cb Callback for binary files; can be NULL * @param hunk_cb Callback for each hunk in diff; can be NULL * @param line_cb Callback for each line in diff; can be NULL * @param payload Payload passed to each callback function @@ -1032,6 +1084,7 @@ GIT_EXTERN(int) git_diff_blob_to_buffer( const char *buffer_as_path, const git_diff_options *options, git_diff_file_cb file_cb, + git_diff_binary_cb binary_cb, git_diff_hunk_cb hunk_cb, git_diff_line_cb line_cb, void *payload); @@ -1051,6 +1104,7 @@ GIT_EXTERN(int) git_diff_blob_to_buffer( * @param new_as_path Treat buffer as if it had this filename; can be NULL * @param options Options for diff, or NULL for default options * @param file_cb Callback for "file"; made once if there is a diff; can be NULL + * @param binary_cb Callback for binary files; can be NULL * @param hunk_cb Callback for each hunk in diff; can be NULL * @param line_cb Callback for each line in diff; can be NULL * @param payload Payload passed to each callback function @@ -1065,6 +1119,7 @@ GIT_EXTERN(int) git_diff_buffers( const char *new_as_path, const git_diff_options *options, git_diff_file_cb file_cb, + git_diff_binary_cb binary_cb, git_diff_hunk_cb hunk_cb, git_diff_line_cb line_cb, void *payload); diff --git a/include/git2/errors.h b/include/git2/errors.h index 31fc6035a41..dda0f8a572a 100644 --- a/include/git2/errors.h +++ b/include/git2/errors.h @@ -38,7 +38,7 @@ typedef enum { GIT_EUNMERGED = -10, /**< Merge in progress prevented operation */ GIT_ENONFASTFORWARD = -11, /**< Reference was not fast-forwardable */ GIT_EINVALIDSPEC = -12, /**< Name/ref spec was not in a valid format */ - GIT_EMERGECONFLICT = -13, /**< Merge conflicts prevented operation */ + GIT_ECONFLICT = -13, /**< Checkout conflicts prevented operation */ GIT_ELOCKED = -14, /**< Lock file prevented operation */ GIT_EMODIFIED = -15, /**< Reference value does not match expected */ GIT_EAUTH = -16, /**< Authentication error */ diff --git a/include/git2/filter.h b/include/git2/filter.h index dc59e63411b..1828903e4f1 100644 --- a/include/git2/filter.h +++ b/include/git2/filter.h @@ -95,6 +95,22 @@ GIT_EXTERN(int) git_filter_list_load( git_filter_mode_t mode, uint32_t flags); +/** + * Query the filter list to see if a given filter (by name) will run. + * The built-in filters "crlf" and "ident" can be queried, otherwise this + * is the name of the filter specified by the filter attribute. + * + * This will return 0 if the given filter is not in the list, or 1 if + * the filter will be applied. + * + * @param filters A loaded git_filter_list (or NULL) + * @param name The name of the filter to query + * @return 1 if the filter is in the list, 0 otherwise + */ +GIT_EXTERN(int) git_filter_list_contains( + git_filter_list *filters, + const char *name); + /** * Apply filter list to a data buffer. * diff --git a/include/git2/remote.h b/include/git2/remote.h index 02d73a0e620..ccd0b43f466 100644 --- a/include/git2/remote.h +++ b/include/git2/remote.h @@ -120,6 +120,9 @@ GIT_EXTERN(const char *) git_remote_name(const git_remote *remote); /** * Get the remote's url * + * If url.*.insteadOf has been configured for this URL, it will + * return the modified URL. + * * @param remote the remote * @return a pointer to the url */ @@ -128,6 +131,9 @@ GIT_EXTERN(const char *) git_remote_url(const git_remote *remote); /** * Get the remote's url for pushing * + * If url.*.pushInsteadOf has been configured for this URL, it + * will return the modified URL. + * * @param remote the remote * @return a pointer to the url or NULL if no special url for pushing is set */ diff --git a/include/git2/transport.h b/include/git2/transport.h index 99fd09a1b3b..2eeebd56589 100644 --- a/include/git2/transport.h +++ b/include/git2/transport.h @@ -108,6 +108,13 @@ typedef enum { * it will ask via this credential type. */ GIT_CREDTYPE_USERNAME = (1u << 5), + + /** + * Credentials read from memory. + * + * Only available for libssh2+OpenSSL for now. + */ + GIT_CREDTYPE_SSH_MEMORY = (1u << 6), } git_credtype_t; /* The base structure for all credential types */ @@ -290,6 +297,23 @@ GIT_EXTERN(int) git_cred_default_new(git_cred **out); */ GIT_EXTERN(int) git_cred_username_new(git_cred **cred, const char *username); +/** + * Create a new ssh key credential object reading the keys from memory. + * + * @param out The newly created credential object. + * @param username username to use to authenticate. + * @param publickey The public key of the credential. + * @param privatekey The private key of the credential. + * @param passphrase The passphrase of the credential. + * @return 0 for success or an error code for failure + */ +GIT_EXTERN(int) git_cred_ssh_key_memory_new( + git_cred **out, + const char *username, + const char *publickey, + const char *privatekey, + const char *passphrase); + /** * Signature of a function which acquires a credential object. * diff --git a/script/cibuild.sh b/script/cibuild.sh index bdc3529313c..a11e7984f23 100755 --- a/script/cibuild.sh +++ b/script/cibuild.sh @@ -53,8 +53,8 @@ export GITTEST_REMOTE_SSH_PASSPHRASE="" if [ -e ./libgit2_clar ]; then ./libgit2_clar -sonline::push -sonline::clone::ssh_cert && - ./libgit2_clar -sonline::clone::ssh_with_paths + ./libgit2_clar -sonline::clone::ssh_with_paths || exit $? if [ "$TRAVIS_OS_NAME" = "linux" ]; then - ./libgit2_clar -sonline::clone::cred_callback + ./libgit2_clar -sonline::clone::cred_callback || exit $? fi fi diff --git a/src/blame.c b/src/blame.c index 4a12cb85b2c..a52f9402b68 100644 --- a/src/blame.c +++ b/src/blame.c @@ -496,8 +496,8 @@ int git_blame_buffer( /* Diff to the reference blob */ git_diff_blob_to_buffer(reference->final_blob, blame->path, - buffer, buffer_len, blame->path, - &diffopts, NULL, buffer_hunk_cb, buffer_line_cb, blame); + buffer, buffer_len, blame->path, &diffopts, + NULL, NULL, buffer_hunk_cb, buffer_line_cb, blame); *out = blame; return 0; diff --git a/src/cache.c b/src/cache.c index 8dc9cbf9c99..2f3ad156316 100644 --- a/src/cache.c +++ b/src/cache.c @@ -68,6 +68,7 @@ int git_cache_init(git_cache *cache) { memset(cache, 0, sizeof(*cache)); cache->map = git_oidmap_alloc(); + GITERR_CHECK_ALLOC(cache->map); if (git_rwlock_init(&cache->lock)) { giterr_set(GITERR_OS, "Failed to initialize cache rwlock"); return -1; diff --git a/src/checkout.c b/src/checkout.c index 6a1d2813615..fd2b19a951b 100644 --- a/src/checkout.c +++ b/src/checkout.c @@ -150,6 +150,15 @@ static int checkout_notify( } } +GIT_INLINE(bool) is_workdir_base_or_new( + const git_oid *workdir_id, + const git_diff_file *baseitem, + const git_diff_file *newitem) +{ + return (git_oid__cmp(&baseitem->id, workdir_id) == 0 || + git_oid__cmp(&newitem->id, workdir_id) == 0); +} + static bool checkout_is_workdir_modified( checkout_data *data, const git_diff_file *baseitem, @@ -193,8 +202,7 @@ static bool checkout_is_workdir_modified( if (wditem->mtime.seconds == ie->mtime.seconds && wditem->mtime.nanoseconds == ie->mtime.nanoseconds && wditem->file_size == ie->file_size) - return (git_oid__cmp(&baseitem->id, &ie->id) != 0 && - git_oid_cmp(&newitem->id, &ie->id) != 0); + return !is_workdir_base_or_new(&ie->id, baseitem, newitem); } /* depending on where base is coming from, we may or may not know @@ -206,7 +214,10 @@ static bool checkout_is_workdir_modified( if (git_diff__oid_for_entry(&oid, data->diff, wditem, NULL) < 0) return false; - return (git_oid__cmp(&baseitem->id, &oid) != 0); + /* Allow the checkout if the workdir is not modified *or* if the checkout + * target's contents are already in the working directory. + */ + return !is_workdir_base_or_new(&oid, baseitem, newitem); } #define CHECKOUT_ACTION_IF(FLAG,YES,NO) \ @@ -1292,7 +1303,7 @@ static int checkout_get_actions( (int)counts[CHECKOUT_ACTION__CONFLICT], counts[CHECKOUT_ACTION__CONFLICT] == 1 ? "conflict prevents" : "conflicts prevent"); - error = GIT_EMERGECONFLICT; + error = GIT_ECONFLICT; goto fail; } @@ -2062,7 +2073,7 @@ static int checkout_write_merge( if (result.path == NULL || result.mode == 0) { giterr_set(GITERR_CHECKOUT, "Could not merge contents of file"); - error = GIT_EMERGECONFLICT; + error = GIT_ECONFLICT; goto done; } @@ -2357,7 +2368,7 @@ static int checkout_data_init( /* cannot checkout if unresolved conflicts exist */ if ((data->opts.checkout_strategy & GIT_CHECKOUT_FORCE) == 0 && git_index_has_conflicts(data->index)) { - error = GIT_EMERGECONFLICT; + error = GIT_ECONFLICT; giterr_set(GITERR_CHECKOUT, "unresolved conflicts exist in the index"); goto cleanup; diff --git a/src/clone.c b/src/clone.c index 8b42ce7061b..070daf94dd2 100644 --- a/src/clone.c +++ b/src/clone.c @@ -532,8 +532,21 @@ static int clone_local_into(git_repository *repo, git_remote *remote, const git_ if (can_link(git_repository_path(src), git_repository_path(repo), link)) flags |= GIT_CPDIR_LINK_FILES; - if ((error = git_futils_cp_r(git_buf_cstr(&src_odb), git_buf_cstr(&dst_odb), - flags, GIT_OBJECT_DIR_MODE)) < 0) + error = git_futils_cp_r(git_buf_cstr(&src_odb), git_buf_cstr(&dst_odb), + flags, GIT_OBJECT_DIR_MODE); + + /* + * can_link() doesn't catch all variations, so if we hit an + * error and did want to link, let's try again without trying + * to link. + */ + if (error < 0 && link) { + flags &= ~GIT_CPDIR_LINK_FILES; + error = git_futils_cp_r(git_buf_cstr(&src_odb), git_buf_cstr(&dst_odb), + flags, GIT_OBJECT_DIR_MODE); + } + + if (error < 0) goto cleanup; git_buf_printf(&reflog_message, "clone: from %s", git_remote_url(remote)); diff --git a/src/commit.c b/src/commit.c index 84f24c6cf45..ce13bdb851e 100644 --- a/src/commit.c +++ b/src/commit.c @@ -309,6 +309,7 @@ int git_commit__parse(void *_commit, git_odb_object *odb_obj) const char *buffer_end = buffer_start + git_odb_object_size(odb_obj); git_oid parent_id; size_t header_len; + git_signature dummy_sig; buffer = buffer_start; @@ -337,6 +338,15 @@ int git_commit__parse(void *_commit, git_odb_object *odb_obj) if (git_signature__parse(commit->author, &buffer, buffer_end, "author ", '\n') < 0) return -1; + /* Some tools create multiple author fields, ignore the extra ones */ + while ((size_t)(buffer_end - buffer) >= strlen("author ") && !git__prefixcmp(buffer, "author ")) { + if (git_signature__parse(&dummy_sig, &buffer, buffer_end, "author ", '\n') < 0) + return -1; + + git__free(dummy_sig.name); + git__free(dummy_sig.email); + } + /* Always parse the committer; we need the commit time */ commit->committer = git__malloc(sizeof(git_signature)); GITERR_CHECK_ALLOC(commit->committer); diff --git a/src/config_file.c b/src/config_file.c index d6a62b85c49..52a5376bd9a 100644 --- a/src/config_file.c +++ b/src/config_file.c @@ -156,7 +156,7 @@ int git_config_file_normalize_section(char *start, char *end) if (end && scan >= end) break; if (isalnum(*scan)) - *scan = (char)tolower(*scan); + *scan = (char)git__tolower(*scan); else if (*scan != '-' || scan == start) return GIT_EINVALIDSPEC; } @@ -1083,7 +1083,7 @@ static int parse_section_header(struct reader *reader, char **section_out) goto fail_parse; } - name[name_length++] = (char) tolower(c); + name[name_length++] = (char)git__tolower(c); } while ((c = line[pos++]) != ']'); diff --git a/src/diff_file.c b/src/diff_file.c index f7061ae8398..cef4bc169c4 100644 --- a/src/diff_file.c +++ b/src/diff_file.c @@ -89,10 +89,9 @@ static int diff_file_content_init_common( int git_diff_file_content__init_from_diff( git_diff_file_content *fc, git_diff *diff, - size_t delta_index, + git_diff_delta *delta, bool use_old) { - git_diff_delta *delta = git_vector_get(&diff->deltas, delta_index); bool has_data = true; memset(fc, 0, sizeof(*fc)); @@ -218,7 +217,9 @@ static int diff_file_content_commit_to_str( return 0; } -static int diff_file_content_load_blob(git_diff_file_content *fc) +static int diff_file_content_load_blob( + git_diff_file_content *fc, + git_diff_options *opts) { int error = 0; git_odb_object *odb_obj = NULL; @@ -236,7 +237,8 @@ static int diff_file_content_load_blob(git_diff_file_content *fc) return error; } - if (diff_file_content_binary_by_size(fc)) + if ((opts->flags & GIT_DIFF_SHOW_BINARY) == 0 && + diff_file_content_binary_by_size(fc)) return 0; if (odb_obj != NULL) { @@ -283,7 +285,9 @@ static int diff_file_content_load_workdir_symlink( } static int diff_file_content_load_workdir_file( - git_diff_file_content *fc, git_buf *path) + git_diff_file_content *fc, + git_buf *path, + git_diff_options *diff_opts) { int error = 0; git_filter_list *fl = NULL; @@ -297,7 +301,8 @@ static int diff_file_content_load_workdir_file( !(fc->file->size = git_futils_filesize(fd))) goto cleanup; - if (diff_file_content_binary_by_size(fc)) + if ((diff_opts->flags & GIT_DIFF_SHOW_BINARY) == 0 && + diff_file_content_binary_by_size(fc)) goto cleanup; if ((error = git_filter_list_load( @@ -339,7 +344,9 @@ static int diff_file_content_load_workdir_file( return error; } -static int diff_file_content_load_workdir(git_diff_file_content *fc) +static int diff_file_content_load_workdir( + git_diff_file_content *fc, + git_diff_options *diff_opts) { int error = 0; git_buf path = GIT_BUF_INIT; @@ -357,7 +364,7 @@ static int diff_file_content_load_workdir(git_diff_file_content *fc) if (S_ISLNK(fc->file->mode)) error = diff_file_content_load_workdir_symlink(fc, &path); else - error = diff_file_content_load_workdir_file(fc, &path); + error = diff_file_content_load_workdir_file(fc, &path, diff_opts); /* once data is loaded, update OID if we didn't have it previously */ if (!error && (fc->file->flags & GIT_DIFF_FLAG_VALID_ID) == 0) { @@ -370,20 +377,23 @@ static int diff_file_content_load_workdir(git_diff_file_content *fc) return error; } -int git_diff_file_content__load(git_diff_file_content *fc) +int git_diff_file_content__load( + git_diff_file_content *fc, + git_diff_options *diff_opts) { int error = 0; if ((fc->flags & GIT_DIFF_FLAG__LOADED) != 0) return 0; - if ((fc->file->flags & GIT_DIFF_FLAG_BINARY) != 0) + if ((fc->file->flags & GIT_DIFF_FLAG_BINARY) != 0 && + (diff_opts->flags & GIT_DIFF_SHOW_BINARY) == 0) return 0; if (fc->src == GIT_ITERATOR_TYPE_WORKDIR) - error = diff_file_content_load_workdir(fc); + error = diff_file_content_load_workdir(fc, diff_opts); else - error = diff_file_content_load_blob(fc); + error = diff_file_content_load_blob(fc, diff_opts); if (error) return error; diff --git a/src/diff_file.h b/src/diff_file.h index 4d290ad4300..0d54b6d330f 100644 --- a/src/diff_file.h +++ b/src/diff_file.h @@ -28,7 +28,7 @@ typedef struct { extern int git_diff_file_content__init_from_diff( git_diff_file_content *fc, git_diff *diff, - size_t delta_index, + git_diff_delta *delta, bool use_old); typedef struct { @@ -49,7 +49,9 @@ extern int git_diff_file_content__init_from_src( git_diff_file *as_file); /* this loads the blob/file-on-disk as needed */ -extern int git_diff_file_content__load(git_diff_file_content *fc); +extern int git_diff_file_content__load( + git_diff_file_content *fc, + git_diff_options *diff_opts); /* this releases the blob/file-in-memory */ extern void git_diff_file_content__unload(git_diff_file_content *fc); diff --git a/src/diff_patch.c b/src/diff_patch.c index 1c4c0e8b86c..60648f8d7f2 100644 --- a/src/diff_patch.c +++ b/src/diff_patch.c @@ -11,41 +11,13 @@ #include "diff_driver.h" #include "diff_patch.h" #include "diff_xdiff.h" +#include "delta.h" +#include "zstream.h" #include "fileops.h" -/* cached information about a hunk in a diff */ -typedef struct diff_patch_hunk { - git_diff_hunk hunk; - size_t line_start; - size_t line_count; -} diff_patch_hunk; - -struct git_patch { - git_refcount rc; - git_diff *diff; /* for refcount purposes, maybe NULL for blob diffs */ - git_diff_delta *delta; - size_t delta_index; - git_diff_file_content ofile; - git_diff_file_content nfile; - uint32_t flags; - git_array_t(diff_patch_hunk) hunks; - git_array_t(git_diff_line) lines; - size_t content_size, context_size, header_size; - git_pool flattened; -}; - -enum { - GIT_DIFF_PATCH_ALLOCATED = (1 << 0), - GIT_DIFF_PATCH_INITIALIZED = (1 << 1), - GIT_DIFF_PATCH_LOADED = (1 << 2), - GIT_DIFF_PATCH_DIFFABLE = (1 << 3), - GIT_DIFF_PATCH_DIFFED = (1 << 4), - GIT_DIFF_PATCH_FLATTENED = (1 << 5), -}; - static void diff_output_init( - git_diff_output*, const git_diff_options*, - git_diff_file_cb, git_diff_hunk_cb, git_diff_line_cb, void*); + git_diff_output*, const git_diff_options*, git_diff_file_cb, + git_diff_binary_cb, git_diff_hunk_cb, git_diff_line_cb, void*); static void diff_output_to_patch(git_diff_output *, git_patch *); @@ -67,15 +39,38 @@ static void diff_patch_init_common(git_patch *patch) { diff_patch_update_binary(patch); - if ((patch->delta->flags & GIT_DIFF_FLAG_BINARY) != 0) - patch->flags |= GIT_DIFF_PATCH_LOADED; /* LOADED but not DIFFABLE */ - patch->flags |= GIT_DIFF_PATCH_INITIALIZED; if (patch->diff) git_diff_addref(patch->diff); } +static int diff_patch_normalize_options( + git_diff_options *out, + const git_diff_options *opts) +{ + if (opts) { + GITERR_CHECK_VERSION(opts, GIT_DIFF_OPTIONS_VERSION, "git_diff_options"); + memcpy(out, opts, sizeof(git_diff_options)); + } else { + git_diff_options default_opts = GIT_DIFF_OPTIONS_INIT; + memcpy(out, &default_opts, sizeof(git_diff_options)); + } + + out->old_prefix = opts && opts->old_prefix ? + git__strdup(opts->old_prefix) : + git__strdup(DIFF_OLD_PREFIX_DEFAULT); + + out->new_prefix = opts && opts->new_prefix ? + git__strdup(opts->new_prefix) : + git__strdup(DIFF_NEW_PREFIX_DEFAULT); + + GITERR_CHECK_ALLOC(out->old_prefix); + GITERR_CHECK_ALLOC(out->new_prefix); + + return 0; +} + static int diff_patch_init_from_diff( git_patch *patch, git_diff *diff, size_t delta_index) { @@ -86,10 +81,12 @@ static int diff_patch_init_from_diff( patch->delta = git_vector_get(&diff->deltas, delta_index); patch->delta_index = delta_index; - if ((error = git_diff_file_content__init_from_diff( - &patch->ofile, diff, delta_index, true)) < 0 || + if ((error = diff_patch_normalize_options( + &patch->diff_opts, &diff->opts)) < 0 || (error = git_diff_file_content__init_from_diff( - &patch->nfile, diff, delta_index, false)) < 0) + &patch->ofile, diff, patch->delta, true)) < 0 || + (error = git_diff_file_content__init_from_diff( + &patch->nfile, diff, patch->delta, false)) < 0) return error; diff_patch_init_common(patch); @@ -116,6 +113,14 @@ static int diff_patch_alloc_from_diff( return error; } +GIT_INLINE(bool) should_skip_binary(git_patch *patch, git_diff_file *file) +{ + if ((patch->diff_opts.flags & GIT_DIFF_SHOW_BINARY) != 0) + return false; + + return (file->flags & GIT_DIFF_FLAG_BINARY) != 0; +} + static int diff_patch_load(git_patch *patch, git_diff_output *output) { int error = 0; @@ -128,7 +133,7 @@ static int diff_patch_load(git_patch *patch, git_diff_output *output) * binary, then there is no need to actually load the data */ if ((patch->ofile.opts_flags & GIT_DIFF_SKIP_BINARY_CHECK) != 0 && - output && !output->hunk_cb && !output->data_cb) + output && !output->binary_cb && !output->hunk_cb && !output->data_cb) return 0; incomplete_data = @@ -141,25 +146,29 @@ static int diff_patch_load(git_patch *patch, git_diff_output *output) * need 2x data size and this minimizes peak memory footprint */ if (patch->ofile.src == GIT_ITERATOR_TYPE_WORKDIR) { - if ((error = git_diff_file_content__load(&patch->ofile)) < 0 || - (patch->ofile.file->flags & GIT_DIFF_FLAG_BINARY) != 0) + if ((error = git_diff_file_content__load( + &patch->ofile, &patch->diff_opts)) < 0 || + should_skip_binary(patch, patch->ofile.file)) goto cleanup; } if (patch->nfile.src == GIT_ITERATOR_TYPE_WORKDIR) { - if ((error = git_diff_file_content__load(&patch->nfile)) < 0 || - (patch->nfile.file->flags & GIT_DIFF_FLAG_BINARY) != 0) + if ((error = git_diff_file_content__load( + &patch->nfile, &patch->diff_opts)) < 0 || + should_skip_binary(patch, patch->nfile.file)) goto cleanup; } /* once workdir has been tried, load other data as needed */ if (patch->ofile.src != GIT_ITERATOR_TYPE_WORKDIR) { - if ((error = git_diff_file_content__load(&patch->ofile)) < 0 || - (patch->ofile.file->flags & GIT_DIFF_FLAG_BINARY) != 0) + if ((error = git_diff_file_content__load( + &patch->ofile, &patch->diff_opts)) < 0 || + should_skip_binary(patch, patch->ofile.file)) goto cleanup; } if (patch->nfile.src != GIT_ITERATOR_TYPE_WORKDIR) { - if ((error = git_diff_file_content__load(&patch->nfile)) < 0 || - (patch->nfile.file->flags & GIT_DIFF_FLAG_BINARY) != 0) + if ((error = git_diff_file_content__load( + &patch->nfile, &patch->diff_opts)) < 0 || + should_skip_binary(patch, patch->nfile.file)) goto cleanup; } @@ -177,10 +186,14 @@ static int diff_patch_load(git_patch *patch, git_diff_output *output) diff_patch_update_binary(patch); if (!error) { + bool skip_binary = + (patch->delta->flags & GIT_DIFF_FLAG_BINARY) != 0 && + (patch->diff_opts.flags & GIT_DIFF_SHOW_BINARY) == 0; + /* patch is diffable only for non-binary, modified files where - * at least one side has data and the data actually changed - */ - if ((patch->delta->flags & GIT_DIFF_FLAG_BINARY) == 0 && + * at least one side has data and the data actually changed + */ + if (!skip_binary && patch->delta->status != GIT_DELTA_UNMODIFIED && (patch->ofile.map.len || patch->nfile.map.len) && (patch->ofile.map.len != patch->nfile.map.len || @@ -207,6 +220,98 @@ static int diff_patch_invoke_file_callback( "git_patch"); } +static int create_binary( + git_diff_binary_t *out_type, + char **out_data, + size_t *out_datalen, + size_t *out_inflatedlen, + const char *a_data, + size_t a_datalen, + const char *b_data, + size_t b_datalen) +{ + git_buf deflate = GIT_BUF_INIT, delta = GIT_BUF_INIT; + unsigned long delta_data_len; + int error; + + /* The git_delta function accepts unsigned long only */ + if (!git__is_ulong(a_datalen) || !git__is_ulong(b_datalen)) + return GIT_EBUFS; + + if ((error = git_zstream_deflatebuf(&deflate, b_data, b_datalen)) < 0) + goto done; + + /* The git_delta function accepts unsigned long only */ + if (!git__is_ulong(deflate.size)) { + error = GIT_EBUFS; + goto done; + } + + if (a_datalen && b_datalen) { + void *delta_data = git_delta( + a_data, (unsigned long)a_datalen, + b_data, (unsigned long)b_datalen, + &delta_data_len, (unsigned long)deflate.size); + + if (delta_data) { + error = git_zstream_deflatebuf( + &delta, delta_data, (size_t)delta_data_len); + + git__free(delta_data); + + if (error < 0) + goto done; + } + } + + if (delta.size && delta.size < deflate.size) { + *out_type = GIT_DIFF_BINARY_DELTA; + *out_datalen = delta.size; + *out_data = git_buf_detach(&delta); + *out_inflatedlen = delta_data_len; + } else { + *out_type = GIT_DIFF_BINARY_LITERAL; + *out_datalen = deflate.size; + *out_data = git_buf_detach(&deflate); + *out_inflatedlen = b_datalen; + } + +done: + git_buf_free(&deflate); + git_buf_free(&delta); + + return error; +} + +static int diff_binary(git_diff_output *output, git_patch *patch) +{ + git_diff_binary binary = {{0}}; + const char *old_data = patch->ofile.map.data; + const char *new_data = patch->nfile.map.data; + size_t old_len = patch->ofile.map.len, + new_len = patch->nfile.map.len; + int error; + + /* Create the old->new delta (as the "new" side of the patch), + * and the new->old delta (as the "old" side) + */ + if ((error = create_binary(&binary.old_file.type, + (char **)&binary.old_file.data, + &binary.old_file.datalen, + &binary.old_file.inflatedlen, + new_data, new_len, old_data, old_len)) < 0 || + (error = create_binary(&binary.new_file.type, + (char **)&binary.new_file.data, + &binary.new_file.datalen, + &binary.new_file.inflatedlen, + old_data, old_len, new_data, new_len)) < 0) + return error; + + return giterr_set_after_callback_function( + output->binary_cb(patch->delta, &binary, output->payload), + "git_patch"); +} + static int diff_patch_generate(git_patch *patch, git_diff_output *output) { int error = 0; @@ -214,8 +319,8 @@ static int diff_patch_generate(git_patch *patch, git_diff_output *output) if ((patch->flags & GIT_DIFF_PATCH_DIFFED) != 0) return 0; - /* if we are not looking at the hunks and lines, don't do the diff */ - if (!output->hunk_cb && !output->data_cb) + /* if we are not looking at the binary or text data, don't do the diff */ + if (!output->binary_cb && !output->hunk_cb && !output->data_cb) return 0; if ((patch->flags & GIT_DIFF_PATCH_LOADED) == 0 && @@ -225,10 +330,16 @@ static int diff_patch_generate(git_patch *patch, git_diff_output *output) if ((patch->flags & GIT_DIFF_PATCH_DIFFABLE) == 0) return 0; - if (output->diff_cb != NULL && - (error = output->diff_cb(output, patch)) < 0) - patch->flags |= GIT_DIFF_PATCH_DIFFED; + if ((patch->delta->flags & GIT_DIFF_FLAG_BINARY) != 0) { + if (output->binary_cb) + error = diff_binary(output, patch); + } + else { + if (output->diff_cb) + error = output->diff_cb(output, patch); + } + patch->flags |= GIT_DIFF_PATCH_DIFFED; return error; } @@ -245,6 +356,9 @@ static void diff_patch_free(git_patch *patch) git_pool_clear(&patch->flattened); + git__free((char *)patch->diff_opts.old_prefix); + git__free((char *)patch->diff_opts.new_prefix); + if (patch->flags & GIT_DIFF_PATCH_ALLOCATED) git__free(patch); } @@ -260,6 +374,7 @@ static int diff_required(git_diff *diff, const char *action) int git_diff_foreach( git_diff *diff, git_diff_file_cb file_cb, + git_diff_binary_cb binary_cb, git_diff_hunk_cb hunk_cb, git_diff_line_cb data_cb, void *payload) @@ -275,7 +390,7 @@ int git_diff_foreach( memset(&xo, 0, sizeof(xo)); memset(&patch, 0, sizeof(patch)); diff_output_init( - &xo.output, &diff->opts, file_cb, hunk_cb, data_cb, payload); + &xo.output, &diff->opts, file_cb, binary_cb, hunk_cb, data_cb, payload); git_xdiff_init(&xo, &diff->opts); git_vector_foreach(&diff->deltas, idx, patch.delta) { @@ -284,11 +399,15 @@ int git_diff_foreach( if (git_diff_delta__should_skip(&diff->opts, patch.delta)) continue; + if (binary_cb || hunk_cb || data_cb) { + if ((error = diff_patch_init_from_diff(&patch, diff, idx)) != 0 || + (error = diff_patch_load(&patch, &xo.output)) != 0) + return error; + } + if ((error = diff_patch_invoke_file_callback(&patch, &xo.output)) == 0) { - if (hunk_cb || data_cb) { - if ((error = diff_patch_init_from_diff(&patch, diff, idx)) == 0) + if (binary_cb || hunk_cb || data_cb) error = diff_patch_generate(&patch, &xo.output); - } } git_patch_free(&patch); @@ -350,7 +469,8 @@ static int diff_patch_from_sources( git_diff_file *lfile = &pd->delta.old_file, *rfile = &pd->delta.new_file; git_diff_file_content *ldata = &pd->patch.ofile, *rdata = &pd->patch.nfile; - GITERR_CHECK_VERSION(opts, GIT_DIFF_OPTIONS_VERSION, "git_diff_options"); + if ((error = diff_patch_normalize_options(&pd->patch.diff_opts, opts)) < 0) + return error; if (opts && (opts->flags & GIT_DIFF_REVERSE) != 0) { void *tmp = lfile; lfile = rfile; rfile = tmp; @@ -419,6 +539,7 @@ static int diff_from_sources( git_diff_file_content_src *newsrc, const git_diff_options *opts, git_diff_file_cb file_cb, + git_diff_binary_cb binary_cb, git_diff_hunk_cb hunk_cb, git_diff_line_cb data_cb, void *payload) @@ -429,7 +550,7 @@ static int diff_from_sources( memset(&xo, 0, sizeof(xo)); diff_output_init( - &xo.output, opts, file_cb, hunk_cb, data_cb, payload); + &xo.output, opts, file_cb, binary_cb, hunk_cb, data_cb, payload); git_xdiff_init(&xo, opts); memset(&pd, 0, sizeof(pd)); @@ -477,6 +598,7 @@ int git_diff_blobs( const char *new_path, const git_diff_options *opts, git_diff_file_cb file_cb, + git_diff_binary_cb binary_cb, git_diff_hunk_cb hunk_cb, git_diff_line_cb data_cb, void *payload) @@ -486,7 +608,7 @@ int git_diff_blobs( git_diff_file_content_src nsrc = GIT_DIFF_FILE_CONTENT_SRC__BLOB(new_blob, new_path); return diff_from_sources( - &osrc, &nsrc, opts, file_cb, hunk_cb, data_cb, payload); + &osrc, &nsrc, opts, file_cb, binary_cb, hunk_cb, data_cb, payload); } int git_patch_from_blobs( @@ -512,6 +634,7 @@ int git_diff_blob_to_buffer( const char *buf_path, const git_diff_options *opts, git_diff_file_cb file_cb, + git_diff_binary_cb binary_cb, git_diff_hunk_cb hunk_cb, git_diff_line_cb data_cb, void *payload) @@ -521,7 +644,7 @@ int git_diff_blob_to_buffer( git_diff_file_content_src nsrc = GIT_DIFF_FILE_CONTENT_SRC__BUF(buf, buflen, buf_path); return diff_from_sources( - &osrc, &nsrc, opts, file_cb, hunk_cb, data_cb, payload); + &osrc, &nsrc, opts, file_cb, binary_cb, hunk_cb, data_cb, payload); } int git_patch_from_blob_and_buffer( @@ -549,6 +672,7 @@ int git_diff_buffers( const char *new_path, const git_diff_options *opts, git_diff_file_cb file_cb, + git_diff_binary_cb binary_cb, git_diff_hunk_cb hunk_cb, git_diff_line_cb data_cb, void *payload) @@ -558,7 +682,7 @@ int git_diff_buffers( git_diff_file_content_src nsrc = GIT_DIFF_FILE_CONTENT_SRC__BUF(new_buf, new_len, new_path); return diff_from_sources( - &osrc, &nsrc, opts, file_cb, hunk_cb, data_cb, payload); + &osrc, &nsrc, opts, file_cb, binary_cb, hunk_cb, data_cb, payload); } int git_patch_from_buffers( @@ -812,6 +936,7 @@ void git_patch__new_data( int git_patch__invoke_callbacks( git_patch *patch, git_diff_file_cb file_cb, + git_diff_binary_cb binary_cb, git_diff_hunk_cb hunk_cb, git_diff_line_cb line_cb, void *payload) @@ -822,6 +947,13 @@ int git_patch__invoke_callbacks( if (file_cb) error = file_cb(patch->delta, 0, payload); + if ((patch->delta->flags & GIT_DIFF_FLAG_BINARY) != 0) { + if (binary_cb) + error = binary_cb(patch->delta, &patch->binary, payload); + + return error; + } + if (!hunk_cb && !line_cb) return error; @@ -855,6 +987,36 @@ static int diff_patch_file_cb( return 0; } +static int diff_patch_binary_cb( + const git_diff_delta *delta, + const git_diff_binary *binary, + void *payload) +{ + git_patch *patch = payload; + + GIT_UNUSED(delta); + + memcpy(&patch->binary, binary, sizeof(git_diff_binary)); + + if (binary->old_file.data) { + patch->binary.old_file.data = git__malloc(binary->old_file.datalen); + GITERR_CHECK_ALLOC(patch->binary.old_file.data); + + memcpy((char *)patch->binary.old_file.data, + binary->old_file.data, binary->old_file.datalen); + } + + if (binary->new_file.data) { + patch->binary.new_file.data = git__malloc(binary->new_file.datalen); + GITERR_CHECK_ALLOC(patch->binary.new_file.data); + + memcpy((char *)patch->binary.new_file.data, + binary->new_file.data, binary->new_file.datalen); + } + + return 0; +} + static int diff_patch_hunk_cb( const git_diff_delta *delta, const git_diff_hunk *hunk_, @@ -921,6 +1083,7 @@ static void diff_output_init( git_diff_output *out, const git_diff_options *opts, git_diff_file_cb file_cb, + git_diff_binary_cb binary_cb, git_diff_hunk_cb hunk_cb, git_diff_line_cb data_cb, void *payload) @@ -930,6 +1093,7 @@ static void diff_output_init( memset(out, 0, sizeof(*out)); out->file_cb = file_cb; + out->binary_cb = binary_cb; out->hunk_cb = hunk_cb; out->data_cb = data_cb; out->payload = payload; @@ -938,6 +1102,11 @@ static void diff_output_init( static void diff_output_to_patch(git_diff_output *out, git_patch *patch) { diff_output_init( - out, NULL, - diff_patch_file_cb, diff_patch_hunk_cb, diff_patch_line_cb, patch); + out, + NULL, + diff_patch_file_cb, + diff_patch_binary_cb, + diff_patch_hunk_cb, + diff_patch_line_cb, + patch); } diff --git a/src/diff_patch.h b/src/diff_patch.h index df2ba4c3199..f6ce57dddab 100644 --- a/src/diff_patch.h +++ b/src/diff_patch.h @@ -13,6 +13,38 @@ #include "array.h" #include "git2/patch.h" + /* cached information about a hunk in a diff */ +typedef struct diff_patch_hunk { + git_diff_hunk hunk; + size_t line_start; + size_t line_count; +} diff_patch_hunk; + +enum { + GIT_DIFF_PATCH_ALLOCATED = (1 << 0), + GIT_DIFF_PATCH_INITIALIZED = (1 << 1), + GIT_DIFF_PATCH_LOADED = (1 << 2), + GIT_DIFF_PATCH_DIFFABLE = (1 << 3), + GIT_DIFF_PATCH_DIFFED = (1 << 4), + GIT_DIFF_PATCH_FLATTENED = (1 << 5), +}; + +struct git_patch { + git_refcount rc; + git_diff *diff; /* for refcount purposes, maybe NULL for blob diffs */ + git_diff_options diff_opts; + git_diff_delta *delta; + size_t delta_index; + git_diff_file_content ofile; + git_diff_file_content nfile; + uint32_t flags; + git_diff_binary binary; + git_array_t(diff_patch_hunk) hunks; + git_array_t(git_diff_line) lines; + size_t content_size, context_size, header_size; + git_pool flattened; +}; + extern git_diff *git_patch__diff(git_patch *); extern git_diff_driver *git_patch__driver(git_patch *); @@ -23,6 +55,7 @@ extern void git_patch__new_data(char **, size_t *, git_patch *); extern int git_patch__invoke_callbacks( git_patch *patch, git_diff_file_cb file_cb, + git_diff_binary_cb binary_cb, git_diff_hunk_cb hunk_cb, git_diff_line_cb line_cb, void *payload); @@ -31,6 +64,7 @@ typedef struct git_diff_output git_diff_output; struct git_diff_output { /* these callbacks are issued with the diff data */ git_diff_file_cb file_cb; + git_diff_binary_cb binary_cb; git_diff_hunk_cb hunk_cb; git_diff_line_cb data_cb; void *payload; diff --git a/src/diff_print.c b/src/diff_print.c index 43a90b3d8a5..c58698368df 100644 --- a/src/diff_print.c +++ b/src/diff_print.c @@ -22,50 +22,92 @@ typedef struct { uint32_t flags; int oid_strlen; git_diff_line line; + unsigned int + content_loaded : 1, + content_allocated : 1; + git_diff_file_content *ofile; + git_diff_file_content *nfile; } diff_print_info; -static int diff_print_info_init( +static int diff_print_info_init__common( diff_print_info *pi, git_buf *out, - git_diff *diff, + git_repository *repo, git_diff_format_t format, git_diff_line_cb cb, void *payload) { - pi->diff = diff; - pi->format = format; + pi->format = format; pi->print_cb = cb; - pi->payload = payload; - pi->buf = out; - - if (diff) - pi->flags = diff->opts.flags; - else - pi->flags = 0; - - if (diff && diff->opts.id_abbrev != 0) - pi->oid_strlen = diff->opts.id_abbrev; - else if (!diff || !diff->repo) - pi->oid_strlen = GIT_ABBREV_DEFAULT; - else if (git_repository__cvar( - &pi->oid_strlen, diff->repo, GIT_CVAR_ABBREV) < 0) - return -1; + pi->payload = payload; + pi->buf = out; + + if (!pi->oid_strlen) { + if (!repo) + pi->oid_strlen = GIT_ABBREV_DEFAULT; + else if (git_repository__cvar(&pi->oid_strlen, repo, GIT_CVAR_ABBREV) < 0) + return -1; + } pi->oid_strlen += 1; /* for NUL byte */ - if (pi->oid_strlen < 2) - pi->oid_strlen = 2; - else if (pi->oid_strlen > GIT_OID_HEXSZ + 1) + if (pi->oid_strlen > GIT_OID_HEXSZ + 1) pi->oid_strlen = GIT_OID_HEXSZ + 1; memset(&pi->line, 0, sizeof(pi->line)); pi->line.old_lineno = -1; pi->line.new_lineno = -1; - pi->line.num_lines = 1; + pi->line.num_lines = 1; return 0; } +static int diff_print_info_init_fromdiff( + diff_print_info *pi, + git_buf *out, + git_diff *diff, + git_diff_format_t format, + git_diff_line_cb cb, + void *payload) +{ + git_repository *repo = diff ? diff->repo : NULL; + + memset(pi, 0, sizeof(diff_print_info)); + + pi->diff = diff; + + if (diff) { + pi->flags = diff->opts.flags; + pi->oid_strlen = diff->opts.id_abbrev; + } + + return diff_print_info_init__common(pi, out, repo, format, cb, payload); +} + +static int diff_print_info_init_frompatch( + diff_print_info *pi, + git_buf *out, + git_patch *patch, + git_diff_format_t format, + git_diff_line_cb cb, + void *payload) +{ + git_repository *repo = patch && patch->diff ? patch->diff->repo : NULL; + + memset(pi, 0, sizeof(diff_print_info)); + + pi->diff = patch->diff; + + pi->flags = patch->diff_opts.flags; + pi->oid_strlen = patch->diff_opts.id_abbrev; + + pi->content_loaded = 1; + pi->ofile = &patch->ofile; + pi->nfile = &patch->nfile; + + return diff_print_info_init__common(pi, out, repo, format, cb, payload); +} + static char diff_pick_suffix(int mode) { if (S_ISDIR(mode)) @@ -283,66 +325,21 @@ int git_diff_delta__format_file_header( return git_buf_oom(out) ? -1 : 0; } -static int print_binary_hunk(diff_print_info *pi, git_blob *old, git_blob *new) +static int format_binary( + diff_print_info *pi, + git_diff_binary_t type, + const char *data, + size_t datalen, + size_t inflatedlen) { - git_buf deflate = GIT_BUF_INIT, delta = GIT_BUF_INIT, *out = NULL; - const void *old_data, *new_data; - git_off_t old_data_len, new_data_len; - unsigned long delta_data_len, inflated_len; - const char *out_type = "literal"; - char *scan, *end; - int error; - - old_data = old ? git_blob_rawcontent(old) : NULL; - new_data = new ? git_blob_rawcontent(new) : NULL; - - old_data_len = old ? git_blob_rawsize(old) : 0; - new_data_len = new ? git_blob_rawsize(new) : 0; - - /* The git_delta function accepts unsigned long only */ - if (!git__is_ulong(old_data_len) || !git__is_ulong(new_data_len)) - return GIT_EBUFS; - - out = &deflate; - inflated_len = (unsigned long)new_data_len; - - if ((error = git_zstream_deflatebuf( - out, new_data, (size_t)new_data_len)) < 0) - goto done; - - /* The git_delta function accepts unsigned long only */ - if (!git__is_ulong((git_off_t)deflate.size)) { - error = GIT_EBUFS; - goto done; - } + const char *typename = type == GIT_DIFF_BINARY_DELTA ? + "delta" : "literal"; + const char *scan, *end; - if (old && new) { - void *delta_data = git_delta( - old_data, (unsigned long)old_data_len, - new_data, (unsigned long)new_data_len, - &delta_data_len, (unsigned long)deflate.size); - - if (delta_data) { - error = git_zstream_deflatebuf( - &delta, delta_data, (size_t)delta_data_len); - - git__free(delta_data); - - if (error < 0) - goto done; - - if (delta.size < deflate.size) { - out = δ - out_type = "delta"; - inflated_len = delta_data_len; - } - } - } - - git_buf_printf(pi->buf, "%s %lu\n", out_type, inflated_len); + git_buf_printf(pi->buf, "%s %lu\n", typename, inflatedlen); pi->line.num_lines++; - for (scan = out->ptr, end = out->ptr + out->size; scan < end; ) { + for (scan = data, end = data + datalen; scan < end; ) { size_t chunk_len = end - scan; if (chunk_len > 52) chunk_len = 52; @@ -355,51 +352,74 @@ static int print_binary_hunk(diff_print_info *pi, git_blob *old, git_blob *new) git_buf_encode_base85(pi->buf, scan, chunk_len); git_buf_putc(pi->buf, '\n'); - if (git_buf_oom(pi->buf)) { - error = -1; - goto done; - } + if (git_buf_oom(pi->buf)) + return -1; scan += chunk_len; pi->line.num_lines++; } -done: - git_buf_free(&deflate); - git_buf_free(&delta); + return 0; +} - return error; +static int diff_print_load_content( + diff_print_info *pi, + git_diff_delta *delta) +{ + git_diff_file_content *ofile, *nfile; + int error; + + assert(pi->diff); + + ofile = git__calloc(1, sizeof(git_diff_file_content)); + nfile = git__calloc(1, sizeof(git_diff_file_content)); + + GITERR_CHECK_ALLOC(ofile); + GITERR_CHECK_ALLOC(nfile); + + if ((error = git_diff_file_content__init_from_diff( + ofile, pi->diff, delta, true)) < 0 || + (error = git_diff_file_content__init_from_diff( + nfile, pi->diff, delta, true)) < 0) { + + git__free(ofile); + git__free(nfile); + return error; + } + + pi->content_loaded = 1; + pi->content_allocated = 1; + pi->ofile = ofile; + pi->nfile = nfile; + + return 0; } -/* git diff --binary 8d7523f~2 8d7523f~1 */ static int diff_print_patch_file_binary( - diff_print_info *pi, const git_diff_delta *delta, - const char *oldpfx, const char *newpfx) + diff_print_info *pi, git_diff_delta *delta, + const char *old_pfx, const char *new_pfx, + const git_diff_binary *binary) { - git_blob *old = NULL, *new = NULL; - const git_oid *old_id, *new_id; - int error; size_t pre_binary_size; + int error; if ((pi->flags & GIT_DIFF_SHOW_BINARY) == 0) goto noshow; + if (!pi->content_loaded && + (error = diff_print_load_content(pi, delta)) < 0) + return error; + pre_binary_size = pi->buf->size; git_buf_printf(pi->buf, "GIT binary patch\n"); pi->line.num_lines++; - old_id = (delta->status != GIT_DELTA_ADDED) ? &delta->old_file.id : NULL; - new_id = (delta->status != GIT_DELTA_DELETED) ? &delta->new_file.id : NULL; - - if (old_id && (error = git_blob_lookup(&old, pi->diff->repo, old_id)) < 0) - goto done; - if (new_id && (error = git_blob_lookup(&new, pi->diff->repo,new_id)) < 0) - goto done; - - if ((error = print_binary_hunk(pi, old, new)) < 0 || + if ((error = format_binary(pi, binary->new_file.type, binary->new_file.data, + binary->new_file.datalen, binary->new_file.inflatedlen)) < 0 || (error = git_buf_putc(pi->buf, '\n')) < 0 || - (error = print_binary_hunk(pi, new, old)) < 0) - { + (error = format_binary(pi, binary->old_file.type, binary->old_file.data, + binary->old_file.datalen, binary->old_file.inflatedlen)) < 0) { + if (error == GIT_EBUFS) { giterr_clear(); git_buf_truncate(pi->buf, pre_binary_size); @@ -408,17 +428,12 @@ static int diff_print_patch_file_binary( } pi->line.num_lines++; - -done: - git_blob_free(old); - git_blob_free(new); - return error; noshow: pi->line.num_lines = 1; return diff_delta_format_with_paths( - pi->buf, delta, oldpfx, newpfx, + pi->buf, delta, old_pfx, new_pfx, "Binary files %s%s and %s%s differ\n"); } @@ -432,7 +447,8 @@ static int diff_print_patch_file( const char *newpfx = pi->diff ? pi->diff->opts.new_prefix : DIFF_NEW_PREFIX_DEFAULT; - bool binary = !!(delta->flags & GIT_DIFF_FLAG_BINARY); + bool binary = (delta->flags & GIT_DIFF_FLAG_BINARY) || + (pi->flags & GIT_DIFF_FORCE_BINARY); bool show_binary = !!(pi->flags & GIT_DIFF_SHOW_BINARY); int oid_strlen = binary && show_binary ? GIT_OID_HEXSZ + 1 : pi->oid_strlen; @@ -455,19 +471,29 @@ static int diff_print_patch_file( pi->line.content = git_buf_cstr(pi->buf); pi->line.content_len = git_buf_len(pi->buf); - if ((error = pi->print_cb(delta, NULL, &pi->line, pi->payload)) != 0) - return error; + return pi->print_cb(delta, NULL, &pi->line, pi->payload); +} - if (!binary) - return 0; +static int diff_print_patch_binary( + const git_diff_delta *delta, + const git_diff_binary *binary, + void *data) +{ + diff_print_info *pi = data; + const char *old_pfx = + pi->diff ? pi->diff->opts.old_prefix : DIFF_OLD_PREFIX_DEFAULT; + const char *new_pfx = + pi->diff ? pi->diff->opts.new_prefix : DIFF_NEW_PREFIX_DEFAULT; + int error; git_buf_clear(pi->buf); - if ((error = diff_print_patch_file_binary(pi, delta, oldpfx, newpfx)) < 0) + if ((error = diff_print_patch_file_binary( + pi, (git_diff_delta *)delta, old_pfx, new_pfx, binary)) < 0) return error; - pi->line.origin = GIT_DIFF_LINE_BINARY; - pi->line.content = git_buf_cstr(pi->buf); + pi->line.origin = GIT_DIFF_LINE_BINARY; + pi->line.content = git_buf_cstr(pi->buf); pi->line.content_len = git_buf_len(pi->buf); return pi->print_cb(delta, NULL, &pi->line, pi->payload); @@ -515,12 +541,14 @@ int git_diff_print( git_buf buf = GIT_BUF_INIT; diff_print_info pi; git_diff_file_cb print_file = NULL; + git_diff_binary_cb print_binary = NULL; git_diff_hunk_cb print_hunk = NULL; git_diff_line_cb print_line = NULL; switch (format) { case GIT_DIFF_FORMAT_PATCH: print_file = diff_print_patch_file; + print_binary = diff_print_patch_binary; print_hunk = diff_print_patch_hunk; print_line = diff_print_patch_line; break; @@ -541,11 +569,10 @@ int git_diff_print( return -1; } - if (!(error = diff_print_info_init( - &pi, &buf, diff, format, print_cb, payload))) - { + if (!(error = diff_print_info_init_fromdiff( + &pi, &buf, diff, format, print_cb, payload))) { error = git_diff_foreach( - diff, print_file, print_hunk, print_line, &pi); + diff, print_file, print_binary, print_hunk, print_line, &pi); if (error) /* make sure error message is set */ giterr_set_after_callback_function(error, "git_diff_print"); @@ -568,13 +595,13 @@ int git_patch_print( assert(patch && print_cb); - if (!(error = diff_print_info_init( - &pi, &temp, git_patch__diff(patch), + if (!(error = diff_print_info_init_frompatch( + &pi, &temp, patch, GIT_DIFF_FORMAT_PATCH, print_cb, payload))) { error = git_patch__invoke_callbacks( - patch, diff_print_patch_file, diff_print_patch_hunk, - diff_print_patch_line, &pi); + patch, diff_print_patch_file, diff_print_patch_binary, + diff_print_patch_hunk, diff_print_patch_line, &pi); if (error) /* make sure error message is set */ giterr_set_after_callback_function(error, "git_patch_print"); diff --git a/src/diff_tform.c b/src/diff_tform.c index 7d84635734f..03dd9c9f74c 100644 --- a/src/diff_tform.c +++ b/src/diff_tform.c @@ -676,11 +676,13 @@ static bool is_rename_target( return false; /* only consider ADDED, RENAMED, COPIED, and split MODIFIED as - * targets; maybe include UNTRACKED and IGNORED if requested. + * targets; maybe include UNTRACKED if requested. */ switch (delta->status) { case GIT_DELTA_UNMODIFIED: case GIT_DELTA_DELETED: + case GIT_DELTA_IGNORED: + case GIT_DELTA_CONFLICTED: return false; case GIT_DELTA_MODIFIED: @@ -707,9 +709,6 @@ static bool is_rename_target( return false; break; - case GIT_DELTA_IGNORED: - return false; - default: /* all other status values should be checked */ break; } @@ -735,6 +734,7 @@ static bool is_rename_source( case GIT_DELTA_UNTRACKED: case GIT_DELTA_UNREADABLE: case GIT_DELTA_IGNORED: + case GIT_DELTA_CONFLICTED: return false; case GIT_DELTA_DELETED: diff --git a/src/filter.c b/src/filter.c index c88fdd4ee95..e25d37c353c 100644 --- a/src/filter.c +++ b/src/filter.c @@ -27,6 +27,7 @@ struct git_filter_source { }; typedef struct { + const char *filter_name; git_filter *filter; void *payload; } git_filter_entry; @@ -526,7 +527,9 @@ int git_filter_list__load_ext( fe = git_array_alloc(fl->filters); GITERR_CHECK_ALLOC(fe); - fe->filter = fdef->filter; + + fe->filter = fdef->filter; + fe->filter_name = fdef->filter_name; fe->payload = payload; } } @@ -574,6 +577,25 @@ void git_filter_list_free(git_filter_list *fl) git__free(fl); } +int git_filter_list_contains( + git_filter_list *fl, + const char *name) +{ + size_t i; + + assert(name); + + if (!fl) + return 0; + + for (i = 0; i < fl->filters.size; i++) { + if (strcmp(fl->filters.ptr[i].filter_name, name) == 0) + return 1; + } + + return 0; +} + int git_filter_list_push( git_filter_list *fl, git_filter *filter, void *payload) { @@ -887,7 +909,7 @@ int git_filter_list_stream_file( git_vector filter_streams = GIT_VECTOR_INIT; git_writestream *stream_start; ssize_t readlen; - int fd, error; + int fd = -1, error; if ((error = stream_list_init( &stream_start, &filter_streams, filters, target)) < 0 || @@ -909,9 +931,10 @@ int git_filter_list_stream_file( else if (readlen < 0) error = readlen; - p_close(fd); done: + if (fd >= 0) + p_close(fd); stream_list_free(&filter_streams); git_buf_free(&abspath); return error; diff --git a/src/fnmatch.c b/src/fnmatch.c index d7899e3e604..a2945b8db34 100644 --- a/src/fnmatch.c +++ b/src/fnmatch.c @@ -164,8 +164,8 @@ p_fnmatchx(const char *pattern, const char *string, int flags, size_t recurs) default: normal: if (c != *string && !((flags & FNM_CASEFOLD) && - (tolower((unsigned char)c) == - tolower((unsigned char)*string)))) + (git__tolower((unsigned char)c) == + git__tolower((unsigned char)*string)))) return (FNM_NOMATCH); ++string; break; @@ -190,7 +190,7 @@ rangematch(const char *pattern, char test, int flags, char **newp) ++pattern; if (flags & FNM_CASEFOLD) - test = (char)tolower((unsigned char)test); + test = (char)git__tolower((unsigned char)test); /* * A right bracket shall lose its special meaning and represent @@ -207,7 +207,7 @@ rangematch(const char *pattern, char test, int flags, char **newp) if (c == '/' && (flags & FNM_PATHNAME)) return (RANGE_NOMATCH); if ((flags & FNM_CASEFOLD)) - c = (char)tolower((unsigned char)c); + c = (char)git__tolower((unsigned char)c); if (*pattern == '-' && (c2 = *(pattern+1)) != EOS && c2 != ']') { pattern += 2; @@ -216,7 +216,7 @@ rangematch(const char *pattern, char test, int flags, char **newp) if (c2 == EOS) return (RANGE_ERROR); if (flags & FNM_CASEFOLD) - c2 = (char)tolower((unsigned char)c2); + c2 = (char)git__tolower((unsigned char)c2); if (c <= test && test <= c2) ok = 1; } else if (c == test) diff --git a/src/global.c b/src/global.c index 9f1a0bf10c7..3f20bfd3195 100644 --- a/src/global.c +++ b/src/global.c @@ -116,6 +116,20 @@ static void init_ssl(void) #endif } +/** + * This function aims to clean-up the SSL context which + * we allocated. + */ +static void uninit_ssl(void) +{ +#ifdef GIT_OPENSSL + if (git__ssl_ctx) { + SSL_CTX_free(git__ssl_ctx); + git__ssl_ctx = NULL; + } +#endif +} + int git_openssl_set_locking(void) { #ifdef GIT_OPENSSL @@ -333,6 +347,7 @@ int git_libgit2_shutdown(void) /* Shut down any subsystems that have global state */ git__shutdown(); + uninit_ssl(); ptr = pthread_getspecific(_tls_key); pthread_setspecific(_tls_key, NULL); @@ -391,6 +406,7 @@ int git_libgit2_shutdown(void) git__shutdown(); git__global_state_cleanup(&__state); + uninit_ssl(); return 0; } diff --git a/src/index.c b/src/index.c index 0422ff1d414..a931f048a5c 100644 --- a/src/index.c +++ b/src/index.c @@ -658,11 +658,29 @@ int git_index__changed_relative_to( index->stamp.ino != fs->ino); } +/* + * Force the next diff to take a look at those entries which have the + * same timestamp as the current index. + */ +static void truncate_racily_clean(git_index *index) +{ + size_t i; + git_index_entry *entry; + git_time_t ts = index->stamp.mtime; + + git_vector_foreach(&index->entries, i, entry) { + if (entry->mtime.seconds == ts || ts == 0) + entry->file_size = 0; + } +} + int git_index_write(git_index *index) { git_indexwriter writer = GIT_INDEXWRITER_INIT; int error; + truncate_racily_clean(index); + if ((error = git_indexwriter_init(&writer, index)) == 0) error = git_indexwriter_commit(&writer); @@ -2727,7 +2745,7 @@ static int index_apply_to_wd_diff(git_index *index, int action, const git_strarr goto cleanup; data.pathspec = &ps; - error = git_diff_foreach(diff, apply_each_file, NULL, NULL, &data); + error = git_diff_foreach(diff, apply_each_file, NULL, NULL, NULL, &data); git_diff_free(diff); if (error) /* make sure error is set if callback stopped iteration */ diff --git a/src/indexer.c b/src/indexer.c index e39345c71e5..512addf48bf 100644 --- a/src/indexer.c +++ b/src/indexer.c @@ -478,13 +478,14 @@ static int write_at(git_indexer *idx, const void *data, git_off_t offset, size_t static int append_to_pack(git_indexer *idx, const void *data, size_t size) { git_off_t current_size = idx->pack->mwf.size; + int fd = idx->pack->mwf.fd; if (!size) return 0; - /* add the extra space we need at the end */ - if (p_ftruncate(idx->pack->mwf.fd, current_size + size) < 0) { - giterr_set(GITERR_OS, "Failed to increase size of pack file '%s'", idx->pack->pack_name); + if (p_lseek(fd, current_size + size - 1, SEEK_SET) < 0 || + p_write(idx->pack->mwf.fd, data, 1) < 0) { + giterr_set(GITERR_OS, "cannot extend packfile '%s'", idx->pack->pack_name); return -1; } @@ -822,7 +823,7 @@ static int resolve_deltas(git_indexer *idx, git_transfer_progress *stats) progressed = 0; non_null = 0; git_vector_foreach(&idx->deltas, i, delta) { - git_rawobj obj; + git_rawobj obj = {NULL}; if (!delta) continue; diff --git a/src/iterator.c b/src/iterator.c index 93303a87d42..7807a16364b 100644 --- a/src/iterator.c +++ b/src/iterator.c @@ -1405,10 +1405,10 @@ GIT_INLINE(bool) workdir_path_is_dotgit(const git_buf *path) if (path->ptr[len - 1] == '/') len--; - if (tolower(path->ptr[len - 1]) != 't' || - tolower(path->ptr[len - 2]) != 'i' || - tolower(path->ptr[len - 3]) != 'g' || - tolower(path->ptr[len - 4]) != '.') + if (git__tolower(path->ptr[len - 1]) != 't' || + git__tolower(path->ptr[len - 2]) != 'i' || + git__tolower(path->ptr[len - 3]) != 'g' || + git__tolower(path->ptr[len - 4]) != '.') return false; return (len == 4 || path->ptr[len - 5] == '/'); diff --git a/src/merge.c b/src/merge.c index eaf7eee1f8e..517d317de05 100644 --- a/src/merge.c +++ b/src/merge.c @@ -1143,9 +1143,9 @@ static void merge_diff_list_count_candidates( if (GIT_MERGE_INDEX_ENTRY_EXISTS(entry->ancestor_entry) && (!GIT_MERGE_INDEX_ENTRY_EXISTS(entry->our_entry) || !GIT_MERGE_INDEX_ENTRY_EXISTS(entry->their_entry))) - src_count++; + (*src_count)++; else if (!GIT_MERGE_INDEX_ENTRY_EXISTS(entry->ancestor_entry)) - tgt_count++; + (*tgt_count)++; } } @@ -2509,7 +2509,7 @@ int git_merge__check_result(git_repository *repo, git_index *index_new) if ((conflicts = index_conflicts + wd_conflicts) > 0) { giterr_set(GITERR_MERGE, "%d uncommitted change%s would be overwritten by merge", conflicts, (conflicts != 1) ? "s" : ""); - error = GIT_EMERGECONFLICT; + error = GIT_ECONFLICT; } done: diff --git a/src/netops.c b/src/netops.c index 6047cf1ac87..5e807559768 100644 --- a/src/netops.c +++ b/src/netops.c @@ -84,7 +84,7 @@ void gitno_consume_n(gitno_buffer *buf, size_t cons) int gitno__match_host(const char *pattern, const char *host) { for (;;) { - char c = tolower(*pattern++); + char c = git__tolower(*pattern++); if (c == '\0') return *host ? -1 : 0; @@ -102,7 +102,7 @@ int gitno__match_host(const char *pattern, const char *host) */ while(*host) { - char h = tolower(*host); + char h = git__tolower(*host); if (c == h) return gitno__match_host(pattern, host++); if (h == '.') @@ -112,7 +112,7 @@ int gitno__match_host(const char *pattern, const char *host) return -1; } - if (c != tolower(*host++)) + if (c != git__tolower(*host++)) return -1; } diff --git a/src/object.c b/src/object.c index 1073559fd12..a178e0ed38a 100644 --- a/src/object.c +++ b/src/object.c @@ -129,10 +129,10 @@ int git_object_lookup_prefix( if (error < 0) return error; - if (len > GIT_OID_HEXSZ) - len = GIT_OID_HEXSZ; + if (len > GIT_OID_RAWSZ) + len = GIT_OID_RAWSZ; - if (len == GIT_OID_HEXSZ) { + if (len == GIT_OID_RAWSZ) { git_cached_obj *cached = NULL; /* We want to match the full id : we can first look up in the cache, @@ -172,9 +172,9 @@ int git_object_lookup_prefix( memcpy(short_oid.id, id->id, (len + 1) / 2); if (len % 2) short_oid.id[len / 2] &= 0xF0; - memset(short_oid.id + (len + 1) / 2, 0, (GIT_OID_HEXSZ - len) / 2); + memset(short_oid.id + (len + 1) / 2, 0, (GIT_OID_RAWSZ - len) / 2); - /* If len < GIT_OID_HEXSZ (a strict short oid was given), we have + /* If len < GIT_OID_RAWSZ (a strict short oid was given), we have * 2 options : * - We always search in the cache first. If we find that short oid is * ambiguous, we can stop. But in all the other cases, we must then diff --git a/src/odb.c b/src/odb.c index deb9d5c8254..7a718f5d65b 100644 --- a/src/odb.c +++ b/src/odb.c @@ -53,7 +53,7 @@ static int load_alternates(git_odb *odb, const char *objects_dir, int alternate_ int git_odb__format_object_header(char *hdr, size_t n, git_off_t obj_len, git_otype obj_type) { const char *type_str = git_object_type2string(obj_type); - int len = p_snprintf(hdr, n, "%s %"PRIuZ, type_str, obj_len); + int len = p_snprintf(hdr, n, "%s %lld", type_str, obj_len); assert(len > 0 && len <= (int)n); return len+1; } diff --git a/src/odb_pack.c b/src/odb_pack.c index 1757cf920d2..735158d9604 100644 --- a/src/odb_pack.c +++ b/src/odb_pack.c @@ -383,7 +383,7 @@ static int pack_backend__read_internal( git_odb_backend *backend, const git_oid *oid) { struct git_pack_entry e; - git_rawobj raw; + git_rawobj raw = {NULL}; int error; if ((error = pack_entry_find(&e, (struct pack_backend *)backend, oid)) < 0 || diff --git a/src/pack.c b/src/pack.c index 105d67510bc..cd652672119 100644 --- a/src/pack.c +++ b/src/pack.c @@ -319,9 +319,9 @@ static int pack_index_check(const char *path, struct git_pack_file *p) static int pack_index_open(struct git_pack_file *p) { - char *idx_name; int error = 0; - size_t name_len, base_len; + size_t name_len; + git_buf idx_name = GIT_BUF_INIT; if (p->index_version > -1) return 0; @@ -329,22 +329,23 @@ static int pack_index_open(struct git_pack_file *p) name_len = strlen(p->pack_name); assert(name_len > strlen(".pack")); /* checked by git_pack_file alloc */ - if ((idx_name = git__malloc(name_len)) == NULL) + git_buf_grow(&idx_name, name_len); + git_buf_put(&idx_name, p->pack_name, name_len - strlen(".pack")); + git_buf_puts(&idx_name, ".idx"); + if (git_buf_oom(&idx_name)) { + giterr_set_oom(); return -1; - - base_len = name_len - strlen(".pack"); - memcpy(idx_name, p->pack_name, base_len); - memcpy(idx_name + base_len, ".idx", sizeof(".idx")); + } if ((error = git_mutex_lock(&p->lock)) < 0) { - git__free(idx_name); + git_buf_free(&idx_name); return error; } if (p->index_version == -1) - error = pack_index_check(idx_name, p); + error = pack_index_check(idx_name.ptr, p); - git__free(idx_name); + git_buf_free(&idx_name); git_mutex_unlock(&p->lock); diff --git a/src/path.c b/src/path.c index 81b4d51df84..c04b5062241 100644 --- a/src/path.c +++ b/src/path.c @@ -889,7 +889,7 @@ void git_path_iconv_clear(git_path_iconv_t *ic) } } -int git_path_iconv(git_path_iconv_t *ic, char **in, size_t *inlen) +int git_path_iconv(git_path_iconv_t *ic, const char **in, size_t *inlen) { char *nfd = *in, *nfc; size_t nfdlen = *inlen, nfclen, wantlen = nfdlen, alloclen, rv; @@ -1018,8 +1018,7 @@ int git_path_direach( int error = 0; ssize_t wd_len; DIR *dir; - path_dirent_data de_data; - struct dirent *de, *de_buf = (struct dirent *)&de_data; + struct dirent *de; #ifdef GIT_USE_ICONV git_path_iconv_t ic = GIT_PATH_ICONV_INIT; @@ -1045,8 +1044,8 @@ int git_path_direach( (void)git_path_iconv_init_precompose(&ic); #endif - while (p_readdir_r(dir, de_buf, &de) == 0 && de != NULL) { - char *de_path = de->d_name; + while ((de = readdir(dir)) != NULL) { + const char *de_path = de->d_name; size_t de_len = strlen(de_path); if (git_path_is_dot_or_dotdot(de_path)) @@ -1066,8 +1065,10 @@ int git_path_direach( git_buf_truncate(path, wd_len); /* restore path */ /* Only set our own error if the callback did not set one already */ - if (error != 0 && !giterr_last()) { - giterr_set_after_callback(error); + if (error != 0) { + if (!giterr_last()) + giterr_set_after_callback(error); + break; } } @@ -1229,6 +1230,8 @@ void git_path_diriter_free(git_path_diriter *diriter) if (diriter == NULL) return; + git_buf_free(&diriter->path_utf8); + if (diriter->handle != INVALID_HANDLE_VALUE) { FindClose(diriter->handle); diriter->handle = INVALID_HANDLE_VALUE; @@ -1302,7 +1305,7 @@ int git_path_diriter_next(git_path_diriter *diriter) #ifdef GIT_USE_ICONV if ((diriter->flags & GIT_PATH_DIR_PRECOMPOSE_UNICODE) != 0 && - (error = git_path_iconv(&diriter->ic, (char **)&filename, &filename_len)) < 0) + (error = git_path_iconv(&diriter->ic, &filename, &filename_len)) < 0) return error; #endif @@ -1471,7 +1474,7 @@ static int32_t next_hfs_char(const char **in, size_t *len) * the ASCII range, which is perfectly fine, because the * git folder name can only be composed of ascii characters */ - return tolower(codepoint); + return git__tolower(codepoint); } return 0; /* NULL byte -- end of string */ } diff --git a/src/path.h b/src/path.h index 14237cb4673..5927a53812c 100644 --- a/src/path.h +++ b/src/path.h @@ -407,7 +407,7 @@ extern void git_path_iconv_clear(git_path_iconv_t *ic); * pointer internal iconv buffer if rewrite happened. The `in` pointer * will be left unchanged if no rewrite was needed. */ -extern int git_path_iconv(git_path_iconv_t *ic, char **in, size_t *inlen); +extern int git_path_iconv(git_path_iconv_t *ic, const char **in, size_t *inlen); #endif /* GIT_USE_ICONV */ diff --git a/src/rebase.c b/src/rebase.c index b636e7951df..8da7b4f7f0f 100644 --- a/src/rebase.c +++ b/src/rebase.c @@ -512,7 +512,7 @@ static int rebase_ensure_not_dirty( git_tree *head = NULL; git_index *index = NULL; git_diff *diff = NULL; - int error; + int error = 0; if (check_index) { if ((error = git_repository_head_tree(&head, repo)) < 0 || diff --git a/src/refs.c b/src/refs.c index ff5e24067f0..7b538659d9b 100644 --- a/src/refs.c +++ b/src/refs.c @@ -863,7 +863,7 @@ int git_reference__normalize_name( const char *name, unsigned int flags) { - char *current; + const char *current; int segment_len, segments_count = 0, error = GIT_EINVALIDSPEC; unsigned int process_flags; bool normalize = (buf != NULL); diff --git a/src/remote.c b/src/remote.c index 43b34561dc7..7c2d9993765 100644 --- a/src/remote.c +++ b/src/remote.c @@ -28,6 +28,7 @@ static int dwim_refspecs(git_vector *out, git_vector *refspecs, git_vector *refs); static int lookup_remote_prune_config(git_remote *remote, git_config *config, const char *name); +char *apply_insteadof(git_config *config, const char *url, int direction); static int add_refspec_to(git_vector *vector, const char *string, bool is_fetch) { @@ -166,14 +167,18 @@ static int get_check_cert(int *out, git_repository *repo) static int canonicalize_url(git_buf *out, const char *in) { -#ifdef GIT_WIN32 - const char *c; + if (in == NULL || strlen(in) == 0) { + giterr_set(GITERR_INVALID, "cannot set empty URL"); + return GIT_EINVALIDSPEC; + } +#ifdef GIT_WIN32 /* Given a UNC path like \\server\path, we need to convert this * to //server/path for compatibility with core git. */ if (in[0] == '\\' && in[1] == '\\' && (git__isalpha(in[2]) || git__isdigit(in[2]))) { + const char *c; for (c = in; *c; c++) git_buf_putc(out, *c == '\\' ? '/' : *c); @@ -207,7 +212,7 @@ static int create_internal(git_remote **out, git_repository *repo, const char *n canonicalize_url(&canonical_url, url) < 0) goto on_error; - remote->url = git_buf_detach(&canonical_url); + remote->url = apply_insteadof(repo->_config, canonical_url.ptr, GIT_DIRECTION_FETCH); if (name != NULL) { remote->name = git__strdup(name); @@ -216,7 +221,7 @@ static int create_internal(git_remote **out, git_repository *repo, const char *n if ((error = git_buf_printf(&var, CONFIG_URL_FMT, name)) < 0) goto on_error; - if ((error = git_config_set_string(config, var.ptr, remote->url)) < 0) + if ((error = git_config_set_string(config, var.ptr, canonical_url.ptr)) < 0) goto on_error; } @@ -341,7 +346,7 @@ int git_remote_dup(git_remote **dest, git_remote *source) if (source->url != NULL) { remote->url = git__strdup(source->url); - GITERR_CHECK_ALLOC(remote->url); + GITERR_CHECK_ALLOC(remote->url); } if (source->pushurl != NULL) { @@ -456,7 +461,7 @@ int git_remote_lookup(git_remote **out, git_repository *repo, const char *name) remote->download_tags = GIT_REMOTE_DOWNLOAD_TAGS_AUTO; if (found && strlen(val) > 0) { - remote->url = git__strdup(val); + remote->url = apply_insteadof(config, val, GIT_DIRECTION_FETCH); GITERR_CHECK_ALLOC(remote->url); } @@ -476,7 +481,7 @@ int git_remote_lookup(git_remote **out, git_repository *repo, const char *name) } if (found && strlen(val) > 0) { - remote->pushurl = git__strdup(val); + remote->pushurl = apply_insteadof(config, val, GIT_DIRECTION_PUSH); GITERR_CHECK_ALLOC(remote->pushurl); } @@ -868,7 +873,7 @@ int git_remote_download(git_remote *remote, const git_strarray *refspecs, const { int error = -1; size_t i; - git_vector refs, specs, *to_active; + git_vector *to_active, specs = GIT_VECTOR_INIT, refs = GIT_VECTOR_INIT; const git_remote_callbacks *cbs = NULL; assert(remote); @@ -2421,3 +2426,68 @@ int git_remote_push(git_remote *remote, const git_strarray *refspecs, const git_ git_remote_disconnect(remote); return error; } + +#define PREFIX "url" +#define SUFFIX_FETCH "insteadof" +#define SUFFIX_PUSH "pushinsteadof" + +char *apply_insteadof(git_config *config, const char *url, int direction) +{ + size_t match_length, prefix_length, suffix_length; + char *replacement = NULL; + const char *regexp; + + git_buf result = GIT_BUF_INIT; + git_config_entry *entry; + git_config_iterator *iter; + + assert(config); + assert(url); + assert(direction == GIT_DIRECTION_FETCH || direction == GIT_DIRECTION_PUSH); + + /* Add 1 to prefix/suffix length due to the additional escaped dot */ + prefix_length = strlen(PREFIX) + 1; + if (direction == GIT_DIRECTION_FETCH) { + regexp = PREFIX "\\..*\\." SUFFIX_FETCH; + suffix_length = strlen(SUFFIX_FETCH) + 1; + } else { + regexp = PREFIX "\\..*\\." SUFFIX_PUSH; + suffix_length = strlen(SUFFIX_PUSH) + 1; + } + + if (git_config_iterator_glob_new(&iter, config, regexp) < 0) + return NULL; + + match_length = 0; + while (git_config_next(&entry, iter) == 0) { + size_t n, replacement_length; + + /* Check if entry value is a prefix of URL */ + if (git__prefixcmp(url, entry->value)) + continue; + /* Check if entry value is longer than previous + * prefixes */ + if ((n = strlen(entry->value)) <= match_length) + continue; + + git__free(replacement); + match_length = n; + + /* Cut off prefix and suffix of the value */ + replacement_length = + strlen(entry->name) - (prefix_length + suffix_length); + replacement = git__strndup(entry->name + prefix_length, + replacement_length); + } + + git_config_iterator_free(iter); + + if (match_length == 0) + return git__strdup(url); + + git_buf_printf(&result, "%s%s", replacement, url + match_length); + + git__free(replacement); + + return result.ptr; +} diff --git a/src/stash.c b/src/stash.c index 0c5cd1d2afa..a7a288c2558 100644 --- a/src/stash.c +++ b/src/stash.c @@ -761,7 +761,7 @@ int git_stash_apply( goto cleanup; if (git_index_has_conflicts(unstashed_index)) { - error = GIT_EMERGECONFLICT; + error = GIT_ECONFLICT; goto cleanup; } } diff --git a/src/stransport_stream.c b/src/stransport_stream.c index 429aa2d5550..34c38b22d41 100644 --- a/src/stransport_stream.c +++ b/src/stransport_stream.c @@ -24,11 +24,16 @@ int stransport_error(OSStatus ret) return 0; } +#if !TARGET_OS_IPHONE message = SecCopyErrorMessageString(ret, NULL); GITERR_CHECK_ALLOC(message); giterr_set(GITERR_NET, "SecureTransport error: %s", CFStringGetCStringPtr(message, kCFStringEncodingUTF8)); CFRelease(message); +#else + giterr_set(GITERR_NET, "SecureTransport error: OSStatus %d", (unsigned int)ret); +#endif + return -1; } @@ -110,19 +115,26 @@ int stransport_certificate(git_cert **out, git_stream *stream) return 0; } +/* + * Contrary to typical network IO callbacks, Secure Transport write callback is + * expected to write *all* passed data, not just as much as it can, and any + * other case would be considered a failure. + * + * This behavior is actually not specified in the Apple documentation, but is + * required for things to work correctly (and incidentally, that's also how + * Apple implements it in its projects at opensource.apple.com). + * + * Libgit2 streams happen to already have this very behavior so this is just + * passthrough. + */ static OSStatus write_cb(SSLConnectionRef conn, const void *data, size_t *len) { git_stream *io = (git_stream *) conn; - ssize_t ret; - ret = git_stream_write(io, data, *len, 0); - if (ret < 0) { - *len = 0; - return -1; + if (git_stream_write(io, data, *len, 0) < 0) { + return -36; /* "ioErr" from MacErrors.h which is not available on iOS */ } - *len = ret; - return noErr; } @@ -141,29 +153,38 @@ ssize_t stransport_write(git_stream *stream, const char *data, size_t len, int f return processed; } +/* + * Contrary to typical network IO callbacks, Secure Transport read callback is + * expected to read *exactly* the requested number of bytes, not just as much + * as it can, and any other case would be considered a failure. + * + * This behavior is actually not specified in the Apple documentation, but is + * required for things to work correctly (and incidentally, that's also how + * Apple implements it in its projects at opensource.apple.com). + */ static OSStatus read_cb(SSLConnectionRef conn, void *data, size_t *len) { git_stream *io = (git_stream *) conn; + OSStatus error = noErr; + size_t off = 0; ssize_t ret; - size_t left, requested; - requested = left = *len; do { - ret = git_stream_read(io, data + (requested - left), left); + ret = git_stream_read(io, data + off, *len - off); if (ret < 0) { - *len = 0; - return -1; + error = -36; /* "ioErr" from MacErrors.h which is not available on iOS */ + break; + } + if (ret == 0) { + error = errSSLClosedGraceful; + break; } - left -= ret; - } while (left); - - *len = requested; - - if (ret == 0) - return errSSLClosedGraceful; + off += ret; + } while (off < *len); - return noErr; + *len = off; + return error; } ssize_t stransport_read(git_stream *stream, void *data, size_t len) diff --git a/src/transaction.c b/src/transaction.c index 7b45b8bf293..e8331891cb7 100644 --- a/src/transaction.c +++ b/src/transaction.c @@ -13,6 +13,7 @@ #include "reflog.h" #include "signature.h" +#include "git2/transaction.h" #include "git2/signature.h" #include "git2/sys/refs.h" #include "git2/sys/refdb_backend.h" diff --git a/src/transports/cred.c b/src/transports/cred.c index 8163d311509..044b2a262f2 100644 --- a/src/transports/cred.c +++ b/src/transports/cred.c @@ -9,6 +9,14 @@ #include "smart.h" #include "git2/cred_helpers.h" +static int git_cred_ssh_key_type_new( + git_cred **cred, + const char *username, + const char *publickey, + const char *privatekey, + const char *passphrase, + git_credtype_t credtype); + int git_cred_has_username(git_cred *cred) { if (cred->credtype == GIT_CREDTYPE_DEFAULT) @@ -31,6 +39,7 @@ const char *git_cred__username(git_cred *cred) return c->username; } case GIT_CREDTYPE_SSH_KEY: + case GIT_CREDTYPE_SSH_MEMORY: { git_cred_ssh_key *c = (git_cred_ssh_key *) cred; return c->username; @@ -174,6 +183,51 @@ int git_cred_ssh_key_new( const char *publickey, const char *privatekey, const char *passphrase) +{ + return git_cred_ssh_key_type_new( + cred, + username, + publickey, + privatekey, + passphrase, + GIT_CREDTYPE_SSH_KEY); +} + +int git_cred_ssh_key_memory_new( + git_cred **cred, + const char *username, + const char *publickey, + const char *privatekey, + const char *passphrase) +{ +#ifdef GIT_SSH_MEMORY_CREDENTIALS + return git_cred_ssh_key_type_new( + cred, + username, + publickey, + privatekey, + passphrase, + GIT_CREDTYPE_SSH_MEMORY); +#else + GIT_UNUSED(cred); + GIT_UNUSED(username); + GIT_UNUSED(publickey); + GIT_UNUSED(privatekey); + GIT_UNUSED(passphrase); + + giterr_set(GITERR_INVALID, + "This version of libgit2 was not built with ssh memory credentials."); + return -1; +#endif +} + +static int git_cred_ssh_key_type_new( + git_cred **cred, + const char *username, + const char *publickey, + const char *privatekey, + const char *passphrase, + git_credtype_t credtype) { git_cred_ssh_key *c; @@ -182,7 +236,7 @@ int git_cred_ssh_key_new( c = git__calloc(1, sizeof(git_cred_ssh_key)); GITERR_CHECK_ALLOC(c); - c->parent.credtype = GIT_CREDTYPE_SSH_KEY; + c->parent.credtype = credtype; c->parent.free = ssh_key_free; c->username = git__strdup(username); diff --git a/src/transports/ssh.c b/src/transports/ssh.c index 55f715b1d69..83af137f8b9 100644 --- a/src/transports/ssh.c +++ b/src/transports/ssh.c @@ -177,11 +177,12 @@ static int ssh_stream_write( static void ssh_stream_free(git_smart_subtransport_stream *stream) { ssh_stream *s = (ssh_stream *)stream; - ssh_subtransport *t = OWNING_SUBTRANSPORT(s); - int ret; + ssh_subtransport *t; - GIT_UNUSED(ret); + if (!stream) + return; + t = OWNING_SUBTRANSPORT(s); t->current_stream = NULL; if (s->channel) { @@ -293,8 +294,14 @@ static int ssh_agent_auth(LIBSSH2_SESSION *session, git_cred_ssh_key *c) { if (rc < 0) goto shutdown; - if (rc == 1) + /* rc is set to 1 whenever the ssh agent ran out of keys to check. + * Set the error code to authentication failure rather than erroring + * out with an untranslatable error code. + */ + if (rc == 1) { + rc = LIBSSH2_ERROR_AUTHENTICATION_FAILED; goto shutdown; + } rc = libssh2_agent_userauth(agent, c->username, curr); @@ -370,6 +377,25 @@ static int _git_ssh_authenticate_session( session, c->username, c->prompt_callback); break; } +#ifdef GIT_SSH_MEMORY_CREDENTIALS + case GIT_CREDTYPE_SSH_MEMORY: { + git_cred_ssh_key *c = (git_cred_ssh_key *)cred; + + assert(c->username); + assert(c->privatekey); + + rc = libssh2_userauth_publickey_frommemory( + session, + c->username, + strlen(c->username), + c->publickey, + c->publickey ? strlen(c->publickey) : 0, + c->privatekey, + strlen(c->privatekey), + c->passphrase); + break; + } +#endif default: rc = LIBSSH2_ERROR_AUTHENTICATION_FAILED; } @@ -596,8 +622,7 @@ static int _git_ssh_setup_conn( done: if (error < 0) { - if (*stream) - ssh_stream_free(*stream); + ssh_stream_free(*stream); if (session) libssh2_session_free(session); @@ -740,6 +765,9 @@ static int list_auth_methods(int *out, LIBSSH2_SESSION *session, const char *use if (!git__prefixcmp(ptr, SSH_AUTH_PUBLICKEY)) { *out |= GIT_CREDTYPE_SSH_KEY; *out |= GIT_CREDTYPE_SSH_CUSTOM; +#ifdef GIT_SSH_MEMORY_CREDENTIALS + *out |= GIT_CREDTYPE_SSH_MEMORY; +#endif ptr += strlen(SSH_AUTH_PUBLICKEY); continue; } diff --git a/src/unix/posix.h b/src/unix/posix.h index 8b4f427f774..425e6bb1b27 100644 --- a/src/unix/posix.h +++ b/src/unix/posix.h @@ -19,6 +19,9 @@ typedef int GIT_SOCKET; #define p_lstat(p,b) lstat(p,b) #define p_stat(p,b) stat(p, b) +#define p_utimes(f, t) utimes(f, t) +#define p_futimes(f, t) futimes(f, t) + #define p_readlink(a, b, c) readlink(a, b, c) #define p_symlink(o,n) symlink(o, n) #define p_link(o,n) link(o, n) diff --git a/src/util.c b/src/util.c index 6bb7d03ee4f..c62826420f6 100644 --- a/src/util.c +++ b/src/util.c @@ -171,9 +171,9 @@ int git__strcmp(const char *a, const char *b) int git__strcasecmp(const char *a, const char *b) { - while (*a && *b && tolower(*a) == tolower(*b)) + while (*a && *b && git__tolower(*a) == git__tolower(*b)) ++a, ++b; - return (tolower(*a) - tolower(*b)); + return ((unsigned char)git__tolower(*a) - (unsigned char)git__tolower(*b)); } int git__strcasesort_cmp(const char *a, const char *b) @@ -182,7 +182,7 @@ int git__strcasesort_cmp(const char *a, const char *b) while (*a && *b) { if (*a != *b) { - if (tolower(*a) != tolower(*b)) + if (git__tolower(*a) != git__tolower(*b)) break; /* use case in sort order even if not in equivalence */ if (!cmp) @@ -193,7 +193,7 @@ int git__strcasesort_cmp(const char *a, const char *b) } if (*a || *b) - return tolower(*a) - tolower(*b); + return (unsigned char)git__tolower(*a) - (unsigned char)git__tolower(*b); return cmp; } @@ -212,8 +212,8 @@ int git__strncasecmp(const char *a, const char *b, size_t sz) int al, bl; do { - al = (unsigned char)tolower(*a); - bl = (unsigned char)tolower(*b); + al = (unsigned char)git__tolower(*a); + bl = (unsigned char)git__tolower(*b); ++a, ++b; } while (--sz && al && al == bl); @@ -225,7 +225,7 @@ void git__strntolower(char *str, size_t len) size_t i; for (i = 0; i < len; ++i) { - str[i] = (char) tolower(str[i]); + str[i] = (char)git__tolower(str[i]); } } @@ -255,8 +255,8 @@ int git__prefixncmp_icase(const char *str, size_t str_n, const char *prefix) int s, p; while(str_n--) { - s = (unsigned char)tolower(*str++); - p = (unsigned char)tolower(*prefix++); + s = (unsigned char)git__tolower(*str++); + p = (unsigned char)git__tolower(*prefix++); if (s != p) return s - p; diff --git a/src/util.h b/src/util.h index be6534580d1..b2abbe6a652 100644 --- a/src/util.h +++ b/src/util.h @@ -275,6 +275,15 @@ extern char *git__strsep(char **end, const char *sep); extern void git__strntolower(char *str, size_t len); extern void git__strtolower(char *str); +#ifdef GIT_WIN32 +GIT_INLINE(int) git__tolower(int c) +{ + return (c >= 'A' && c <= 'Z') ? (c + 32) : c; +} +#else +# define git__tolower(a) tolower(a) +#endif + GIT_INLINE(const char *) git__next_line(const char *s) { while (*s && *s != '\n') s++; diff --git a/src/win32/posix.h b/src/win32/posix.h index bf35c812536..ac98fd864ed 100644 --- a/src/win32/posix.h +++ b/src/win32/posix.h @@ -20,6 +20,9 @@ typedef SOCKET GIT_SOCKET; extern int p_lstat(const char *file_name, struct stat *buf); extern int p_stat(const char* path, struct stat* buf); +extern int p_utimes(const char *filename, const struct timeval times[2]); +extern int p_futimes(int fd, const struct timeval times[2]); + extern int p_readlink(const char *path, char *buf, size_t bufsiz); extern int p_symlink(const char *old, const char *new); extern int p_link(const char *old, const char *new); diff --git a/src/win32/posix_w32.c b/src/win32/posix_w32.c index 332ea233c6b..504562b0e3e 100644 --- a/src/win32/posix_w32.c +++ b/src/win32/posix_w32.c @@ -201,6 +201,44 @@ int p_lstat_posixly(const char *filename, struct stat *buf) return do_lstat(filename, buf, true); } +int p_utimes(const char *filename, const struct timeval times[2]) +{ + int fd, error; + + if ((fd = p_open(filename, O_RDWR)) < 0) + return fd; + + error = p_futimes(fd, times); + + close(fd); + return error; +} + +int p_futimes(int fd, const struct timeval times[2]) +{ + HANDLE handle; + FILETIME atime = {0}, mtime = {0}; + + if (times == NULL) { + SYSTEMTIME st; + + GetSystemTime(&st); + SystemTimeToFileTime(&st, &atime); + SystemTimeToFileTime(&st, &mtime); + } else { + git_win32__timeval_to_filetime(&atime, times[0]); + git_win32__timeval_to_filetime(&mtime, times[1]); + } + + if ((handle = (HANDLE)_get_osfhandle(fd)) == INVALID_HANDLE_VALUE) + return -1; + + if (SetFileTime(handle, NULL, &atime, &mtime) == 0) + return -1; + + return 0; +} + int p_readlink(const char *path, char *buf, size_t bufsiz) { git_win32_path path_w, target_w; diff --git a/src/win32/w32_util.h b/src/win32/w32_util.h index 8cb0f5b9436..377d651a8d4 100644 --- a/src/win32/w32_util.h +++ b/src/win32/w32_util.h @@ -79,6 +79,16 @@ GIT_INLINE(time_t) git_win32__filetime_to_time_t(const FILETIME *ft) return (time_t)winTime; } +GIT_INLINE(void) git_win32__timeval_to_filetime( + FILETIME *ft, const struct timeval tv) +{ + long long ticks = (tv.tv_sec * 10000000LL) + + (tv.tv_usec * 10LL) + 116444736000000000LL; + + ft->dwHighDateTime = ((ticks >> 32) & 0xffffffffLL); + ft->dwLowDateTime = (ticks & 0xffffffffLL); +} + GIT_INLINE(int) git_win32__file_attribute_to_stat( struct stat *st, const WIN32_FILE_ATTRIBUTE_DATA *attrdata, diff --git a/tests/checkout/checkout_helpers.c b/tests/checkout/checkout_helpers.c index 06b4e0682e5..f6e36d39b45 100644 --- a/tests/checkout/checkout_helpers.c +++ b/tests/checkout/checkout_helpers.c @@ -2,6 +2,7 @@ #include "checkout_helpers.h" #include "refs.h" #include "fileops.h" +#include "index.h" void assert_on_branch(git_repository *repo, const char *branch) { @@ -128,3 +129,24 @@ int checkout_count_callback( return 0; } + +void tick_index(git_index *index) +{ + int index_fd; + git_time_t ts; + struct timeval times[2]; + + cl_assert(index->on_disk); + cl_assert(git_index_path(index)); + + cl_git_pass(git_index_read(index, true)); + ts = index->stamp.mtime; + + times[0].tv_sec = ts; + times[0].tv_usec = 0; + times[1].tv_sec = ts + 1; + times[1].tv_usec = 0; + + cl_git_pass(p_utimes(git_index_path(index), times)); + cl_git_pass(git_index_read(index, true)); +} diff --git a/tests/checkout/checkout_helpers.h b/tests/checkout/checkout_helpers.h index 705ee903d15..6058a196c70 100644 --- a/tests/checkout/checkout_helpers.h +++ b/tests/checkout/checkout_helpers.h @@ -27,3 +27,5 @@ extern int checkout_count_callback( const git_diff_file *target, const git_diff_file *workdir, void *payload); + +extern void tick_index(git_index *index); diff --git a/tests/checkout/crlf.c b/tests/checkout/crlf.c index 381b0401374..61459b3a44e 100644 --- a/tests/checkout/crlf.c +++ b/tests/checkout/crlf.c @@ -4,6 +4,7 @@ #include "git2/checkout.h" #include "repository.h" +#include "index.h" #include "posix.h" static git_repository *g_repo; @@ -40,9 +41,10 @@ void test_checkout_crlf__autocrlf_false_index_size_is_unfiltered_size(void) cl_repo_set_bool(g_repo, "core.autocrlf", false); - git_checkout_head(g_repo, &opts); - git_repository_index(&index, g_repo); + tick_index(index); + + git_checkout_head(g_repo, &opts); cl_assert((entry = git_index_get_bypath(index, "all-lf", 0)) != NULL); cl_assert(entry->file_size == strlen(ALL_LF_TEXT_RAW)); @@ -140,9 +142,10 @@ void test_checkout_crlf__autocrlf_true_index_size_is_filtered_size(void) cl_repo_set_bool(g_repo, "core.autocrlf", true); - git_checkout_head(g_repo, &opts); - git_repository_index(&index, g_repo); + tick_index(index); + + git_checkout_head(g_repo, &opts); cl_assert((entry = git_index_get_bypath(index, "all-lf", 0)) != NULL); diff --git a/tests/checkout/icase.c b/tests/checkout/icase.c index 510f5424d85..55ab3ab24ba 100644 --- a/tests/checkout/icase.c +++ b/tests/checkout/icase.c @@ -269,7 +269,9 @@ void test_checkout_icase__ignores_unstaged_casechange(void) cl_git_pass(git_checkout_tree(repo, (const git_object *)br2, &checkout_opts)); git_commit_free(orig); + git_commit_free(br2); git_reference_free(orig_ref); + git_reference_free(br2_ref); } void test_checkout_icase__conflicts_with_casechanged_subtrees(void) diff --git a/tests/checkout/tree.c b/tests/checkout/tree.c index 46232318696..be4019822f4 100644 --- a/tests/checkout/tree.c +++ b/tests/checkout/tree.c @@ -306,7 +306,7 @@ void test_checkout_tree__conflict_on_ignored_when_not_overwriting(void) cl_git_fail(error = checkout_tree_with_blob_ignored_in_workdir( GIT_CHECKOUT_SAFE | GIT_CHECKOUT_DONT_OVERWRITE_IGNORED, false)); - cl_assert_equal_i(GIT_EMERGECONFLICT, error); + cl_assert_equal_i(GIT_ECONFLICT, error); } void test_checkout_tree__can_overwrite_ignored_by_default(void) @@ -327,7 +327,7 @@ void test_checkout_tree__conflict_on_ignored_folder_when_not_overwriting(void) cl_git_fail(error = checkout_tree_with_blob_ignored_in_workdir( GIT_CHECKOUT_SAFE | GIT_CHECKOUT_DONT_OVERWRITE_IGNORED, true)); - cl_assert_equal_i(GIT_EMERGECONFLICT, error); + cl_assert_equal_i(GIT_ECONFLICT, error); } void test_checkout_tree__can_overwrite_ignored_folder_by_default(void) @@ -512,7 +512,7 @@ void assert_conflict( g_opts.checkout_strategy = GIT_CHECKOUT_SAFE; cl_assert_equal_i( - GIT_EMERGECONFLICT, git_checkout_tree(g_repo, g_object, &g_opts)); + GIT_ECONFLICT, git_checkout_tree(g_repo, g_object, &g_opts)); /* Stage the conflicting change */ cl_git_pass(git_index_add_bypath(index, entry_path)); @@ -520,10 +520,10 @@ void assert_conflict( git_index_free(index); cl_assert_equal_i( - GIT_EMERGECONFLICT, git_checkout_tree(g_repo, g_object, &g_opts)); + GIT_ECONFLICT, git_checkout_tree(g_repo, g_object, &g_opts)); } -void test_checkout_tree__checking_out_a_conflicting_type_change_returns_EMERGECONFLICT(void) +void test_checkout_tree__checking_out_a_conflicting_type_change_returns_ECONFLICT(void) { /* * 099faba adds a symlink named 'link_to_new.txt' @@ -533,7 +533,7 @@ void test_checkout_tree__checking_out_a_conflicting_type_change_returns_EMERGECO assert_conflict("link_to_new.txt", "old.txt", "a65fedf", "099faba"); } -void test_checkout_tree__checking_out_a_conflicting_type_change_returns_EMERGECONFLICT_2(void) +void test_checkout_tree__checking_out_a_conflicting_type_change_returns_ECONFLICT_2(void) { /* * cf80f8d adds a directory named 'a/' @@ -543,7 +543,7 @@ void test_checkout_tree__checking_out_a_conflicting_type_change_returns_EMERGECO assert_conflict("a", "hello\n", "a4a7dce", "cf80f8d"); } -void test_checkout_tree__checking_out_a_conflicting_content_change_returns_EMERGECONFLICT(void) +void test_checkout_tree__checking_out_a_conflicting_content_change_returns_ECONFLICT(void) { /* * c47800c adds a symlink named 'branch_file.txt' diff --git a/tests/commit/parse.c b/tests/commit/parse.c index 41e162440e3..fa079f47099 100644 --- a/tests/commit/parse.c +++ b/tests/commit/parse.c @@ -262,6 +262,13 @@ gpgsig -----BEGIN PGP SIGNATURE-----\n\ -----END PGP SIGNATURE-----\n\ \n\ a simple commit which works\n", +/* some tools create two author entries */ +"tree 1810dff58d8a660512d4832e740f692884338ccd\n\ +author Vicent Marti 1273848544 +0200\n\ +author Helpful Coworker 1273848544 +0200\n\ +committer Vicent Marti 1273848544 +0200\n\ +\n\ +a simple commit which works", }; static int parse_commit(git_commit **out, const char *buffer) diff --git a/tests/core/iconv.c b/tests/core/iconv.c index cb85f458a98..498094bdbb8 100644 --- a/tests/core/iconv.c +++ b/tests/core/iconv.c @@ -24,7 +24,7 @@ void test_core_iconv__cleanup(void) void test_core_iconv__unchanged(void) { #ifdef GIT_USE_ICONV - char *data = "Ascii data", *original = data; + const char *data = "Ascii data", *original = data; size_t datalen = strlen(data); cl_git_pass(git_path_iconv(&ic, &data, &datalen)); @@ -38,7 +38,7 @@ void test_core_iconv__unchanged(void) void test_core_iconv__decomposed_to_precomposed(void) { #ifdef GIT_USE_ICONV - char *data = nfd; + const char *data = nfd; size_t datalen, nfdlen = strlen(nfd); datalen = nfdlen; @@ -64,7 +64,7 @@ void test_core_iconv__decomposed_to_precomposed(void) void test_core_iconv__precomposed_is_unmodified(void) { #ifdef GIT_USE_ICONV - char *data = nfc; + const char *data = nfc; size_t datalen = strlen(nfc); cl_git_pass(git_path_iconv(&ic, &data, &datalen)); diff --git a/tests/core/path.c b/tests/core/path.c index 7d3e4938fd3..c3e622f0221 100644 --- a/tests/core/path.c +++ b/tests/core/path.c @@ -492,7 +492,7 @@ void test_core_path__13_cannot_prettify_a_non_existing_file(void) { git_buf p = GIT_BUF_INIT; - cl_must_pass(git_path_exists(NON_EXISTING_FILEPATH) == false); + cl_assert_equal_b(git_path_exists(NON_EXISTING_FILEPATH), false); cl_assert_equal_i(GIT_ENOTFOUND, git_path_prettify(&p, NON_EXISTING_FILEPATH, NULL)); cl_assert_equal_i(GIT_ENOTFOUND, git_path_prettify(&p, NON_EXISTING_FILEPATH "/so-do-i", NULL)); diff --git a/tests/core/posix.c b/tests/core/posix.c index 1cef937cdb0..5a9e24899f9 100644 --- a/tests/core/posix.c +++ b/tests/core/posix.c @@ -97,3 +97,52 @@ void test_core_posix__inet_pton(void) cl_git_fail(p_inet_pton(5, "315.124", NULL)); /* AF_CHAOS */ cl_assert_equal_i(EAFNOSUPPORT, errno); } + +void test_core_posix__utimes(void) +{ + struct timeval times[2]; + struct stat st; + time_t curtime; + int fd; + + /* test p_utimes */ + times[0].tv_sec = 1234567890; + times[0].tv_usec = 0; + times[1].tv_sec = 1234567890; + times[1].tv_usec = 0; + + cl_git_mkfile("foo", "Dummy file."); + cl_must_pass(p_utimes("foo", times)); + + p_stat("foo", &st); + cl_assert_equal_i(1234567890, st.st_atime); + cl_assert_equal_i(1234567890, st.st_mtime); + + + /* test p_futimes */ + times[0].tv_sec = 1414141414; + times[0].tv_usec = 0; + times[1].tv_sec = 1414141414; + times[1].tv_usec = 0; + + cl_must_pass(fd = p_open("foo", O_RDWR)); + cl_must_pass(p_futimes(fd, times)); + p_close(fd); + + p_stat("foo", &st); + cl_assert_equal_i(1414141414, st.st_atime); + cl_assert_equal_i(1414141414, st.st_mtime); + + + /* test p_utimes with current time, assume that + * it takes < 5 seconds to get the time...! + */ + cl_must_pass(p_utimes("foo", NULL)); + + curtime = time(NULL); + p_stat("foo", &st); + cl_assert((st.st_atime - curtime) < 5); + cl_assert((st.st_mtime - curtime) < 5); + + p_unlink("foo"); +} diff --git a/tests/core/string.c b/tests/core/string.c index ec95756859f..90e8fa027cf 100644 --- a/tests/core/string.c +++ b/tests/core/string.c @@ -39,3 +39,45 @@ void test_core_string__2(void) cl_assert(git__strcasesort_cmp("BAR", "foo") < 0); cl_assert(git__strcasesort_cmp("fooBar", "foobar") < 0); } + +void test_core_string__strcmp(void) +{ + cl_assert(git__strcmp("", "") == 0); + cl_assert(git__strcmp("foo", "foo") == 0); + cl_assert(git__strcmp("Foo", "foo") < 0); + cl_assert(git__strcmp("foo", "FOO") > 0); + cl_assert(git__strcmp("foo", "fOO") > 0); + + cl_assert(strcmp("rt\303\202of", "rt dev\302\266h") > 0); + cl_assert(strcmp("e\342\202\254ghi=", "et") > 0); + cl_assert(strcmp("rt dev\302\266h", "rt\303\202of") < 0); + cl_assert(strcmp("et", "e\342\202\254ghi=") < 0); + cl_assert(strcmp("\303\215", "\303\255") < 0); + + cl_assert(git__strcmp("rt\303\202of", "rt dev\302\266h") > 0); + cl_assert(git__strcmp("e\342\202\254ghi=", "et") > 0); + cl_assert(git__strcmp("rt dev\302\266h", "rt\303\202of") < 0); + cl_assert(git__strcmp("et", "e\342\202\254ghi=") < 0); + cl_assert(git__strcmp("\303\215", "\303\255") < 0); +} + +void test_core_string__strcasecmp(void) +{ + cl_assert(git__strcasecmp("", "") == 0); + cl_assert(git__strcasecmp("foo", "foo") == 0); + cl_assert(git__strcasecmp("foo", "Foo") == 0); + cl_assert(git__strcasecmp("foo", "FOO") == 0); + cl_assert(git__strcasecmp("foo", "fOO") == 0); + + cl_assert(strcasecmp("rt\303\202of", "rt dev\302\266h") > 0); + cl_assert(strcasecmp("e\342\202\254ghi=", "et") > 0); + cl_assert(strcasecmp("rt dev\302\266h", "rt\303\202of") < 0); + cl_assert(strcasecmp("et", "e\342\202\254ghi=") < 0); + cl_assert(strcasecmp("\303\215", "\303\255") < 0); + + cl_assert(git__strcasecmp("rt\303\202of", "rt dev\302\266h") > 0); + cl_assert(git__strcasecmp("e\342\202\254ghi=", "et") > 0); + cl_assert(git__strcasecmp("rt dev\302\266h", "rt\303\202of") < 0); + cl_assert(git__strcasecmp("et", "e\342\202\254ghi=") < 0); + cl_assert(git__strcasecmp("\303\215", "\303\255") < 0); +} diff --git a/tests/diff/binary.c b/tests/diff/binary.c index cb574a588ed..424a53e5f09 100644 --- a/tests/diff/binary.c +++ b/tests/diff/binary.c @@ -261,3 +261,238 @@ void test_diff_binary__delta_append(void) git_index_free(index); } + +void test_diff_binary__index_to_workdir(void) +{ + git_index *index; + git_diff *diff; + git_patch *patch; + git_buf actual = GIT_BUF_INIT; + git_diff_options opts = GIT_DIFF_OPTIONS_INIT; + const char *expected = + "diff --git a/untimely.txt b/untimely.txt\n" \ + "index 9a69d960ae94b060f56c2a8702545e2bb1abb935..1111d4f11f4b35bf6759e0fb714fe09731ef0840 100644\n" \ + "GIT binary patch\n" \ + "delta 32\n" \ + "nc%1vf+QYWt3zLL@hC)e3Vu?a>QDRl4f_G*?PG(-ZA}<#J$+QbW\n" \ + "\n" \ + "delta 7\n" \ + "Oc%18D`@*{63ljhg(E~C7\n"; + + opts.flags = GIT_DIFF_SHOW_BINARY | GIT_DIFF_FORCE_BINARY; + opts.id_abbrev = GIT_OID_HEXSZ; + + repo = cl_git_sandbox_init("renames"); + cl_git_pass(git_repository_index(&index, repo)); + + cl_git_append2file("renames/untimely.txt", "Oh that crazy Kipling!\r\n"); + + cl_git_pass(git_diff_index_to_workdir(&diff, repo, index, &opts)); + + cl_git_pass(git_patch_from_diff(&patch, diff, 0)); + cl_git_pass(git_patch_to_buf(&actual, patch)); + + cl_assert_equal_s(expected, actual.ptr); + + cl_git_pass(git_index_add_bypath(index, "untimely.txt")); + cl_git_pass(git_index_write(index)); + + test_patch( + "19dd32dfb1520a64e5bbaae8dce6ef423dfa2f13", + NULL, + &opts, + expected); + + git_buf_free(&actual); + git_patch_free(patch); + git_diff_free(diff); + git_index_free(index); +} + +static int print_cb( + const git_diff_delta *delta, + const git_diff_hunk *hunk, + const git_diff_line *line, + void *payload) +{ + git_buf *buf = (git_buf *)payload; + + GIT_UNUSED(delta); + + if (hunk) + git_buf_put(buf, hunk->header, hunk->header_len); + + if (line) + git_buf_put(buf, line->content, line->content_len); + + return git_buf_oom(buf) ? -1 : 0; +} + +void test_diff_binary__print_patch_from_diff(void) +{ + git_index *index; + git_diff *diff; + git_buf actual = GIT_BUF_INIT; + git_diff_options opts = GIT_DIFF_OPTIONS_INIT; + const char *expected = + "diff --git a/untimely.txt b/untimely.txt\n" \ + "index 9a69d960ae94b060f56c2a8702545e2bb1abb935..1111d4f11f4b35bf6759e0fb714fe09731ef0840 100644\n" \ + "GIT binary patch\n" \ + "delta 32\n" \ + "nc%1vf+QYWt3zLL@hC)e3Vu?a>QDRl4f_G*?PG(-ZA}<#J$+QbW\n" \ + "\n" \ + "delta 7\n" \ + "Oc%18D`@*{63ljhg(E~C7\n"; + + opts.flags = GIT_DIFF_SHOW_BINARY | GIT_DIFF_FORCE_BINARY; + opts.id_abbrev = GIT_OID_HEXSZ; + + repo = cl_git_sandbox_init("renames"); + cl_git_pass(git_repository_index(&index, repo)); + + cl_git_append2file("renames/untimely.txt", "Oh that crazy Kipling!\r\n"); + + cl_git_pass(git_diff_index_to_workdir(&diff, repo, index, &opts)); + + cl_git_pass(git_diff_print(diff, GIT_DIFF_FORMAT_PATCH, print_cb, &actual)); + + cl_assert_equal_s(expected, actual.ptr); + + git_buf_free(&actual); + git_diff_free(diff); + git_index_free(index); +} + +struct diff_data { + char *old_path; + git_oid old_id; + git_buf old_binary_base85; + size_t old_binary_inflatedlen; + git_diff_binary_t old_binary_type; + + char *new_path; + git_oid new_id; + git_buf new_binary_base85; + size_t new_binary_inflatedlen; + git_diff_binary_t new_binary_type; +}; + +static int file_cb( + const git_diff_delta *delta, + float progress, + void *payload) +{ + struct diff_data *diff_data = payload; + + GIT_UNUSED(progress); + + if (delta->old_file.path) + diff_data->old_path = git__strdup(delta->old_file.path); + + if (delta->new_file.path) + diff_data->new_path = git__strdup(delta->new_file.path); + + git_oid_cpy(&diff_data->old_id, &delta->old_file.id); + git_oid_cpy(&diff_data->new_id, &delta->new_file.id); + + return 0; +} + +static int binary_cb( + const git_diff_delta *delta, + const git_diff_binary *binary, + void *payload) +{ + struct diff_data *diff_data = payload; + + GIT_UNUSED(delta); + + git_buf_encode_base85(&diff_data->old_binary_base85, + binary->old_file.data, binary->old_file.datalen); + diff_data->old_binary_inflatedlen = binary->old_file.inflatedlen; + diff_data->old_binary_type = binary->old_file.type; + + git_buf_encode_base85(&diff_data->new_binary_base85, + binary->new_file.data, binary->new_file.datalen); + diff_data->new_binary_inflatedlen = binary->new_file.inflatedlen; + diff_data->new_binary_type = binary->new_file.type; + + return 0; +} + +static int hunk_cb( + const git_diff_delta *delta, + const git_diff_hunk *hunk, + void *payload) +{ + GIT_UNUSED(delta); + GIT_UNUSED(hunk); + GIT_UNUSED(payload); + + cl_fail("did not expect hunk callback"); + return 0; +} + +static int line_cb( + const git_diff_delta *delta, + const git_diff_hunk *hunk, + const git_diff_line *line, + void *payload) +{ + GIT_UNUSED(delta); + GIT_UNUSED(hunk); + GIT_UNUSED(line); + GIT_UNUSED(payload); + + cl_fail("did not expect line callback"); + return 0; +} + +void test_diff_binary__blob_to_blob(void) +{ + git_index *index; + git_diff_options opts = GIT_DIFF_OPTIONS_INIT; + git_blob *old_blob, *new_blob; + git_oid old_id, new_id; + struct diff_data diff_data = {0}; + + opts.flags = GIT_DIFF_SHOW_BINARY | GIT_DIFF_FORCE_BINARY; + opts.id_abbrev = GIT_OID_HEXSZ; + + repo = cl_git_sandbox_init("renames"); + cl_git_pass(git_repository_index(&index, repo)); + + cl_git_append2file("renames/untimely.txt", "Oh that crazy Kipling!\r\n"); + cl_git_pass(git_index_add_bypath(index, "untimely.txt")); + cl_git_pass(git_index_write(index)); + + git_oid_fromstr(&old_id, "9a69d960ae94b060f56c2a8702545e2bb1abb935"); + git_oid_fromstr(&new_id, "1111d4f11f4b35bf6759e0fb714fe09731ef0840"); + + cl_git_pass(git_blob_lookup(&old_blob, repo, &old_id)); + cl_git_pass(git_blob_lookup(&new_blob, repo, &new_id)); + + cl_git_pass(git_diff_blobs(old_blob, + "untimely.txt", new_blob, "untimely.txt", &opts, + file_cb, binary_cb, hunk_cb, line_cb, &diff_data)); + + cl_assert_equal_s("untimely.txt", diff_data.old_path); + cl_assert_equal_oid(&old_id, &diff_data.old_id); + cl_assert_equal_i(GIT_DIFF_BINARY_DELTA, diff_data.old_binary_type); + cl_assert_equal_i(7, diff_data.old_binary_inflatedlen); + cl_assert_equal_s("c%18D`@*{63ljhg(E~C7", + diff_data.old_binary_base85.ptr); + + cl_assert_equal_s("untimely.txt", diff_data.new_path); + cl_assert_equal_oid(&new_id, &diff_data.new_id); + cl_assert_equal_i(GIT_DIFF_BINARY_DELTA, diff_data.new_binary_type); + cl_assert_equal_i(32, diff_data.new_binary_inflatedlen); + cl_assert_equal_s("c%1vf+QYWt3zLL@hC)e3Vu?a>QDRl4f_G*?PG(-ZA}<#J$+QbW", + diff_data.new_binary_base85.ptr); + + git_blob_free(old_blob); + git_blob_free(new_blob); + + git__free(diff_data.old_path); + git__free(diff_data.new_path); +} diff --git a/tests/diff/blob.c b/tests/diff/blob.c index 51bdbab15e7..b0253f6dcb7 100644 --- a/tests/diff/blob.c +++ b/tests/diff/blob.c @@ -17,7 +17,7 @@ static void quick_diff_blob_to_str( cl_git_pass(git_diff_blob_to_buffer( blob, blob_path, str, len, str_path, - &opts, diff_file_cb, diff_hunk_cb, diff_line_cb, &expected)); + &opts, diff_file_cb, diff_binary_cb, diff_hunk_cb, diff_line_cb, &expected)); } void test_diff_blob__initialize(void) @@ -88,7 +88,7 @@ void test_diff_blob__can_compare_text_blobs(void) memset(&expected, 0, sizeof(expected)); cl_git_pass(git_diff_blobs( a, NULL, b, NULL, &opts, - diff_file_cb, diff_hunk_cb, diff_line_cb, &expected)); + diff_file_cb, diff_binary_cb, diff_hunk_cb, diff_line_cb, &expected)); assert_one_modified(1, 6, 1, 5, 0, &expected); /* same diff but use direct buffers */ @@ -96,27 +96,27 @@ void test_diff_blob__can_compare_text_blobs(void) cl_git_pass(git_diff_buffers( git_blob_rawcontent(a), (size_t)git_blob_rawsize(a), NULL, git_blob_rawcontent(b), (size_t)git_blob_rawsize(b), NULL, &opts, - diff_file_cb, diff_hunk_cb, diff_line_cb, &expected)); + diff_file_cb, diff_binary_cb, diff_hunk_cb, diff_line_cb, &expected)); assert_one_modified(1, 6, 1, 5, 0, &expected); /* diff on tests/resources/attr/root_test2 */ memset(&expected, 0, sizeof(expected)); cl_git_pass(git_diff_blobs( b, NULL, c, NULL, &opts, - diff_file_cb, diff_hunk_cb, diff_line_cb, &expected)); + diff_file_cb, diff_binary_cb, diff_hunk_cb, diff_line_cb, &expected)); assert_one_modified(1, 15, 3, 9, 3, &expected); /* diff on tests/resources/attr/root_test3 */ memset(&expected, 0, sizeof(expected)); cl_git_pass(git_diff_blobs( a, NULL, c, NULL, &opts, - diff_file_cb, diff_hunk_cb, diff_line_cb, &expected)); + diff_file_cb, diff_binary_cb, diff_hunk_cb, diff_line_cb, &expected)); assert_one_modified(1, 13, 0, 12, 1, &expected); memset(&expected, 0, sizeof(expected)); cl_git_pass(git_diff_blobs( c, NULL, d, NULL, &opts, - diff_file_cb, diff_hunk_cb, diff_line_cb, &expected)); + diff_file_cb, diff_binary_cb, diff_hunk_cb, diff_line_cb, &expected)); assert_one_modified(2, 14, 4, 6, 4, &expected); git_blob_free(a); @@ -206,7 +206,7 @@ void test_diff_blob__can_compare_against_null_blobs(void) cl_git_pass(git_diff_blobs( d, NULL, e, NULL, &opts, - diff_file_cb, diff_hunk_cb, diff_line_cb, &expected)); + diff_file_cb, diff_binary_cb, diff_hunk_cb, diff_line_cb, &expected)); cl_assert_equal_i(1, expected.files); cl_assert_equal_i(1, expected.file_status[GIT_DELTA_DELETED]); @@ -222,7 +222,7 @@ void test_diff_blob__can_compare_against_null_blobs(void) cl_git_pass(git_diff_blobs( d, NULL, e, NULL, &opts, - diff_file_cb, diff_hunk_cb, diff_line_cb, &expected)); + diff_file_cb, diff_binary_cb, diff_hunk_cb, diff_line_cb, &expected)); cl_assert_equal_i(1, expected.files); cl_assert_equal_i(1, expected.file_status[GIT_DELTA_ADDED]); @@ -238,7 +238,7 @@ void test_diff_blob__can_compare_against_null_blobs(void) cl_git_pass(git_diff_blobs( alien, NULL, NULL, NULL, &opts, - diff_file_cb, diff_hunk_cb, diff_line_cb, &expected)); + diff_file_cb, diff_binary_cb, diff_hunk_cb, diff_line_cb, &expected)); cl_assert_equal_i(1, expected.files); cl_assert_equal_i(1, expected.files_binary); @@ -250,7 +250,7 @@ void test_diff_blob__can_compare_against_null_blobs(void) cl_git_pass(git_diff_blobs( NULL, NULL, alien, NULL, &opts, - diff_file_cb, diff_hunk_cb, diff_line_cb, &expected)); + diff_file_cb, diff_binary_cb, diff_hunk_cb, diff_line_cb, &expected)); cl_assert_equal_i(1, expected.files); cl_assert_equal_i(1, expected.files_binary); @@ -358,7 +358,7 @@ void test_diff_blob__can_compare_identical_blobs(void) cl_git_pass(git_diff_blobs( d, NULL, d, NULL, &opts, - diff_file_cb, diff_hunk_cb, diff_line_cb, &expected)); + diff_file_cb, diff_binary_cb, diff_hunk_cb, diff_line_cb, &expected)); assert_identical_blobs_comparison(&expected); cl_assert_equal_i(0, expected.files_binary); @@ -366,7 +366,7 @@ void test_diff_blob__can_compare_identical_blobs(void) memset(&expected, 0, sizeof(expected)); cl_git_pass(git_diff_blobs( NULL, NULL, NULL, NULL, &opts, - diff_file_cb, diff_hunk_cb, diff_line_cb, &expected)); + diff_file_cb, diff_binary_cb, diff_hunk_cb, diff_line_cb, &expected)); assert_identical_blobs_comparison(&expected); cl_assert_equal_i(0, expected.files_binary); @@ -374,7 +374,7 @@ void test_diff_blob__can_compare_identical_blobs(void) memset(&expected, 0, sizeof(expected)); cl_git_pass(git_diff_blobs( alien, NULL, alien, NULL, &opts, - diff_file_cb, diff_hunk_cb, diff_line_cb, &expected)); + diff_file_cb, diff_binary_cb, diff_hunk_cb, diff_line_cb, &expected)); assert_identical_blobs_comparison(&expected); cl_assert(expected.files_binary > 0); @@ -441,7 +441,7 @@ void test_diff_blob__can_compare_two_binary_blobs(void) cl_git_pass(git_diff_blobs( alien, NULL, heart, NULL, &opts, - diff_file_cb, diff_hunk_cb, diff_line_cb, &expected)); + diff_file_cb, diff_binary_cb, diff_hunk_cb, diff_line_cb, &expected)); assert_binary_blobs_comparison(&expected); @@ -449,7 +449,7 @@ void test_diff_blob__can_compare_two_binary_blobs(void) cl_git_pass(git_diff_blobs( heart, NULL, alien, NULL, &opts, - diff_file_cb, diff_hunk_cb, diff_line_cb, &expected)); + diff_file_cb, diff_binary_cb, diff_hunk_cb, diff_line_cb, &expected)); assert_binary_blobs_comparison(&expected); @@ -460,7 +460,7 @@ void test_diff_blob__can_compare_a_binary_blob_and_a_text_blob(void) { cl_git_pass(git_diff_blobs( alien, NULL, d, NULL, &opts, - diff_file_cb, diff_hunk_cb, diff_line_cb, &expected)); + diff_file_cb, diff_binary_cb, diff_hunk_cb, diff_line_cb, &expected)); assert_binary_blobs_comparison(&expected); @@ -468,7 +468,7 @@ void test_diff_blob__can_compare_a_binary_blob_and_a_text_blob(void) cl_git_pass(git_diff_blobs( d, NULL, alien, NULL, &opts, - diff_file_cb, diff_hunk_cb, diff_line_cb, &expected)); + diff_file_cb, diff_binary_cb, diff_hunk_cb, diff_line_cb, &expected)); assert_binary_blobs_comparison(&expected); } @@ -510,7 +510,7 @@ void test_diff_blob__comparing_two_text_blobs_honors_interhunkcontext(void) /* Test with default inter-hunk-context (not set) => default is 0 */ cl_git_pass(git_diff_blobs( old_d, NULL, d, NULL, &opts, - diff_file_cb, diff_hunk_cb, diff_line_cb, &expected)); + diff_file_cb, diff_binary_cb, diff_hunk_cb, diff_line_cb, &expected)); cl_assert_equal_i(2, expected.hunks); @@ -519,7 +519,7 @@ void test_diff_blob__comparing_two_text_blobs_honors_interhunkcontext(void) memset(&expected, 0, sizeof(expected)); cl_git_pass(git_diff_blobs( old_d, NULL, d, NULL, &opts, - diff_file_cb, diff_hunk_cb, diff_line_cb, &expected)); + diff_file_cb, diff_binary_cb, diff_hunk_cb, diff_line_cb, &expected)); cl_assert_equal_i(2, expected.hunks); @@ -528,7 +528,7 @@ void test_diff_blob__comparing_two_text_blobs_honors_interhunkcontext(void) memset(&expected, 0, sizeof(expected)); cl_git_pass(git_diff_blobs( old_d, NULL, d, NULL, &opts, - diff_file_cb, diff_hunk_cb, diff_line_cb, &expected)); + diff_file_cb, diff_binary_cb, diff_hunk_cb, diff_line_cb, &expected)); cl_assert_equal_i(1, expected.hunks); @@ -542,7 +542,7 @@ void test_diff_blob__checks_options_version_too_low(void) opts.version = 0; cl_git_fail(git_diff_blobs( d, NULL, alien, NULL, &opts, - diff_file_cb, diff_hunk_cb, diff_line_cb, &expected)); + diff_file_cb, diff_binary_cb, diff_hunk_cb, diff_line_cb, &expected)); err = giterr_last(); cl_assert_equal_i(GITERR_INVALID, err->klass); } @@ -554,7 +554,7 @@ void test_diff_blob__checks_options_version_too_high(void) opts.version = 1024; cl_git_fail(git_diff_blobs( d, NULL, alien, NULL, &opts, - diff_file_cb, diff_hunk_cb, diff_line_cb, &expected)); + diff_file_cb, diff_binary_cb, diff_hunk_cb, diff_line_cb, &expected)); err = giterr_last(); cl_assert_equal_i(GITERR_INVALID, err->klass); } @@ -752,7 +752,7 @@ void test_diff_blob__binary_data_comparisons(void) memset(&expected, 0, sizeof(expected)); cl_git_pass(git_diff_blobs( bin, NULL, nonbin, NULL, &opts, - diff_file_cb, diff_hunk_cb, diff_line_cb, &expected)); + diff_file_cb, diff_binary_cb, diff_hunk_cb, diff_line_cb, &expected)); assert_binary_blobs_comparison(&expected); /* @@ -773,7 +773,7 @@ void test_diff_blob__binary_data_comparisons(void) memset(&expected, 0, sizeof(expected)); cl_git_pass(git_diff_blobs( bin, NULL, nonbin, NULL, &opts, - diff_file_cb, diff_hunk_cb, diff_line_cb, &expected)); + diff_file_cb, diff_binary_cb, diff_hunk_cb, diff_line_cb, &expected)); assert_one_modified_with_lines(&expected, 4); /* cleanup */ @@ -993,8 +993,8 @@ void test_diff_blob__can_compare_buffer_to_buffer(void) memset(&expected, 0, sizeof(expected)); cl_git_pass(git_diff_buffers( - a, strlen(a), NULL, b, strlen(b), NULL, - &opts, diff_file_cb, diff_hunk_cb, diff_line_cb, &expected)); + a, strlen(a), NULL, b, strlen(b), NULL, &opts, + diff_file_cb, diff_binary_cb, diff_hunk_cb, diff_line_cb, &expected)); assert_one_modified(4, 9, 0, 4, 5, &expected); opts.flags ^= GIT_DIFF_REVERSE; @@ -1002,7 +1002,7 @@ void test_diff_blob__can_compare_buffer_to_buffer(void) memset(&expected, 0, sizeof(expected)); cl_git_pass(git_diff_buffers( - a, strlen(a), NULL, b, strlen(b), NULL, - &opts, diff_file_cb, diff_hunk_cb, diff_line_cb, &expected)); + a, strlen(a), NULL, b, strlen(b), NULL, &opts, + diff_file_cb, diff_binary_cb, diff_hunk_cb, diff_line_cb, &expected)); assert_one_modified(4, 9, 0, 5, 4, &expected); } diff --git a/tests/diff/diff_helpers.c b/tests/diff/diff_helpers.c index 03862d6b46c..c6cdf803fc4 100644 --- a/tests/diff/diff_helpers.c +++ b/tests/diff/diff_helpers.c @@ -91,6 +91,18 @@ int diff_print_file_cb( return diff_file_cb(delta, progress, payload); } +int diff_binary_cb( + const git_diff_delta *delta, + const git_diff_binary *binary, + void *payload) +{ + GIT_UNUSED(delta); + GIT_UNUSED(binary); + GIT_UNUSED(payload); + + return 0; +} + int diff_hunk_cb( const git_diff_delta *delta, const git_diff_hunk *hunk, @@ -145,12 +157,15 @@ int diff_line_cb( int diff_foreach_via_iterator( git_diff *diff, git_diff_file_cb file_cb, + git_diff_binary_cb binary_cb, git_diff_hunk_cb hunk_cb, git_diff_line_cb line_cb, void *data) { size_t d, num_d = git_diff_num_deltas(diff); + GIT_UNUSED(binary_cb); + for (d = 0; d < num_d; ++d) { git_patch *patch; const git_diff_delta *delta; diff --git a/tests/diff/diff_helpers.h b/tests/diff/diff_helpers.h index 6bcd1e671d5..4d3cd347440 100644 --- a/tests/diff/diff_helpers.h +++ b/tests/diff/diff_helpers.h @@ -42,6 +42,11 @@ extern int diff_print_file_cb( float progress, void *cb_data); +extern int diff_binary_cb( + const git_diff_delta *delta, + const git_diff_binary *binary, + void *cb_data); + extern int diff_hunk_cb( const git_diff_delta *delta, const git_diff_hunk *hunk, @@ -56,6 +61,7 @@ extern int diff_line_cb( extern int diff_foreach_via_iterator( git_diff *diff, git_diff_file_cb file_cb, + git_diff_binary_cb binary_cb, git_diff_hunk_cb hunk_cb, git_diff_line_cb line_cb, void *data); diff --git a/tests/diff/index.c b/tests/diff/index.c index a544b83c70c..242fb004620 100644 --- a/tests/diff/index.c +++ b/tests/diff/index.c @@ -35,7 +35,7 @@ void test_diff_index__0(void) cl_git_pass(git_diff_tree_to_index(&diff, g_repo, a, NULL, &opts)); cl_git_pass(git_diff_foreach( - diff, diff_file_cb, diff_hunk_cb, diff_line_cb, &exp)); + diff, diff_file_cb, diff_binary_cb, diff_hunk_cb, diff_line_cb, &exp)); /* to generate these values: * - cd to tests/resources/status, @@ -63,7 +63,7 @@ void test_diff_index__0(void) cl_git_pass(git_diff_tree_to_index(&diff, g_repo, b, NULL, &opts)); cl_git_pass(git_diff_foreach( - diff, diff_file_cb, diff_hunk_cb, diff_line_cb, &exp)); + diff, diff_file_cb, diff_binary_cb, diff_hunk_cb, diff_line_cb, &exp)); /* to generate these values: * - cd to tests/resources/status, @@ -127,8 +127,8 @@ void test_diff_index__1(void) cl_git_pass(git_diff_tree_to_index(&diff, g_repo, a, NULL, &opts)); - cl_assert_equal_i( - 1, git_diff_foreach(diff, diff_stop_after_2_files, NULL, NULL, &exp) ); + cl_assert_equal_i(1, git_diff_foreach( + diff, diff_stop_after_2_files, NULL, NULL, NULL, &exp) ); cl_assert_equal_i(2, exp.files); @@ -168,7 +168,7 @@ static void do_conflicted_diff(diff_expects *exp, unsigned long flags) const char *a_commit = "26a125ee1bf"; /* the current HEAD */ git_tree *a = resolve_commit_oid_to_tree(g_repo, a_commit); git_diff_options opts = GIT_DIFF_OPTIONS_INIT; - git_index_entry ancestor = {0}, ours = {0}, theirs = {0}; + git_index_entry ancestor = {{0}}, ours = {{0}}, theirs = {{0}}; git_diff *diff = NULL; git_index *index; @@ -193,7 +193,7 @@ static void do_conflicted_diff(diff_expects *exp, unsigned long flags) cl_git_pass(git_diff_tree_to_index(&diff, g_repo, a, index, &opts)); cl_git_pass(git_diff_foreach( - diff, diff_file_cb, diff_hunk_cb, diff_line_cb, exp)); + diff, diff_file_cb, diff_binary_cb, diff_hunk_cb, diff_line_cb, exp)); git_diff_free(diff); git_tree_free(a); diff --git a/tests/diff/notify.c b/tests/diff/notify.c index da7390d3f07..6ef4af5731c 100644 --- a/tests/diff/notify.c +++ b/tests/diff/notify.c @@ -59,7 +59,7 @@ static void test_notify( memset(&exp, 0, sizeof(exp)); cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, &opts)); - cl_git_pass(git_diff_foreach(diff, diff_file_cb, NULL, NULL, &exp)); + cl_git_pass(git_diff_foreach(diff, diff_file_cb, NULL, NULL, NULL, &exp)); cl_assert_equal_i(expected_diffed_files_count, exp.files); @@ -222,7 +222,7 @@ void test_diff_notify__notify_cb_can_be_used_as_filtering_function(void) memset(&exp, 0, sizeof(exp)); cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, &opts)); - cl_git_pass(git_diff_foreach(diff, diff_file_cb, NULL, NULL, &exp)); + cl_git_pass(git_diff_foreach(diff, diff_file_cb, NULL, NULL, NULL, &exp)); cl_assert_equal_i(0, exp.files); diff --git a/tests/diff/racy.c b/tests/diff/racy.c new file mode 100644 index 00000000000..a109f8c3b7f --- /dev/null +++ b/tests/diff/racy.c @@ -0,0 +1,39 @@ +#include "clar_libgit2.h" + +#include "buffer.h" + +static git_repository *g_repo; + +void test_diff_racy__initialize(void) +{ + cl_git_pass(git_repository_init(&g_repo, "diff_racy", false)); +} + +void test_diff_racy__cleanup(void) +{ + cl_git_sandbox_cleanup(); +} + +void test_diff_racy__diff(void) +{ + git_index *index; + git_diff *diff; + git_buf path = GIT_BUF_INIT; + + cl_git_pass(git_buf_joinpath(&path, git_repository_workdir(g_repo), "A")); + cl_git_mkfile(path.ptr, "A"); + + /* Put 'A' into the index */ + cl_git_pass(git_repository_index(&index, g_repo)); + cl_git_pass(git_index_add_bypath(index, "A")); + cl_git_pass(git_index_write(index)); + + cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, index, NULL)); + cl_assert_equal_i(0, git_diff_num_deltas(diff)); + + /* Change its contents quickly, so we get the same timestamp */ + cl_git_mkfile(path.ptr, "B"); + + cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, index, NULL)); + cl_assert_equal_i(1, git_diff_num_deltas(diff)); +} diff --git a/tests/diff/rename.c b/tests/diff/rename.c index 8a327f0355a..5cfd8e23566 100644 --- a/tests/diff/rename.c +++ b/tests/diff/rename.c @@ -65,7 +65,7 @@ void test_diff_rename__match_oid(void) */ memset(&exp, 0, sizeof(exp)); cl_git_pass(git_diff_foreach( - diff, diff_file_cb, diff_hunk_cb, diff_line_cb, &exp)); + diff, diff_file_cb, diff_binary_cb, diff_hunk_cb, diff_line_cb, &exp)); cl_assert_equal_i(4, exp.files); cl_assert_equal_i(1, exp.file_status[GIT_DELTA_UNMODIFIED]); @@ -81,7 +81,7 @@ void test_diff_rename__match_oid(void) memset(&exp, 0, sizeof(exp)); cl_git_pass(git_diff_foreach( - diff, diff_file_cb, diff_hunk_cb, diff_line_cb, &exp)); + diff, diff_file_cb, diff_binary_cb, diff_hunk_cb, diff_line_cb, &exp)); cl_assert_equal_i(3, exp.files); cl_assert_equal_i(1, exp.file_status[GIT_DELTA_UNMODIFIED]); @@ -102,7 +102,7 @@ void test_diff_rename__match_oid(void) memset(&exp, 0, sizeof(exp)); cl_git_pass(git_diff_foreach( - diff, diff_file_cb, diff_hunk_cb, diff_line_cb, &exp)); + diff, diff_file_cb, diff_binary_cb, diff_hunk_cb, diff_line_cb, &exp)); cl_assert_equal_i(3, exp.files); cl_assert_equal_i(1, exp.file_status[GIT_DELTA_UNMODIFIED]); @@ -124,7 +124,7 @@ void test_diff_rename__match_oid(void) memset(&exp, 0, sizeof(exp)); cl_git_pass(git_diff_foreach( - diff, diff_file_cb, diff_hunk_cb, diff_line_cb, &exp)); + diff, diff_file_cb, diff_binary_cb, diff_hunk_cb, diff_line_cb, &exp)); cl_assert_equal_i(3, exp.files); cl_assert_equal_i(1, exp.file_status[GIT_DELTA_UNMODIFIED]); @@ -204,7 +204,7 @@ void test_diff_rename__not_exact_match(void) */ memset(&exp, 0, sizeof(exp)); cl_git_pass(git_diff_foreach( - diff, diff_file_cb, diff_hunk_cb, diff_line_cb, &exp)); + diff, diff_file_cb, diff_binary_cb, diff_hunk_cb, diff_line_cb, &exp)); cl_assert_equal_i(4, exp.files); cl_assert_equal_i(1, exp.file_status[GIT_DELTA_UNMODIFIED]); @@ -222,7 +222,7 @@ void test_diff_rename__not_exact_match(void) memset(&exp, 0, sizeof(exp)); cl_git_pass(git_diff_foreach( - diff, diff_file_cb, diff_hunk_cb, diff_line_cb, &exp)); + diff, diff_file_cb, diff_binary_cb, diff_hunk_cb, diff_line_cb, &exp)); cl_assert_equal_i(4, exp.files); cl_assert_equal_i(1, exp.file_status[GIT_DELTA_UNMODIFIED]); @@ -243,7 +243,7 @@ void test_diff_rename__not_exact_match(void) memset(&exp, 0, sizeof(exp)); cl_git_pass(git_diff_foreach( - diff, diff_file_cb, diff_hunk_cb, diff_line_cb, &exp)); + diff, diff_file_cb, diff_binary_cb, diff_hunk_cb, diff_line_cb, &exp)); cl_assert_equal_i(4, exp.files); cl_assert_equal_i(1, exp.file_status[GIT_DELTA_UNMODIFIED]); @@ -266,7 +266,7 @@ void test_diff_rename__not_exact_match(void) memset(&exp, 0, sizeof(exp)); cl_git_pass(git_diff_foreach( - diff, diff_file_cb, diff_hunk_cb, diff_line_cb, &exp)); + diff, diff_file_cb, diff_binary_cb, diff_hunk_cb, diff_line_cb, &exp)); cl_assert_equal_i(5, exp.files); cl_assert_equal_i(1, exp.file_status[GIT_DELTA_UNMODIFIED]); @@ -297,7 +297,7 @@ void test_diff_rename__not_exact_match(void) */ memset(&exp, 0, sizeof(exp)); cl_git_pass(git_diff_foreach( - diff, diff_file_cb, diff_hunk_cb, diff_line_cb, &exp)); + diff, diff_file_cb, diff_binary_cb, diff_hunk_cb, diff_line_cb, &exp)); cl_assert_equal_i(6, exp.files); cl_assert_equal_i(2, exp.file_status[GIT_DELTA_MODIFIED]); @@ -317,7 +317,7 @@ void test_diff_rename__not_exact_match(void) memset(&exp, 0, sizeof(exp)); cl_git_pass(git_diff_foreach( - diff, diff_file_cb, diff_hunk_cb, diff_line_cb, &exp)); + diff, diff_file_cb, diff_binary_cb, diff_hunk_cb, diff_line_cb, &exp)); cl_assert_equal_i(4, exp.files); cl_assert_equal_i(2, exp.file_status[GIT_DELTA_MODIFIED]); @@ -344,7 +344,7 @@ void test_diff_rename__not_exact_match(void) memset(&exp, 0, sizeof(exp)); cl_git_pass(git_diff_foreach( - diff, diff_file_cb, diff_hunk_cb, diff_line_cb, &exp)); + diff, diff_file_cb, diff_binary_cb, diff_hunk_cb, diff_line_cb, &exp)); cl_assert_equal_i(5, exp.files); cl_assert_equal_i(1, exp.file_status[GIT_DELTA_MODIFIED]); @@ -369,7 +369,7 @@ void test_diff_rename__not_exact_match(void) memset(&exp, 0, sizeof(exp)); cl_git_pass(git_diff_foreach( - diff, diff_file_cb, diff_hunk_cb, diff_line_cb, &exp)); + diff, diff_file_cb, diff_binary_cb, diff_hunk_cb, diff_line_cb, &exp)); cl_assert_equal_i(4, exp.files); cl_assert_equal_i(2, exp.file_status[GIT_DELTA_MODIFIED]); @@ -469,7 +469,7 @@ void test_diff_rename__working_directory_changes(void) /* git diff --no-renames 2bc7f351d20b53f1c72c16c4b036e491c478c49a */ memset(&exp, 0, sizeof(exp)); cl_git_pass(git_diff_foreach( - diff, diff_file_cb, diff_hunk_cb, diff_line_cb, &exp)); + diff, diff_file_cb, diff_binary_cb, diff_hunk_cb, diff_line_cb, &exp)); cl_assert_equal_i(6, exp.files); cl_assert_equal_i(1, exp.file_status[GIT_DELTA_MODIFIED]); @@ -482,7 +482,7 @@ void test_diff_rename__working_directory_changes(void) memset(&exp, 0, sizeof(exp)); cl_git_pass(git_diff_foreach( - diff, diff_file_cb, diff_hunk_cb, diff_line_cb, &exp)); + diff, diff_file_cb, diff_binary_cb, diff_hunk_cb, diff_line_cb, &exp)); cl_assert_equal_i(5, exp.files); cl_assert_equal_i(2, exp.file_status[GIT_DELTA_RENAMED]); @@ -508,7 +508,7 @@ void test_diff_rename__working_directory_changes(void) memset(&exp, 0, sizeof(exp)); cl_git_pass(git_diff_foreach( - diff, diff_file_cb, diff_hunk_cb, diff_line_cb, &exp)); + diff, diff_file_cb, diff_binary_cb, diff_hunk_cb, diff_line_cb, &exp)); cl_assert_equal_i(5, exp.files); cl_assert_equal_i(2, exp.file_status[GIT_DELTA_RENAMED]); @@ -527,7 +527,7 @@ void test_diff_rename__working_directory_changes(void) memset(&exp, 0, sizeof(exp)); cl_git_pass(git_diff_foreach( - diff, diff_file_cb, diff_hunk_cb, diff_line_cb, &exp)); + diff, diff_file_cb, diff_binary_cb, diff_hunk_cb, diff_line_cb, &exp)); cl_assert_equal_i(6, exp.files); cl_assert_equal_i(1, exp.file_status[GIT_DELTA_RENAMED]); @@ -545,7 +545,7 @@ void test_diff_rename__working_directory_changes(void) memset(&exp, 0, sizeof(exp)); cl_git_pass(git_diff_foreach( - diff, diff_file_cb, diff_hunk_cb, diff_line_cb, &exp)); + diff, diff_file_cb, diff_binary_cb, diff_hunk_cb, diff_line_cb, &exp)); cl_assert_equal_i(6, exp.files); cl_assert_equal_i(1, exp.file_status[GIT_DELTA_MODIFIED]); @@ -575,7 +575,7 @@ void test_diff_rename__working_directory_changes(void) memset(&exp, 0, sizeof(exp)); cl_git_pass(git_diff_foreach( - diff, diff_file_cb, diff_hunk_cb, diff_line_cb, &exp)); + diff, diff_file_cb, diff_binary_cb, diff_hunk_cb, diff_line_cb, &exp)); cl_assert_equal_i(5, exp.files); cl_assert_equal_i(1, exp.file_status[GIT_DELTA_MODIFIED]); @@ -673,7 +673,7 @@ void test_diff_rename__file_exchange(void) memset(&exp, 0, sizeof(exp)); cl_git_pass(git_diff_foreach( - diff, diff_file_cb, diff_hunk_cb, diff_line_cb, &exp)); + diff, diff_file_cb, diff_binary_cb, diff_hunk_cb, diff_line_cb, &exp)); cl_assert_equal_i(2, exp.files); cl_assert_equal_i(2, exp.file_status[GIT_DELTA_MODIFIED]); @@ -682,7 +682,7 @@ void test_diff_rename__file_exchange(void) memset(&exp, 0, sizeof(exp)); cl_git_pass(git_diff_foreach( - diff, diff_file_cb, diff_hunk_cb, diff_line_cb, &exp)); + diff, diff_file_cb, diff_binary_cb, diff_hunk_cb, diff_line_cb, &exp)); cl_assert_equal_i(2, exp.files); cl_assert_equal_i(2, exp.file_status[GIT_DELTA_RENAMED]); @@ -725,7 +725,7 @@ void test_diff_rename__file_exchange_three(void) memset(&exp, 0, sizeof(exp)); cl_git_pass(git_diff_foreach( - diff, diff_file_cb, diff_hunk_cb, diff_line_cb, &exp)); + diff, diff_file_cb, diff_binary_cb, diff_hunk_cb, diff_line_cb, &exp)); cl_assert_equal_i(3, exp.files); cl_assert_equal_i(3, exp.file_status[GIT_DELTA_MODIFIED]); @@ -734,7 +734,7 @@ void test_diff_rename__file_exchange_three(void) memset(&exp, 0, sizeof(exp)); cl_git_pass(git_diff_foreach( - diff, diff_file_cb, diff_hunk_cb, diff_line_cb, &exp)); + diff, diff_file_cb, diff_binary_cb, diff_hunk_cb, diff_line_cb, &exp)); cl_assert_equal_i(3, exp.files); cl_assert_equal_i(3, exp.file_status[GIT_DELTA_RENAMED]); @@ -776,7 +776,7 @@ void test_diff_rename__file_partial_exchange(void) memset(&exp, 0, sizeof(exp)); cl_git_pass(git_diff_foreach( - diff, diff_file_cb, diff_hunk_cb, diff_line_cb, &exp)); + diff, diff_file_cb, diff_binary_cb, diff_hunk_cb, diff_line_cb, &exp)); cl_assert_equal_i(2, exp.files); cl_assert_equal_i(2, exp.file_status[GIT_DELTA_MODIFIED]); @@ -785,7 +785,7 @@ void test_diff_rename__file_partial_exchange(void) memset(&exp, 0, sizeof(exp)); cl_git_pass(git_diff_foreach( - diff, diff_file_cb, diff_hunk_cb, diff_line_cb, &exp)); + diff, diff_file_cb, diff_binary_cb, diff_hunk_cb, diff_line_cb, &exp)); cl_assert_equal_i(3, exp.files); cl_assert_equal_i(1, exp.file_status[GIT_DELTA_RENAMED]); cl_assert_equal_i(1, exp.file_status[GIT_DELTA_ADDED]); @@ -833,7 +833,7 @@ void test_diff_rename__rename_and_copy_from_same_source(void) memset(&exp, 0, sizeof(exp)); cl_git_pass(git_diff_foreach( - diff, diff_file_cb, diff_hunk_cb, diff_line_cb, &exp)); + diff, diff_file_cb, diff_binary_cb, diff_hunk_cb, diff_line_cb, &exp)); cl_assert_equal_i(6, exp.files); cl_assert_equal_i(2, exp.file_status[GIT_DELTA_ADDED]); cl_assert_equal_i(4, exp.file_status[GIT_DELTA_UNMODIFIED]); @@ -843,7 +843,7 @@ void test_diff_rename__rename_and_copy_from_same_source(void) memset(&exp, 0, sizeof(exp)); cl_git_pass(git_diff_foreach( - diff, diff_file_cb, diff_hunk_cb, diff_line_cb, &exp)); + diff, diff_file_cb, diff_binary_cb, diff_hunk_cb, diff_line_cb, &exp)); cl_assert_equal_i(6, exp.files); cl_assert_equal_i(2, exp.file_status[GIT_DELTA_COPIED]); cl_assert_equal_i(4, exp.file_status[GIT_DELTA_UNMODIFIED]); @@ -885,7 +885,7 @@ void test_diff_rename__from_deleted_to_split(void) memset(&exp, 0, sizeof(exp)); cl_git_pass(git_diff_foreach( - diff, diff_file_cb, diff_hunk_cb, diff_line_cb, &exp)); + diff, diff_file_cb, diff_binary_cb, diff_hunk_cb, diff_line_cb, &exp)); cl_assert_equal_i(4, exp.files); cl_assert_equal_i(1, exp.file_status[GIT_DELTA_DELETED]); cl_assert_equal_i(1, exp.file_status[GIT_DELTA_MODIFIED]); @@ -896,7 +896,7 @@ void test_diff_rename__from_deleted_to_split(void) memset(&exp, 0, sizeof(exp)); cl_git_pass(git_diff_foreach( - diff, diff_file_cb, diff_hunk_cb, diff_line_cb, &exp)); + diff, diff_file_cb, diff_binary_cb, diff_hunk_cb, diff_line_cb, &exp)); cl_assert_equal_i(4, exp.files); cl_assert_equal_i(1, exp.file_status[GIT_DELTA_DELETED]); cl_assert_equal_i(1, exp.file_status[GIT_DELTA_RENAMED]); @@ -998,8 +998,8 @@ void test_diff_rename__rejected_match_can_match_others(void) cl_git_pass(git_diff_find_similar(diff, &findopts)); - cl_git_pass( - git_diff_foreach(diff, test_names_expected, NULL, NULL, &expect)); + cl_git_pass(git_diff_foreach( + diff, test_names_expected, NULL, NULL, NULL, &expect)); git_diff_free(diff); git_tree_free(tree); @@ -1072,8 +1072,8 @@ void test_diff_rename__rejected_match_can_match_others_two(void) cl_git_pass(git_diff_find_similar(diff, &findopts)); - cl_git_pass( - git_diff_foreach(diff, test_names_expected, NULL, NULL, &expect)); + cl_git_pass(git_diff_foreach( + diff, test_names_expected, NULL, NULL, NULL, &expect)); cl_assert(expect.idx > 0); git_diff_free(diff); @@ -1128,8 +1128,8 @@ void test_diff_rename__rejected_match_can_match_others_three(void) cl_git_pass(git_diff_find_similar(diff, &findopts)); - cl_git_pass( - git_diff_foreach(diff, test_names_expected, NULL, NULL, &expect)); + cl_git_pass(git_diff_foreach( + diff, test_names_expected, NULL, NULL, NULL, &expect)); cl_assert(expect.idx == expect.len); @@ -1177,8 +1177,8 @@ void test_diff_rename__can_rename_from_rewrite(void) cl_git_pass(git_diff_find_similar(diff, &findopts)); - cl_git_pass( - git_diff_foreach(diff, test_names_expected, NULL, NULL, &expect)); + cl_git_pass(git_diff_foreach( + diff, test_names_expected, NULL, NULL, NULL, &expect)); cl_assert(expect.idx == expect.len); @@ -1210,7 +1210,7 @@ void test_diff_rename__case_changes_are_split(void) memset(&exp, 0, sizeof(exp)); cl_git_pass(git_diff_foreach( - diff, diff_file_cb, diff_hunk_cb, diff_line_cb, &exp)); + diff, diff_file_cb, diff_binary_cb, diff_hunk_cb, diff_line_cb, &exp)); cl_assert_equal_i(2, exp.files); cl_assert_equal_i(1, exp.file_status[GIT_DELTA_DELETED]); cl_assert_equal_i(1, exp.file_status[GIT_DELTA_ADDED]); @@ -1220,7 +1220,7 @@ void test_diff_rename__case_changes_are_split(void) memset(&exp, 0, sizeof(exp)); cl_git_pass(git_diff_foreach( - diff, diff_file_cb, diff_hunk_cb, diff_line_cb, &exp)); + diff, diff_file_cb, diff_binary_cb, diff_hunk_cb, diff_line_cb, &exp)); cl_assert_equal_i(1, exp.files); cl_assert_equal_i(1, exp.file_status[GIT_DELTA_RENAMED]); @@ -1252,7 +1252,7 @@ void test_diff_rename__unmodified_can_be_renamed(void) memset(&exp, 0, sizeof(exp)); cl_git_pass(git_diff_foreach( - diff, diff_file_cb, diff_hunk_cb, diff_line_cb, &exp)); + diff, diff_file_cb, diff_binary_cb, diff_hunk_cb, diff_line_cb, &exp)); cl_assert_equal_i(2, exp.files); cl_assert_equal_i(1, exp.file_status[GIT_DELTA_DELETED]); cl_assert_equal_i(1, exp.file_status[GIT_DELTA_ADDED]); @@ -1262,13 +1262,13 @@ void test_diff_rename__unmodified_can_be_renamed(void) memset(&exp, 0, sizeof(exp)); cl_git_pass(git_diff_foreach( - diff, diff_file_cb, diff_hunk_cb, diff_line_cb, &exp)); + diff, diff_file_cb, diff_binary_cb, diff_hunk_cb, diff_line_cb, &exp)); cl_assert_equal_i(1, exp.files); cl_assert_equal_i(1, exp.file_status[GIT_DELTA_RENAMED]); memset(&exp, 0, sizeof(exp)); cl_git_pass(git_diff_foreach( - diff, diff_file_cb, diff_hunk_cb, diff_line_cb, &exp)); + diff, diff_file_cb, diff_binary_cb, diff_hunk_cb, diff_line_cb, &exp)); cl_assert_equal_i(1, exp.files); cl_assert_equal_i(1, exp.file_status[GIT_DELTA_RENAMED]); @@ -1317,7 +1317,7 @@ void test_diff_rename__rewrite_on_single_file(void) memset(&exp, 0, sizeof(exp)); cl_git_pass(git_diff_foreach( - diff, diff_file_cb, diff_hunk_cb, diff_line_cb, &exp)); + diff, diff_file_cb, diff_binary_cb, diff_hunk_cb, diff_line_cb, &exp)); cl_assert_equal_i(2, exp.files); cl_assert_equal_i(1, exp.file_status[GIT_DELTA_DELETED]); cl_assert_equal_i(1, exp.file_status[GIT_DELTA_UNTRACKED]); @@ -1352,7 +1352,7 @@ void test_diff_rename__can_find_copy_to_split(void) memset(&exp, 0, sizeof(exp)); cl_git_pass(git_diff_foreach( - diff, diff_file_cb, diff_hunk_cb, diff_line_cb, &exp)); + diff, diff_file_cb, diff_binary_cb, diff_hunk_cb, diff_line_cb, &exp)); cl_assert_equal_i(4, exp.files); cl_assert_equal_i(1, exp.file_status[GIT_DELTA_MODIFIED]); cl_assert_equal_i(3, exp.file_status[GIT_DELTA_UNMODIFIED]); @@ -1362,7 +1362,7 @@ void test_diff_rename__can_find_copy_to_split(void) memset(&exp, 0, sizeof(exp)); cl_git_pass(git_diff_foreach( - diff, diff_file_cb, diff_hunk_cb, diff_line_cb, &exp)); + diff, diff_file_cb, diff_binary_cb, diff_hunk_cb, diff_line_cb, &exp)); cl_assert_equal_i(5, exp.files); cl_assert_equal_i(1, exp.file_status[GIT_DELTA_DELETED]); cl_assert_equal_i(1, exp.file_status[GIT_DELTA_COPIED]); @@ -1401,7 +1401,7 @@ void test_diff_rename__can_delete_unmodified_deltas(void) memset(&exp, 0, sizeof(exp)); cl_git_pass(git_diff_foreach( - diff, diff_file_cb, diff_hunk_cb, diff_line_cb, &exp)); + diff, diff_file_cb, diff_binary_cb, diff_hunk_cb, diff_line_cb, &exp)); cl_assert_equal_i(4, exp.files); cl_assert_equal_i(1, exp.file_status[GIT_DELTA_MODIFIED]); cl_assert_equal_i(3, exp.file_status[GIT_DELTA_UNMODIFIED]); @@ -1411,7 +1411,7 @@ void test_diff_rename__can_delete_unmodified_deltas(void) memset(&exp, 0, sizeof(exp)); cl_git_pass(git_diff_foreach( - diff, diff_file_cb, diff_hunk_cb, diff_line_cb, &exp)); + diff, diff_file_cb, diff_binary_cb, diff_hunk_cb, diff_line_cb, &exp)); cl_assert_equal_i(2, exp.files); cl_assert_equal_i(1, exp.file_status[GIT_DELTA_DELETED]); cl_assert_equal_i(1, exp.file_status[GIT_DELTA_COPIED]); @@ -1451,7 +1451,7 @@ void test_diff_rename__matches_config_behavior(void) memset(&exp, 0, sizeof(exp)); cl_git_pass(git_diff_find_similar(diff, &opts)); cl_git_pass(git_diff_foreach(diff, - diff_file_cb, diff_hunk_cb, diff_line_cb, &exp)); + diff_file_cb, diff_binary_cb, diff_hunk_cb, diff_line_cb, &exp)); cl_assert_equal_i(4, exp.files); cl_assert_equal_i(1, exp.file_status[GIT_DELTA_UNMODIFIED]); cl_assert_equal_i(2, exp.file_status[GIT_DELTA_ADDED]); @@ -1465,7 +1465,7 @@ void test_diff_rename__matches_config_behavior(void) memset(&exp, 0, sizeof(exp)); cl_git_pass(git_diff_find_similar(diff, &opts)); cl_git_pass(git_diff_foreach(diff, - diff_file_cb, diff_hunk_cb, diff_line_cb, &exp)); + diff_file_cb, diff_binary_cb, diff_hunk_cb, diff_line_cb, &exp)); cl_assert_equal_i(3, exp.files); cl_assert_equal_i(1, exp.file_status[GIT_DELTA_UNMODIFIED]); cl_assert_equal_i(1, exp.file_status[GIT_DELTA_ADDED]); @@ -1479,7 +1479,7 @@ void test_diff_rename__matches_config_behavior(void) memset(&exp, 0, sizeof(exp)); cl_git_pass(git_diff_find_similar(diff, &opts)); cl_git_pass(git_diff_foreach(diff, - diff_file_cb, diff_hunk_cb, diff_line_cb, &exp)); + diff_file_cb, diff_binary_cb, diff_hunk_cb, diff_line_cb, &exp)); cl_assert_equal_i(4, exp.files); cl_assert_equal_i(1, exp.file_status[GIT_DELTA_UNMODIFIED]); cl_assert_equal_i(2, exp.file_status[GIT_DELTA_MODIFIED]); @@ -1492,7 +1492,7 @@ void test_diff_rename__matches_config_behavior(void) memset(&exp, 0, sizeof(exp)); cl_git_pass(git_diff_find_similar(diff, NULL)); cl_git_pass(git_diff_foreach(diff, - diff_file_cb, diff_hunk_cb, diff_line_cb, &exp)); + diff_file_cb, diff_binary_cb, diff_hunk_cb, diff_line_cb, &exp)); cl_assert_equal_i(4, exp.files); cl_assert_equal_i(1, exp.file_status[GIT_DELTA_UNMODIFIED]); cl_assert_equal_i(2, exp.file_status[GIT_DELTA_MODIFIED]); @@ -1535,7 +1535,7 @@ void test_diff_rename__can_override_thresholds_when_obeying_config(void) memset(&exp, 0, sizeof(exp)); cl_git_pass(git_diff_find_similar(diff, &opts)); cl_git_pass(git_diff_foreach(diff, - diff_file_cb, diff_hunk_cb, diff_line_cb, &exp)); + diff_file_cb, diff_binary_cb, diff_hunk_cb, diff_line_cb, &exp)); cl_assert_equal_i(4, exp.files); cl_assert_equal_i(1, exp.file_status[GIT_DELTA_UNMODIFIED]); cl_assert_equal_i(2, exp.file_status[GIT_DELTA_MODIFIED]); @@ -1549,7 +1549,7 @@ void test_diff_rename__can_override_thresholds_when_obeying_config(void) memset(&exp, 0, sizeof(exp)); cl_git_pass(git_diff_find_similar(diff, &opts)); cl_git_pass(git_diff_foreach(diff, - diff_file_cb, diff_hunk_cb, diff_line_cb, &exp)); + diff_file_cb, diff_binary_cb, diff_hunk_cb, diff_line_cb, &exp)); cl_assert_equal_i(4, exp.files); cl_assert_equal_i(1, exp.file_status[GIT_DELTA_UNMODIFIED]); cl_assert_equal_i(2, exp.file_status[GIT_DELTA_MODIFIED]); @@ -1590,7 +1590,7 @@ void test_diff_rename__by_config_doesnt_mess_with_whitespace_settings(void) memset(&exp, 0, sizeof(exp)); cl_git_pass(git_diff_find_similar(diff, &opts)); cl_git_pass(git_diff_foreach(diff, - diff_file_cb, diff_hunk_cb, diff_line_cb, &exp)); + diff_file_cb, diff_binary_cb, diff_hunk_cb, diff_line_cb, &exp)); cl_assert_equal_i(5, exp.files); cl_assert_equal_i(2, exp.file_status[GIT_DELTA_MODIFIED]); cl_assert_equal_i(1, exp.file_status[GIT_DELTA_RENAMED]); @@ -1631,7 +1631,7 @@ static void expect_files_renamed(const char *one, const char *two, uint32_t whit memset(&exp, 0, sizeof(exp)); cl_git_pass(git_diff_foreach( - diff, diff_file_cb, diff_hunk_cb, diff_line_cb, &exp)); + diff, diff_file_cb, diff_binary_cb, diff_hunk_cb, diff_line_cb, &exp)); cl_assert_equal_i(1, exp.files); cl_assert_equal_i(1, exp.file_status[GIT_DELTA_RENAMED]); @@ -1686,7 +1686,7 @@ static void expect_files_not_renamed(const char *one, const char *two, uint32_t memset(&exp, 0, sizeof(exp)); cl_git_pass(git_diff_foreach( - diff, diff_file_cb, diff_hunk_cb, diff_line_cb, &exp)); + diff, diff_file_cb, diff_binary_cb, diff_hunk_cb, diff_line_cb, &exp)); cl_assert_equal_i(2, exp.files); cl_assert_equal_i(1, exp.file_status[GIT_DELTA_DELETED]); cl_assert_equal_i(1, exp.file_status[GIT_DELTA_UNTRACKED]); diff --git a/tests/diff/submodules.c b/tests/diff/submodules.c index 02870ac8649..e2169583bf0 100644 --- a/tests/diff/submodules.c +++ b/tests/diff/submodules.c @@ -465,7 +465,7 @@ void test_diff_submodules__skips_empty_includes_used(void) cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, &opts)); memset(&exp, 0, sizeof(exp)); cl_git_pass(git_diff_foreach( - diff, diff_file_cb, diff_hunk_cb, diff_line_cb, &exp)); + diff, diff_file_cb, diff_binary_cb, diff_hunk_cb, diff_line_cb, &exp)); cl_assert_equal_i(0, exp.files); git_diff_free(diff); @@ -478,7 +478,7 @@ void test_diff_submodules__skips_empty_includes_used(void) cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, &opts)); memset(&exp, 0, sizeof(exp)); cl_git_pass(git_diff_foreach( - diff, diff_file_cb, diff_hunk_cb, diff_line_cb, &exp)); + diff, diff_file_cb, diff_binary_cb, diff_hunk_cb, diff_line_cb, &exp)); cl_assert_equal_i(1, exp.files); cl_assert_equal_i(1, exp.file_status[GIT_DELTA_IGNORED]); git_diff_free(diff); @@ -488,7 +488,7 @@ void test_diff_submodules__skips_empty_includes_used(void) cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, &opts)); memset(&exp, 0, sizeof(exp)); cl_git_pass(git_diff_foreach( - diff, diff_file_cb, diff_hunk_cb, diff_line_cb, &exp)); + diff, diff_file_cb, diff_binary_cb, diff_hunk_cb, diff_line_cb, &exp)); cl_assert_equal_i(1, exp.files); cl_assert_equal_i(1, exp.file_status[GIT_DELTA_UNTRACKED]); git_diff_free(diff); diff --git a/tests/diff/tree.c b/tests/diff/tree.c index 6ab49fdb0b3..6dd17203d10 100644 --- a/tests/diff/tree.c +++ b/tests/diff/tree.c @@ -49,7 +49,7 @@ void test_diff_tree__0(void) cl_git_pass(git_diff_tree_to_tree(&diff, g_repo, a, b, &opts)); cl_git_pass(git_diff_foreach( - diff, diff_file_cb, diff_hunk_cb, diff_line_cb, &expect)); + diff, diff_file_cb, diff_binary_cb, diff_hunk_cb, diff_line_cb, &expect)); cl_assert_equal_i(5, expect.files); cl_assert_equal_i(2, expect.file_status[GIT_DELTA_ADDED]); @@ -71,7 +71,7 @@ void test_diff_tree__0(void) cl_git_pass(git_diff_tree_to_tree(&diff, g_repo, c, b, &opts)); cl_git_pass(git_diff_foreach( - diff, diff_file_cb, diff_hunk_cb, diff_line_cb, &expect)); + diff, diff_file_cb, diff_binary_cb, diff_hunk_cb, diff_line_cb, &expect)); cl_assert_equal_i(2, expect.files); cl_assert_equal_i(0, expect.file_status[GIT_DELTA_ADDED]); @@ -158,7 +158,7 @@ void test_diff_tree__options(void) cl_git_pass(git_diff_tree_to_tree(&diff, g_repo, c, d, &opts)); cl_git_pass(git_diff_foreach( - diff, diff_file_cb, diff_hunk_cb, diff_line_cb, &actual)); + diff, diff_file_cb, diff_binary_cb, diff_hunk_cb, diff_line_cb, &actual)); expected = &test_expects[i]; cl_assert_equal_i(actual.files, expected->files); @@ -194,7 +194,7 @@ void test_diff_tree__bare(void) cl_git_pass(git_diff_tree_to_tree(&diff, g_repo, a, b, &opts)); cl_git_pass(git_diff_foreach( - diff, diff_file_cb, diff_hunk_cb, diff_line_cb, &expect)); + diff, diff_file_cb, diff_binary_cb, diff_hunk_cb, diff_line_cb, &expect)); cl_assert_equal_i(3, expect.files); cl_assert_equal_i(2, expect.file_status[GIT_DELTA_ADDED]); @@ -235,7 +235,7 @@ void test_diff_tree__merge(void) git_diff_free(diff2); cl_git_pass(git_diff_foreach( - diff1, diff_file_cb, diff_hunk_cb, diff_line_cb, &expect)); + diff1, diff_file_cb, diff_binary_cb, diff_hunk_cb, diff_line_cb, &expect)); cl_assert_equal_i(6, expect.files); cl_assert_equal_i(2, expect.file_status[GIT_DELTA_ADDED]); @@ -332,7 +332,7 @@ void process_tree_to_tree_diffing( cl_git_pass(git_diff_tree_to_tree(&diff, g_repo, a, b, &opts)); cl_git_pass(git_diff_foreach( - diff, diff_file_cb, NULL, NULL, &expect)); + diff, diff_file_cb, NULL, NULL, NULL, &expect)); } void test_diff_tree__symlink_blob_mode_changed_to_regular_file(void) @@ -441,8 +441,8 @@ void test_diff_tree__issue_1397(void) cl_git_pass(git_diff_tree_to_tree(&diff, g_repo, a, b, &opts)); - cl_git_pass(git_diff_foreach( - diff, diff_file_cb, diff_hunk_cb, diff_line_cb, &expect)); + cl_git_pass(git_diff_foreach(diff, + diff_file_cb, diff_binary_cb, diff_hunk_cb, diff_line_cb, &expect)); cl_assert_equal_i(1, expect.files); cl_assert_equal_i(0, expect.file_status[GIT_DELTA_DELETED]); @@ -472,8 +472,8 @@ void test_diff_tree__diff_configs(void) cl_git_pass(git_diff_tree_to_tree(&diff, g_repo, a, b, NULL)); - cl_git_pass(git_diff_foreach( - diff, diff_file_cb, diff_hunk_cb, diff_line_cb, &expect)); + cl_git_pass(git_diff_foreach(diff, + diff_file_cb, diff_binary_cb, diff_hunk_cb, diff_line_cb, &expect)); cl_assert_equal_i(2, expect.files); cl_assert_equal_i(2, expect.file_status[GIT_DELTA_MODIFIED]); @@ -492,8 +492,8 @@ void test_diff_tree__diff_configs(void) cl_git_pass(git_diff_tree_to_tree(&diff, g_repo, a, b, NULL)); - cl_git_pass(git_diff_foreach( - diff, diff_file_cb, diff_hunk_cb, diff_line_cb, &expect)); + cl_git_pass(git_diff_foreach(diff, + diff_file_cb, diff_binary_cb, diff_hunk_cb, diff_line_cb, &expect)); cl_assert_equal_i(2, expect.files); cl_assert_equal_i(2, expect.file_status[GIT_DELTA_MODIFIED]); @@ -513,8 +513,8 @@ void test_diff_tree__diff_configs(void) cl_git_pass(git_diff_tree_to_tree(&diff, g_repo, a, b, NULL)); - cl_git_pass(git_diff_foreach( - diff, diff_file_cb, diff_hunk_cb, diff_line_cb, &expect)); + cl_git_pass(git_diff_foreach(diff, + diff_file_cb, diff_binary_cb, diff_hunk_cb, diff_line_cb, &expect)); cl_assert_equal_i(2, expect.files); cl_assert_equal_i(2, expect.file_status[GIT_DELTA_MODIFIED]); diff --git a/tests/diff/workdir.c b/tests/diff/workdir.c index 460f1b5929b..6b72f3286b4 100644 --- a/tests/diff/workdir.c +++ b/tests/diff/workdir.c @@ -2,6 +2,7 @@ #include "diff_helpers.h" #include "repository.h" #include "git2/sys/diff.h" +#include "../checkout/checkout_helpers.h" static git_repository *g_repo = NULL; @@ -30,10 +31,10 @@ void test_diff_workdir__to_index(void) if (use_iterator) cl_git_pass(diff_foreach_via_iterator( - diff, diff_file_cb, diff_hunk_cb, diff_line_cb, &exp)); + diff, diff_file_cb, diff_binary_cb, diff_hunk_cb, diff_line_cb, &exp)); else cl_git_pass(git_diff_foreach( - diff, diff_file_cb, diff_hunk_cb, diff_line_cb, &exp)); + diff, diff_file_cb, diff_binary_cb, diff_hunk_cb, diff_line_cb, &exp)); /* to generate these values: * - cd to tests/resources/status, @@ -73,7 +74,7 @@ void test_diff_workdir__to_index_with_conflicts(void) git_diff_options opts = GIT_DIFF_OPTIONS_INIT; git_diff *diff = NULL; git_index *index; - git_index_entry our_entry = {0}, their_entry = {0}; + git_index_entry our_entry = {{0}}, their_entry = {{0}}; diff_expects exp = {0}; g_repo = cl_git_sandbox_init("status"); @@ -94,7 +95,7 @@ void test_diff_workdir__to_index_with_conflicts(void) cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, index, &opts)); cl_git_pass(diff_foreach_via_iterator( - diff, diff_file_cb, diff_hunk_cb, diff_line_cb, &exp)); + diff, diff_file_cb, diff_binary_cb, diff_hunk_cb, diff_line_cb, &exp)); cl_assert_equal_i(9, exp.files); cl_assert_equal_i(0, exp.file_status[GIT_DELTA_ADDED]); @@ -129,7 +130,7 @@ void test_diff_workdir__to_index_with_assume_unchanged(void) cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, &opts)); memset(&exp, 0, sizeof(exp)); cl_git_pass(git_diff_foreach( - diff, diff_file_cb, diff_hunk_cb, diff_line_cb, &exp)); + diff, diff_file_cb, diff_binary_cb, diff_hunk_cb, diff_line_cb, &exp)); cl_assert_equal_i(8, exp.files); cl_assert_equal_i(0, exp.file_status[GIT_DELTA_ADDED]); cl_assert_equal_i(4, exp.file_status[GIT_DELTA_DELETED]); @@ -158,7 +159,7 @@ void test_diff_workdir__to_index_with_assume_unchanged(void) cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, &opts)); memset(&exp, 0, sizeof(exp)); cl_git_pass(git_diff_foreach( - diff, diff_file_cb, diff_hunk_cb, diff_line_cb, &exp)); + diff, diff_file_cb, diff_binary_cb, diff_hunk_cb, diff_line_cb, &exp)); cl_assert_equal_i(6, exp.files); cl_assert_equal_i(0, exp.file_status[GIT_DELTA_ADDED]); cl_assert_equal_i(3, exp.file_status[GIT_DELTA_DELETED]); @@ -205,10 +206,10 @@ void test_diff_workdir__to_tree(void) if (use_iterator) cl_git_pass(diff_foreach_via_iterator( - diff, diff_file_cb, diff_hunk_cb, diff_line_cb, &exp)); + diff, diff_file_cb, diff_binary_cb, diff_hunk_cb, diff_line_cb, &exp)); else cl_git_pass(git_diff_foreach( - diff, diff_file_cb, diff_hunk_cb, diff_line_cb, &exp)); + diff, diff_file_cb, diff_binary_cb, diff_hunk_cb, diff_line_cb, &exp)); cl_assert_equal_i(14, exp.files); cl_assert_equal_i(0, exp.file_status[GIT_DELTA_ADDED]); @@ -241,10 +242,10 @@ void test_diff_workdir__to_tree(void) if (use_iterator) cl_git_pass(diff_foreach_via_iterator( - diff, diff_file_cb, diff_hunk_cb, diff_line_cb, &exp)); + diff, diff_file_cb, diff_binary_cb, diff_hunk_cb, diff_line_cb, &exp)); else cl_git_pass(git_diff_foreach( - diff, diff_file_cb, diff_hunk_cb, diff_line_cb, &exp)); + diff, diff_file_cb, diff_binary_cb, diff_hunk_cb, diff_line_cb, &exp)); cl_assert_equal_i(15, exp.files); cl_assert_equal_i(2, exp.file_status[GIT_DELTA_ADDED]); @@ -278,10 +279,10 @@ void test_diff_workdir__to_tree(void) if (use_iterator) cl_git_pass(diff_foreach_via_iterator( - diff, diff_file_cb, diff_hunk_cb, diff_line_cb, &exp)); + diff, diff_file_cb, diff_binary_cb, diff_hunk_cb, diff_line_cb, &exp)); else cl_git_pass(git_diff_foreach( - diff, diff_file_cb, diff_hunk_cb, diff_line_cb, &exp)); + diff, diff_file_cb, diff_binary_cb, diff_hunk_cb, diff_line_cb, &exp)); cl_assert_equal_i(16, exp.files); cl_assert_equal_i(5, exp.file_status[GIT_DELTA_ADDED]); @@ -312,7 +313,7 @@ void test_diff_workdir__to_tree(void) memset(&exp, 0, sizeof(exp)); cl_git_pass(git_diff_foreach( - diff, diff_file_cb, diff_hunk_cb, diff_line_cb, &exp)); + diff, diff_file_cb, diff_binary_cb, diff_hunk_cb, diff_line_cb, &exp)); cl_assert_equal_i(16, exp.files); cl_assert_equal_i(5, exp.file_status[GIT_DELTA_DELETED]); @@ -359,9 +360,9 @@ void test_diff_workdir__to_index_with_pathspec(void) if (use_iterator) cl_git_pass(diff_foreach_via_iterator( - diff, diff_file_cb, NULL, NULL, &exp)); + diff, diff_file_cb, NULL, NULL, NULL, &exp)); else - cl_git_pass(git_diff_foreach(diff, diff_file_cb, NULL, NULL, &exp)); + cl_git_pass(git_diff_foreach(diff, diff_file_cb, NULL, NULL, NULL, &exp)); cl_assert_equal_i(13, exp.files); cl_assert_equal_i(0, exp.file_status[GIT_DELTA_ADDED]); @@ -382,9 +383,9 @@ void test_diff_workdir__to_index_with_pathspec(void) if (use_iterator) cl_git_pass(diff_foreach_via_iterator( - diff, diff_file_cb, NULL, NULL, &exp)); + diff, diff_file_cb, NULL, NULL, NULL, &exp)); else - cl_git_pass(git_diff_foreach(diff, diff_file_cb, NULL, NULL, &exp)); + cl_git_pass(git_diff_foreach(diff, diff_file_cb, NULL, NULL, NULL, &exp)); cl_assert_equal_i(1, exp.files); cl_assert_equal_i(0, exp.file_status[GIT_DELTA_ADDED]); @@ -405,9 +406,9 @@ void test_diff_workdir__to_index_with_pathspec(void) if (use_iterator) cl_git_pass(diff_foreach_via_iterator( - diff, diff_file_cb, NULL, NULL, &exp)); + diff, diff_file_cb, NULL, NULL, NULL, &exp)); else - cl_git_pass(git_diff_foreach(diff, diff_file_cb, NULL, NULL, &exp)); + cl_git_pass(git_diff_foreach(diff, diff_file_cb, NULL, NULL, NULL, &exp)); cl_assert_equal_i(3, exp.files); cl_assert_equal_i(0, exp.file_status[GIT_DELTA_ADDED]); @@ -428,9 +429,9 @@ void test_diff_workdir__to_index_with_pathspec(void) if (use_iterator) cl_git_pass(diff_foreach_via_iterator( - diff, diff_file_cb, NULL, NULL, &exp)); + diff, diff_file_cb, NULL, NULL, NULL, &exp)); else - cl_git_pass(git_diff_foreach(diff, diff_file_cb, NULL, NULL, &exp)); + cl_git_pass(git_diff_foreach(diff, diff_file_cb, NULL, NULL, NULL, &exp)); cl_assert_equal_i(2, exp.files); cl_assert_equal_i(0, exp.file_status[GIT_DELTA_ADDED]); @@ -465,10 +466,10 @@ void test_diff_workdir__filemode_changes(void) if (use_iterator) cl_git_pass(diff_foreach_via_iterator( - diff, diff_file_cb, diff_hunk_cb, diff_line_cb, &exp)); + diff, diff_file_cb, diff_binary_cb, diff_hunk_cb, diff_line_cb, &exp)); else cl_git_pass(git_diff_foreach( - diff, diff_file_cb, diff_hunk_cb, diff_line_cb, &exp)); + diff, diff_file_cb, diff_binary_cb, diff_hunk_cb, diff_line_cb, &exp)); cl_assert_equal_i(0, exp.files); cl_assert_equal_i(0, exp.file_status[GIT_DELTA_MODIFIED]); @@ -488,10 +489,10 @@ void test_diff_workdir__filemode_changes(void) if (use_iterator) cl_git_pass(diff_foreach_via_iterator( - diff, diff_file_cb, diff_hunk_cb, diff_line_cb, &exp)); + diff, diff_file_cb, diff_binary_cb, diff_hunk_cb, diff_line_cb, &exp)); else cl_git_pass(git_diff_foreach( - diff, diff_file_cb, diff_hunk_cb, diff_line_cb, &exp)); + diff, diff_file_cb, diff_binary_cb, diff_hunk_cb, diff_line_cb, &exp)); cl_assert_equal_i(1, exp.files); cl_assert_equal_i(1, exp.file_status[GIT_DELTA_MODIFIED]); @@ -521,7 +522,7 @@ void test_diff_workdir__filemode_changes_with_filemode_false(void) memset(&exp, 0, sizeof(exp)); cl_git_pass(git_diff_foreach( - diff, diff_file_cb, diff_hunk_cb, diff_line_cb, &exp)); + diff, diff_file_cb, diff_binary_cb, diff_hunk_cb, diff_line_cb, &exp)); cl_assert_equal_i(0, exp.files); cl_assert_equal_i(0, exp.file_status[GIT_DELTA_MODIFIED]); @@ -536,8 +537,8 @@ void test_diff_workdir__filemode_changes_with_filemode_false(void) cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, NULL)); memset(&exp, 0, sizeof(exp)); - cl_git_pass(git_diff_foreach( - diff, diff_file_cb, diff_hunk_cb, diff_line_cb, &exp)); + cl_git_pass(git_diff_foreach(diff, + diff_file_cb, diff_binary_cb, diff_hunk_cb, diff_line_cb, &exp)); cl_assert_equal_i(0, exp.files); cl_assert_equal_i(0, exp.file_status[GIT_DELTA_MODIFIED]); @@ -580,10 +581,10 @@ void test_diff_workdir__head_index_and_workdir_all_differ(void) if (use_iterator) cl_git_pass(diff_foreach_via_iterator( - diff_i2t, diff_file_cb, diff_hunk_cb, diff_line_cb, &exp)); + diff_i2t, diff_file_cb, diff_binary_cb, diff_hunk_cb, diff_line_cb, &exp)); else cl_git_pass(git_diff_foreach( - diff_i2t, diff_file_cb, diff_hunk_cb, diff_line_cb, &exp)); + diff_i2t, diff_file_cb, diff_binary_cb, diff_hunk_cb, diff_line_cb, &exp)); cl_assert_equal_i(1, exp.files); cl_assert_equal_i(0, exp.file_status[GIT_DELTA_ADDED]); @@ -601,10 +602,10 @@ void test_diff_workdir__head_index_and_workdir_all_differ(void) if (use_iterator) cl_git_pass(diff_foreach_via_iterator( - diff_w2i, diff_file_cb, diff_hunk_cb, diff_line_cb, &exp)); + diff_w2i, diff_file_cb, diff_binary_cb, diff_hunk_cb, diff_line_cb, &exp)); else cl_git_pass(git_diff_foreach( - diff_w2i, diff_file_cb, diff_hunk_cb, diff_line_cb, &exp)); + diff_w2i, diff_file_cb, diff_binary_cb, diff_hunk_cb, diff_line_cb, &exp)); cl_assert_equal_i(1, exp.files); cl_assert_equal_i(0, exp.file_status[GIT_DELTA_ADDED]); @@ -624,10 +625,10 @@ void test_diff_workdir__head_index_and_workdir_all_differ(void) if (use_iterator) cl_git_pass(diff_foreach_via_iterator( - diff_i2t, diff_file_cb, diff_hunk_cb, diff_line_cb, &exp)); + diff_i2t, diff_file_cb, diff_binary_cb, diff_hunk_cb, diff_line_cb, &exp)); else cl_git_pass(git_diff_foreach( - diff_i2t, diff_file_cb, diff_hunk_cb, diff_line_cb, &exp)); + diff_i2t, diff_file_cb, diff_binary_cb, diff_hunk_cb, diff_line_cb, &exp)); cl_assert_equal_i(1, exp.files); cl_assert_equal_i(0, exp.file_status[GIT_DELTA_ADDED]); @@ -666,10 +667,10 @@ void test_diff_workdir__eof_newline_changes(void) if (use_iterator) cl_git_pass(diff_foreach_via_iterator( - diff, diff_file_cb, diff_hunk_cb, diff_line_cb, &exp)); + diff, diff_file_cb, diff_binary_cb, diff_hunk_cb, diff_line_cb, &exp)); else cl_git_pass(git_diff_foreach( - diff, diff_file_cb, diff_hunk_cb, diff_line_cb, &exp)); + diff, diff_file_cb, diff_binary_cb, diff_hunk_cb, diff_line_cb, &exp)); cl_assert_equal_i(0, exp.files); cl_assert_equal_i(0, exp.file_status[GIT_DELTA_ADDED]); @@ -693,10 +694,10 @@ void test_diff_workdir__eof_newline_changes(void) if (use_iterator) cl_git_pass(diff_foreach_via_iterator( - diff, diff_file_cb, diff_hunk_cb, diff_line_cb, &exp)); + diff, diff_file_cb, diff_binary_cb, diff_hunk_cb, diff_line_cb, &exp)); else cl_git_pass(git_diff_foreach( - diff, diff_file_cb, diff_hunk_cb, diff_line_cb, &exp)); + diff, diff_file_cb, diff_binary_cb, diff_hunk_cb, diff_line_cb, &exp)); cl_assert_equal_i(1, exp.files); cl_assert_equal_i(0, exp.file_status[GIT_DELTA_ADDED]); @@ -720,10 +721,10 @@ void test_diff_workdir__eof_newline_changes(void) if (use_iterator) cl_git_pass(diff_foreach_via_iterator( - diff, diff_file_cb, diff_hunk_cb, diff_line_cb, &exp)); + diff, diff_file_cb, diff_binary_cb, diff_hunk_cb, diff_line_cb, &exp)); else cl_git_pass(git_diff_foreach( - diff, diff_file_cb, diff_hunk_cb, diff_line_cb, &exp)); + diff, diff_file_cb, diff_binary_cb, diff_hunk_cb, diff_line_cb, &exp)); cl_assert_equal_i(1, exp.files); cl_assert_equal_i(0, exp.file_status[GIT_DELTA_ADDED]); @@ -913,7 +914,7 @@ void test_diff_workdir__submodules(void) memset(&exp, 0, sizeof(exp)); cl_git_pass(git_diff_foreach( - diff, diff_file_cb, diff_hunk_cb, diff_line_cb, &exp)); + diff, diff_file_cb, diff_binary_cb, diff_hunk_cb, diff_line_cb, &exp)); /* so "git diff 873585" returns: * M .gitmodules @@ -991,7 +992,7 @@ void test_diff_workdir__to_null_tree(void) memset(&exp, 0, sizeof(exp)); cl_git_pass(git_diff_foreach( - diff, diff_file_cb, diff_hunk_cb, diff_line_cb, &exp)); + diff, diff_file_cb, diff_binary_cb, diff_hunk_cb, diff_line_cb, &exp)); cl_assert_equal_i(exp.files, exp.file_status[GIT_DELTA_UNTRACKED]); @@ -1080,7 +1081,7 @@ void test_diff_workdir__to_index_issue_1397(void) memset(&exp, 0, sizeof(exp)); cl_git_pass(git_diff_foreach( - diff, diff_file_cb, diff_hunk_cb, diff_line_cb, &exp)); + diff, diff_file_cb, diff_binary_cb, diff_hunk_cb, diff_line_cb, &exp)); cl_assert_equal_i(0, exp.files); cl_assert_equal_i(0, exp.hunks); @@ -1096,7 +1097,7 @@ void test_diff_workdir__to_index_issue_1397(void) memset(&exp, 0, sizeof(exp)); cl_git_pass(git_diff_foreach( - diff, diff_file_cb, diff_hunk_cb, diff_line_cb, &exp)); + diff, diff_file_cb, diff_binary_cb, diff_hunk_cb, diff_line_cb, &exp)); cl_assert_equal_i(1, exp.files); cl_assert_equal_i(1, exp.file_status[GIT_DELTA_MODIFIED]); @@ -1133,7 +1134,7 @@ void test_diff_workdir__to_tree_issue_1397(void) memset(&exp, 0, sizeof(exp)); cl_git_pass(git_diff_foreach( - diff, diff_file_cb, diff_hunk_cb, diff_line_cb, &exp)); + diff, diff_file_cb, diff_binary_cb, diff_hunk_cb, diff_line_cb, &exp)); cl_assert_equal_i(0, exp.files); cl_assert_equal_i(0, exp.hunks); @@ -1149,7 +1150,7 @@ void test_diff_workdir__to_tree_issue_1397(void) memset(&exp, 0, sizeof(exp)); cl_git_pass(git_diff_foreach( - diff, diff_file_cb, diff_hunk_cb, diff_line_cb, &exp)); + diff, diff_file_cb, diff_binary_cb, diff_hunk_cb, diff_line_cb, &exp)); cl_assert_equal_i(0, exp.files); cl_assert_equal_i(0, exp.hunks); @@ -1203,7 +1204,7 @@ void test_diff_workdir__untracked_directory_scenarios(void) cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, &opts)); - cl_git_pass(git_diff_foreach(diff, diff_file_cb, NULL, NULL, &exp)); + cl_git_pass(git_diff_foreach(diff, diff_file_cb, NULL, NULL, NULL, &exp)); cl_assert_equal_i(3, exp.files); cl_assert_equal_i(0, exp.file_status[GIT_DELTA_ADDED]); @@ -1223,7 +1224,7 @@ void test_diff_workdir__untracked_directory_scenarios(void) cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, &opts)); - cl_git_pass(git_diff_foreach(diff, diff_file_cb, NULL, NULL, &exp)); + cl_git_pass(git_diff_foreach(diff, diff_file_cb, NULL, NULL, NULL, &exp)); cl_assert_equal_i(4, exp.files); cl_assert_equal_i(0, exp.file_status[GIT_DELTA_ADDED]); @@ -1243,7 +1244,7 @@ void test_diff_workdir__untracked_directory_scenarios(void) cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, &opts)); - cl_git_pass(git_diff_foreach(diff, diff_file_cb, NULL, NULL, &exp)); + cl_git_pass(git_diff_foreach(diff, diff_file_cb, NULL, NULL, NULL, &exp)); cl_assert_equal_i(4, exp.files); cl_assert_equal_i(0, exp.file_status[GIT_DELTA_ADDED]); @@ -1267,7 +1268,7 @@ void test_diff_workdir__untracked_directory_scenarios(void) cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, &opts)); - cl_git_pass(git_diff_foreach(diff, diff_file_cb, NULL, NULL, &exp)); + cl_git_pass(git_diff_foreach(diff, diff_file_cb, NULL, NULL, NULL, &exp)); cl_assert_equal_i(4, exp.files); cl_assert_equal_i(0, exp.file_status[GIT_DELTA_ADDED]); @@ -1290,7 +1291,7 @@ void test_diff_workdir__untracked_directory_scenarios(void) cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, &opts)); - cl_git_pass(git_diff_foreach(diff, diff_file_cb, NULL, NULL, &exp)); + cl_git_pass(git_diff_foreach(diff, diff_file_cb, NULL, NULL, NULL, &exp)); cl_assert_equal_i(4, exp.files); cl_assert_equal_i(0, exp.file_status[GIT_DELTA_ADDED]); @@ -1310,7 +1311,7 @@ void test_diff_workdir__untracked_directory_scenarios(void) cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, &opts)); - cl_git_pass(git_diff_foreach(diff, diff_file_cb, NULL, NULL, &exp)); + cl_git_pass(git_diff_foreach(diff, diff_file_cb, NULL, NULL, NULL, &exp)); cl_assert_equal_i(4, exp.files); cl_assert_equal_i(0, exp.file_status[GIT_DELTA_ADDED]); @@ -1333,7 +1334,7 @@ void test_diff_workdir__untracked_directory_scenarios(void) cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, &opts)); - cl_git_pass(git_diff_foreach(diff, diff_file_cb, NULL, NULL, &exp)); + cl_git_pass(git_diff_foreach(diff, diff_file_cb, NULL, NULL, NULL, &exp)); cl_assert_equal_i(4, exp.files); cl_assert_equal_i(0, exp.file_status[GIT_DELTA_ADDED]); @@ -1354,7 +1355,7 @@ void test_diff_workdir__untracked_directory_scenarios(void) cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, &opts)); - cl_git_pass(git_diff_foreach(diff, diff_file_cb, NULL, NULL, &exp)); + cl_git_pass(git_diff_foreach(diff, diff_file_cb, NULL, NULL, NULL, &exp)); cl_assert_equal_i(4, exp.files); cl_assert_equal_i(0, exp.file_status[GIT_DELTA_ADDED]); @@ -1505,7 +1506,7 @@ void test_diff_workdir__with_stale_index(void) memset(&exp, 0, sizeof(exp)); cl_git_pass(git_diff_foreach( - diff, diff_file_cb, diff_hunk_cb, diff_line_cb, &exp)); + diff, diff_file_cb, diff_binary_cb, diff_hunk_cb, diff_line_cb, &exp)); cl_assert_equal_i(17, exp.files); cl_assert_equal_i(0, exp.file_status[GIT_DELTA_ADDED]); @@ -1527,7 +1528,7 @@ void test_diff_workdir__with_stale_index(void) memset(&exp, 0, sizeof(exp)); cl_git_pass(git_diff_foreach( - diff, diff_file_cb, diff_hunk_cb, diff_line_cb, &exp)); + diff, diff_file_cb, diff_binary_cb, diff_hunk_cb, diff_line_cb, &exp)); git_diff_free(diff); @@ -1568,7 +1569,7 @@ static void basic_diff_status(git_diff **out, const git_diff_options *opts) memset(&exp, 0, sizeof(exp)); cl_git_pass(git_diff_foreach( - *out, diff_file_cb, diff_hunk_cb, diff_line_cb, &exp)); + *out, diff_file_cb, diff_binary_cb, diff_hunk_cb, diff_line_cb, &exp)); cl_assert_equal_i(13, exp.files); cl_assert_equal_i(0, exp.file_status[GIT_DELTA_ADDED]); @@ -1583,6 +1584,7 @@ void test_diff_workdir__can_update_index(void) git_diff_options opts = GIT_DIFF_OPTIONS_INIT; git_diff *diff = NULL; git_diff_perfdata perf = GIT_DIFF_PERFDATA_INIT; + git_index *index; g_repo = cl_git_sandbox_init("status"); @@ -1607,6 +1609,10 @@ void test_diff_workdir__can_update_index(void) /* now allow diff to update stat cache */ opts.flags |= GIT_DIFF_UPDATE_INDEX; + /* advance a tick for the index so we don't re-calculate racily-clean entries */ + cl_git_pass(git_repository_index__weakptr(&index, g_repo)); + tick_index(index); + basic_diff_status(&diff, &opts); cl_git_pass(git_diff_get_perfdata(&perf, diff)); diff --git a/tests/filter/query.c b/tests/filter/query.c new file mode 100644 index 00000000000..6889d715bb3 --- /dev/null +++ b/tests/filter/query.c @@ -0,0 +1,91 @@ +#include "clar_libgit2.h" +#include "git2/sys/filter.h" +#include "crlf.h" +#include "buffer.h" + +static git_repository *g_repo = NULL; + +void test_filter_query__initialize(void) +{ + g_repo = cl_git_sandbox_init("crlf"); + + cl_git_mkfile("crlf/.gitattributes", + "*.txt text\n" + "*.bin binary\n" + "*.crlf text eol=crlf\n" + "*.lf text eol=lf\n" + "*.binident binary ident\n" + "*.ident text ident\n" + "*.identcrlf ident text eol=crlf\n" + "*.identlf ident text eol=lf\n" + "*.custom custom ident text\n"); +} + +void test_filter_query__cleanup(void) +{ + cl_git_sandbox_cleanup(); +} + +static int filter_for(const char *filename, const char *filter) +{ + git_filter_list *fl; + int filtered; + + cl_git_pass(git_filter_list_load( + &fl, g_repo, NULL, filename, GIT_FILTER_TO_WORKTREE, 0)); + filtered = git_filter_list_contains(fl, filter); + git_filter_list_free(fl); + + return filtered; +} + +void test_filter_query__filters(void) +{ + cl_assert_equal_i(1, filter_for("text.txt", "crlf")); + cl_assert_equal_i(0, filter_for("binary.bin", "crlf")); + + cl_assert_equal_i(1, filter_for("foo.lf", "crlf")); + cl_assert_equal_i(0, filter_for("foo.lf", "ident")); + + cl_assert_equal_i(1, filter_for("id.ident", "crlf")); + cl_assert_equal_i(1, filter_for("id.ident", "ident")); + + cl_assert_equal_i(0, filter_for("id.binident", "crlf")); + cl_assert_equal_i(1, filter_for("id.binident", "ident")); +} + +void test_filter_query__autocrlf_true_implies_crlf(void) +{ + cl_repo_set_bool(g_repo, "core.autocrlf", true); + cl_assert_equal_i(1, filter_for("not_in_gitattributes", "crlf")); + cl_assert_equal_i(1, filter_for("foo.txt", "crlf")); + cl_assert_equal_i(0, filter_for("foo.bin", "crlf")); + cl_assert_equal_i(1, filter_for("foo.lf", "crlf")); + + cl_repo_set_bool(g_repo, "core.autocrlf", false); + cl_assert_equal_i(0, filter_for("not_in_gitattributes", "crlf")); + cl_assert_equal_i(1, filter_for("foo.txt", "crlf")); + cl_assert_equal_i(0, filter_for("foo.bin", "crlf")); + cl_assert_equal_i(1, filter_for("foo.lf", "crlf")); +} + +void test_filter_query__unknown(void) +{ + cl_assert_equal_i(1, filter_for("foo.custom", "crlf")); + cl_assert_equal_i(1, filter_for("foo.custom", "ident")); + cl_assert_equal_i(0, filter_for("foo.custom", "custom")); +} + +void test_filter_query__custom(void) +{ + git_filter custom = { GIT_FILTER_VERSION }; + + cl_git_pass(git_filter_register( + "custom", &custom, 42)); + + cl_assert_equal_i(1, filter_for("foo.custom", "crlf")); + cl_assert_equal_i(1, filter_for("foo.custom", "ident")); + cl_assert_equal_i(1, filter_for("foo.custom", "custom")); + + git_filter_unregister("custom"); +} diff --git a/tests/index/addall.c b/tests/index/addall.c index 211e7622824..f344cc6ae01 100644 --- a/tests/index/addall.c +++ b/tests/index/addall.c @@ -288,7 +288,6 @@ void test_index_addall__repo_lifecycle(void) void test_index_addall__files_in_folders(void) { git_index *index; - git_strarray paths = { NULL, 0 }; addall_create_test_repo(true); @@ -408,7 +407,7 @@ void test_index_addall__adds_conflicts(void) cl_git_pass(git_reference_lookup(&ref, g_repo, "refs/heads/branch")); cl_git_pass(git_annotated_commit_from_ref(&annotated, g_repo, ref)); - cl_git_pass(git_merge(g_repo, &annotated, 1, NULL, NULL)); + cl_git_pass(git_merge(g_repo, (const git_annotated_commit**)&annotated, 1, NULL, NULL)); check_status(g_repo, 0, 1, 2, 0, 0, 0, 0, 1); cl_git_pass(git_index_add_all(index, NULL, 0, NULL, NULL)); @@ -433,7 +432,7 @@ void test_index_addall__removes_deleted_conflicted_files(void) cl_git_pass(git_reference_lookup(&ref, g_repo, "refs/heads/branch")); cl_git_pass(git_annotated_commit_from_ref(&annotated, g_repo, ref)); - cl_git_pass(git_merge(g_repo, &annotated, 1, NULL, NULL)); + cl_git_pass(git_merge(g_repo, (const git_annotated_commit**)&annotated, 1, NULL, NULL)); check_status(g_repo, 0, 1, 2, 0, 0, 0, 0, 1); cl_git_rmfile("merge-resolve/conflicting.txt"); diff --git a/tests/merge/workdir/dirty.c b/tests/merge/workdir/dirty.c index b66225d1f33..30c404b701e 100644 --- a/tests/merge/workdir/dirty.c +++ b/tests/merge/workdir/dirty.c @@ -2,6 +2,7 @@ #include "git2/merge.h" #include "buffer.h" #include "merge.h" +#include "index.h" #include "../merge_helpers.h" #include "posix.h" @@ -231,9 +232,20 @@ static int merge_differently_filtered_files(char *files[]) cl_git_pass(git_reference_peel(&head_object, head, GIT_OBJ_COMMIT)); cl_git_pass(git_reset(repo, head_object, GIT_RESET_HARD, NULL)); + /* Emulate checkout with a broken or misconfigured filter: modify some + * files on-disk and then update the index with the updated file size + * and time, as if some filter applied them. These files should not be + * treated as dirty since we created them. + * + * (Make sure to update the index stamp to defeat racy-git protections + * trying to sanity check the files in the index; those would rehash the + * files, showing them as dirty, the exact mechanism we're trying to avoid.) + */ + write_files(files); hack_index(files); + repo_index->stamp.mtime = time(NULL) + 1; cl_git_pass(git_index_write(repo_index)); error = merge_branch(); diff --git a/tests/odb/foreach.c b/tests/odb/foreach.c index 75448a2f7f1..12b81b4f148 100644 --- a/tests/odb/foreach.c +++ b/tests/odb/foreach.c @@ -71,15 +71,35 @@ static int foreach_stop_cb(const git_oid *oid, void *data) return (*nobj == 1000) ? -321 : 0; } +static int foreach_stop_first_cb(const git_oid *oid, void *data) +{ + int *nobj = data; + (*nobj)++; + + GIT_UNUSED(oid); + + return -123; +} + void test_odb_foreach__interrupt_foreach(void) { int nobj = 0; + git_oid id; cl_git_pass(git_repository_open(&_repo, cl_fixture("testrepo.git"))); git_repository_odb(&_odb, _repo); cl_assert_equal_i(-321, git_odb_foreach(_odb, foreach_stop_cb, &nobj)); cl_assert(nobj == 1000); + + git_odb_free(_odb); + git_repository_free(_repo); + + cl_git_pass(git_repository_init(&_repo, "onlyloose.git", true)); + git_repository_odb(&_odb, _repo); + + cl_git_pass(git_odb_write(&id, _odb, "", 0, GIT_OBJ_BLOB)); + cl_assert_equal_i(-123, git_odb_foreach(_odb, foreach_stop_first_cb, &nobj)); } void test_odb_foreach__files_in_objects_dir(void) diff --git a/tests/online/clone.c b/tests/online/clone.c index 1930a8ba3d6..e63cf55f1a8 100644 --- a/tests/online/clone.c +++ b/tests/online/clone.c @@ -428,6 +428,7 @@ void test_online_clone__ssh_with_paths(void) g_options.remote_cb = custom_remote_ssh_with_paths; g_options.fetch_opts.callbacks.transport = git_transport_ssh_with_paths; + g_options.fetch_opts.callbacks.credentials = cred_cb; g_options.fetch_opts.callbacks.payload = &arr; cl_git_fail(git_clone(&g_repo, remote_url, "./foo", &g_options)); @@ -501,6 +502,74 @@ void test_online_clone__ssh_cert(void) cl_git_fail_with(GIT_EUSER, git_clone(&g_repo, "ssh://localhost/foo", "./foo", &g_options)); } +static char *read_key_file(const char *path) +{ + FILE *f; + char *buf; + long key_length; + + if (!path || !*path) + return NULL; + + cl_assert((f = fopen(path, "r")) != NULL); + cl_assert(fseek(f, 0, SEEK_END) != -1); + cl_assert((key_length = ftell(f)) != -1); + cl_assert(fseek(f, 0, SEEK_SET) != -1); + cl_assert((buf = malloc(key_length)) != NULL); + cl_assert(fread(buf, key_length, 1, f) == 1); + fclose(f); + + return buf; +} + +static int ssh_memory_cred_cb(git_cred **cred, const char *url, const char *user_from_url, + unsigned int allowed_types, void *payload) +{ + const char *remote_user = cl_getenv("GITTEST_REMOTE_USER"); + const char *pubkey_path = cl_getenv("GITTEST_REMOTE_SSH_PUBKEY"); + const char *privkey_path = cl_getenv("GITTEST_REMOTE_SSH_KEY"); + const char *passphrase = cl_getenv("GITTEST_REMOTE_SSH_PASSPHRASE"); + + GIT_UNUSED(url); GIT_UNUSED(user_from_url); GIT_UNUSED(payload); + + if (allowed_types & GIT_CREDTYPE_USERNAME) + return git_cred_username_new(cred, remote_user); + + if (allowed_types & GIT_CREDTYPE_SSH_KEY) + { + char *pubkey = read_key_file(pubkey_path); + char *privkey = read_key_file(privkey_path); + + int ret = git_cred_ssh_key_memory_new(cred, remote_user, pubkey, privkey, passphrase); + + if (privkey) + free(privkey); + if (pubkey) + free(pubkey); + return ret; + } + + giterr_set(GITERR_NET, "unexpected cred type"); + return -1; +} + +void test_online_clone__ssh_memory_auth(void) +{ + const char *remote_url = cl_getenv("GITTEST_REMOTE_URL"); + const char *remote_user = cl_getenv("GITTEST_REMOTE_USER"); + const char *privkey = cl_getenv("GITTEST_REMOTE_SSH_KEY"); + +#ifndef GIT_SSH_MEMORY_CREDENTIALS + clar__skip(); +#endif + if (!remote_url || !remote_user || !privkey || strncmp(remote_url, "ssh://", 5) != 0) + clar__skip(); + + g_options.fetch_opts.callbacks.credentials = ssh_memory_cred_cb; + + cl_git_pass(git_clone(&g_repo, remote_url, "./foo", &g_options)); +} + void test_online_clone__url_with_no_path_returns_EINVALIDSPEC(void) { cl_git_fail_with(git_clone(&g_repo, "http://github.com", "./foo", &g_options), diff --git a/tests/online/push.c b/tests/online/push.c index 04ad7a2eda5..6cd444320d9 100644 --- a/tests/online/push.c +++ b/tests/online/push.c @@ -319,6 +319,8 @@ void test_online_push__initialize(void) git_vector delete_specs = GIT_VECTOR_INIT; const git_remote_head **heads; size_t heads_len; + git_push_options push_opts = GIT_PUSH_OPTIONS_INIT; + git_fetch_options fetch_opts = GIT_FETCH_OPTIONS_INIT; _repo = cl_git_sandbox_init("push_src"); @@ -370,7 +372,7 @@ void test_online_push__initialize(void) record_callbacks_data_clear(&_record_cbs_data); - cl_git_pass(git_remote_connect(_remote, GIT_DIRECTION_PUSH, NULL)); + cl_git_pass(git_remote_connect(_remote, GIT_DIRECTION_PUSH, &_record_cbs)); /* Clean up previously pushed branches. Fails if receive.denyDeletes is * set on the remote. Also, on Git 1.7.0 and newer, you must run @@ -386,14 +388,16 @@ void test_online_push__initialize(void) delete_specs.length, }; - cl_git_pass(git_remote_upload(_remote, &arr, NULL)); + memcpy(&push_opts.callbacks, &_record_cbs, sizeof(git_remote_callbacks)); + cl_git_pass(git_remote_upload(_remote, &arr, &push_opts)); } git_remote_disconnect(_remote); git_vector_free(&delete_specs); /* Now that we've deleted everything, fetch from the remote */ - cl_git_pass(git_remote_fetch(_remote, NULL, NULL, NULL)); + memcpy(&fetch_opts.callbacks, &_record_cbs, sizeof(git_remote_callbacks)); + cl_git_pass(git_remote_fetch(_remote, NULL, &fetch_opts, NULL)); } void test_online_push__cleanup(void) diff --git a/tests/remote/insteadof.c b/tests/remote/insteadof.c new file mode 100644 index 00000000000..05d4757cf0c --- /dev/null +++ b/tests/remote/insteadof.c @@ -0,0 +1,72 @@ +#include "clar_libgit2.h" +#include "remote.h" +#include "repository.h" + +#define REPO_PATH "testrepo2/.gitted" +#define REMOTE_ORIGIN "origin" +#define REMOTE_INSTEADOF "insteadof-test" + +static git_repository *g_repo; +static git_remote *g_remote; + +void test_remote_insteadof__initialize(void) +{ + g_repo = NULL; + g_remote = NULL; +} + +void test_remote_insteadof__cleanup(void) +{ + git_repository_free(g_repo); + git_remote_free(g_remote); +} + +void test_remote_insteadof__url_insteadof_not_applicable(void) +{ + cl_git_pass(git_repository_open(&g_repo, cl_fixture(REPO_PATH))); + cl_git_pass(git_remote_lookup(&g_remote, g_repo, REMOTE_ORIGIN)); + + cl_assert_equal_s( + git_remote_url(g_remote), + "https://github.com/libgit2/false.git"); +} + +void test_remote_insteadof__url_insteadof_applicable(void) +{ + cl_git_pass(git_repository_open(&g_repo, cl_fixture(REPO_PATH))); + cl_git_pass(git_remote_lookup(&g_remote, g_repo, REMOTE_INSTEADOF)); + + cl_assert_equal_s( + git_remote_url(g_remote), + "http://github.com/libgit2/libgit2"); +} + +void test_remote_insteadof__pushurl_insteadof_not_applicable(void) +{ + cl_git_pass(git_repository_open(&g_repo, cl_fixture(REPO_PATH))); + cl_git_pass(git_remote_lookup(&g_remote, g_repo, REMOTE_ORIGIN)); + + cl_assert_equal_p(git_remote_pushurl(g_remote), NULL); +} + +void test_remote_insteadof__pushurl_insteadof_applicable(void) +{ + cl_git_pass(git_repository_open(&g_repo, cl_fixture(REPO_PATH))); + cl_git_pass(git_remote_lookup(&g_remote, g_repo, REMOTE_INSTEADOF)); + + cl_assert_equal_s( + git_remote_pushurl(g_remote), + "git@github.com:libgit2/libgit2"); +} + +void test_remote_insteadof__anonymous_remote(void) +{ + cl_git_pass(git_repository_open(&g_repo, cl_fixture(REPO_PATH))); + cl_git_pass(git_remote_create_anonymous(&g_remote, g_repo, + "http://example.com/libgit2/libgit2")); + + cl_assert_equal_s( + git_remote_url(g_remote), + "http://github.com/libgit2/libgit2"); + cl_assert_equal_p(git_remote_pushurl(g_remote), NULL); +} diff --git a/tests/resources/testrepo2/.gitted/config b/tests/resources/testrepo2/.gitted/config index fc2433caf99..4af067f0401 100644 --- a/tests/resources/testrepo2/.gitted/config +++ b/tests/resources/testrepo2/.gitted/config @@ -8,7 +8,19 @@ [remote "origin"] url = https://github.com/libgit2/false.git fetch = +refs/heads/*:refs/remotes/origin/* +[remote "insteadof-test"] + url = http://example.com/libgit2/libgit2 + pushurl = http://github.com/libgit2/libgit2 + fetch = +refs/heads/*:refs/remotes/test/* [branch "master"] remote = origin merge = refs/heads/master rebase = true +[url "longer-non-prefix-match"] + insteadOf = ttp://example.com/li +[url "shorter-prefix"] + insteadOf = http://example.co +[url "http://github.com"] + insteadOf = http://example.com +[url "git@github.com:"] + pushInsteadOf = http://github.com/ diff --git a/tests/stash/apply.c b/tests/stash/apply.c index 42186b6fb85..c242536be4c 100644 --- a/tests/stash/apply.c +++ b/tests/stash/apply.c @@ -118,7 +118,7 @@ void test_stash_apply__conflict_index_with_reinstate_index(void) cl_git_pass(git_index_add_bypath(repo_index, "who")); cl_git_pass(git_index_write(repo_index)); - cl_git_fail_with(git_stash_apply(repo, 0, &opts), GIT_EMERGECONFLICT); + cl_git_fail_with(git_stash_apply(repo, 0, &opts), GIT_ECONFLICT); cl_assert_equal_i(git_index_has_conflicts(repo_index), 0); assert_status(repo, "what", GIT_STATUS_CURRENT); @@ -133,7 +133,7 @@ void test_stash_apply__conflict_untracked_with_default(void) cl_git_mkfile("stash/when", "nothing\n"); - cl_git_fail_with(git_stash_apply(repo, 0, &opts), GIT_EMERGECONFLICT); + cl_git_fail_with(git_stash_apply(repo, 0, &opts), GIT_ECONFLICT); cl_assert_equal_i(git_index_has_conflicts(repo_index), 0); assert_status(repo, "what", GIT_STATUS_CURRENT); @@ -150,7 +150,7 @@ void test_stash_apply__conflict_untracked_with_reinstate_index(void) cl_git_mkfile("stash/when", "nothing\n"); - cl_git_fail_with(git_stash_apply(repo, 0, &opts), GIT_EMERGECONFLICT); + cl_git_fail_with(git_stash_apply(repo, 0, &opts), GIT_ECONFLICT); cl_assert_equal_i(git_index_has_conflicts(repo_index), 0); assert_status(repo, "what", GIT_STATUS_CURRENT); @@ -163,7 +163,7 @@ void test_stash_apply__conflict_workdir_with_default(void) { cl_git_rewritefile("stash/what", "ciao\n"); - cl_git_fail_with(git_stash_apply(repo, 0, NULL), GIT_EMERGECONFLICT); + cl_git_fail_with(git_stash_apply(repo, 0, NULL), GIT_ECONFLICT); cl_assert_equal_i(git_index_has_conflicts(repo_index), 0); assert_status(repo, "what", GIT_STATUS_WT_MODIFIED); @@ -180,7 +180,7 @@ void test_stash_apply__conflict_workdir_with_reinstate_index(void) cl_git_rewritefile("stash/what", "ciao\n"); - cl_git_fail_with(git_stash_apply(repo, 0, &opts), GIT_EMERGECONFLICT); + cl_git_fail_with(git_stash_apply(repo, 0, &opts), GIT_ECONFLICT); cl_assert_equal_i(git_index_has_conflicts(repo_index), 0); assert_status(repo, "what", GIT_STATUS_WT_MODIFIED); @@ -254,6 +254,11 @@ int checkout_notify( { struct seen_paths *seen_paths = (struct seen_paths *)payload; + GIT_UNUSED(why); + GIT_UNUSED(baseline); + GIT_UNUSED(target); + GIT_UNUSED(workdir); + if (strcmp(path, "what") == 0) seen_paths->what = 1; else if (strcmp(path, "how") == 0) @@ -318,6 +323,8 @@ int aborting_progress_cb( git_stash_apply_progress_t progress, void *payload) { + GIT_UNUSED(payload); + if (progress == GIT_STASH_APPLY_PROGRESS_ANALYZE_MODIFIED) return -44; @@ -327,7 +334,6 @@ int aborting_progress_cb( void test_stash_apply__progress_cb_can_abort(void) { git_stash_apply_options opts = GIT_STASH_APPLY_OPTIONS_INIT; - git_stash_apply_progress_t progress = GIT_STASH_APPLY_PROGRESS_NONE; opts.progress_cb = aborting_progress_cb; diff --git a/tests/status/worktree.c b/tests/status/worktree.c index e272c0a108a..f8d1f7f54bb 100644 --- a/tests/status/worktree.c +++ b/tests/status/worktree.c @@ -6,6 +6,7 @@ #include "util.h" #include "path.h" #include "../diff/diff_helpers.h" +#include "../checkout/checkout_helpers.h" #include "git2/sys/diff.h" /** @@ -649,10 +650,10 @@ void test_status_worktree__conflict_has_no_oid(void) { git_repository *repo = cl_git_sandbox_init("status"); git_index *index; - git_index_entry entry = {0}; + git_index_entry entry = {{0}}; git_status_list *statuslist; const git_status_entry *status; - git_oid zero_id = {0}; + git_oid zero_id = {{0}}; entry.mode = 0100644; entry.path = "modified_file"; @@ -956,6 +957,7 @@ void test_status_worktree__update_stat_cache_0(void) git_status_options opts = GIT_STATUS_OPTIONS_INIT; git_status_list *status; git_diff_perfdata perf = GIT_DIFF_PERFDATA_INIT; + git_index *index; opts.flags = GIT_STATUS_OPT_DEFAULTS; @@ -967,6 +969,10 @@ void test_status_worktree__update_stat_cache_0(void) git_status_list_free(status); + /* tick the index so we avoid recalculating racily-clean entries */ + cl_git_pass(git_repository_index__weakptr(&index, repo)); + tick_index(index); + opts.flags |= GIT_STATUS_OPT_UPDATE_INDEX; cl_git_pass(git_status_list_new(&status, repo, &opts)); diff --git a/tests/stress/diff.c b/tests/stress/diff.c index 0dda44d3017..a3ba4fab3ce 100644 --- a/tests/stress/diff.c +++ b/tests/stress/diff.c @@ -37,7 +37,7 @@ static void test_with_many(int expected_new) memset(&exp, 0, sizeof(exp)); cl_git_pass(git_diff_foreach( - diff, diff_file_cb, NULL, NULL, &exp)); + diff, diff_file_cb, NULL, NULL, NULL, &exp)); cl_assert_equal_i(1, exp.file_status[GIT_DELTA_DELETED]); cl_assert_equal_i(expected_new + 1, exp.file_status[GIT_DELTA_ADDED]); cl_assert_equal_i(expected_new + 2, exp.files); @@ -47,7 +47,7 @@ static void test_with_many(int expected_new) memset(&exp, 0, sizeof(exp)); cl_git_pass(git_diff_foreach( - diff, diff_file_cb, NULL, NULL, &exp)); + diff, diff_file_cb, NULL, NULL, NULL, &exp)); cl_assert_equal_i(1, exp.file_status[GIT_DELTA_RENAMED]); cl_assert_equal_i(expected_new, exp.file_status[GIT_DELTA_ADDED]); cl_assert_equal_i(expected_new + 1, exp.files); @@ -63,7 +63,7 @@ static void test_with_many(int expected_new) memset(&exp, 0, sizeof(exp)); cl_git_pass(git_diff_foreach( - diff, diff_file_cb, NULL, NULL, &exp)); + diff, diff_file_cb, NULL, NULL, NULL, &exp)); cl_assert_equal_i(1, exp.file_status[GIT_DELTA_DELETED]); cl_assert_equal_i(expected_new + 1, exp.file_status[GIT_DELTA_ADDED]); cl_assert_equal_i(expected_new + 2, exp.files); @@ -73,7 +73,7 @@ static void test_with_many(int expected_new) memset(&exp, 0, sizeof(exp)); cl_git_pass(git_diff_foreach( - diff, diff_file_cb, NULL, NULL, &exp)); + diff, diff_file_cb, NULL, NULL, NULL, &exp)); cl_assert_equal_i(1, exp.file_status[GIT_DELTA_RENAMED]); cl_assert_equal_i(expected_new, exp.file_status[GIT_DELTA_ADDED]); cl_assert_equal_i(expected_new + 1, exp.files);